¿Cómo me muevo verticalmente hasta llegar a un personaje que no es un espacio en blanco?


27

En un archivo muy largo con código sangrado (con precisión), puede ser útil moverse directamente a una línea de texto encima o debajo del cursor que delimita la sangría.

(Una forma de hacer esto podría ser a través de la foldmethod guión, doblando el nivel actual de sangría, que colapsa las líneas que delimitan el nivel de sangría a ser sólo una jo klejos del cursor. Instancias Sin embargo, he encontrado donde plegado guión no tiene he podido trabajar en la sangría que me interesa)

Aquí hay un ejemplo, con el cursor marcado por el guión bajo _(en la segunda columna de caracteres entre las definiciones de class Bazzy class Qux), pero imagine que el número de párrafos o líneas dentro de la modules es desconocido o variable:

module Foo
  # lots of code...
end

module Bar
  class Baz
    # ...
  end

  class Bazz
    # lots of code...
  end
 _
  class Qux
    # ...
  end

  class Quux
    # lots of code...
  end
end

... ¿cómo podría navegar rápidamente hacia la oparte module Barsuperior del cursor o la nparte endinferior del cursor en la última línea? Tenga en cuenta que la columna vertical contiene espacios en blanco, pero tampoco caracteres en la segunda columna entre las classdefiniciones.


2
relacionado: "Pasar a la línea siguiente / anterior con la misma sangría" en Vim Tips Wiki vim.wikia.com/wiki/Move_to_next/…
alxndr

Presionando gy luego la tecla de dirección podría evitar pestañas y moverse a través de las líneas
SibiCoder

1
La solución en el enlace de @ alxndr funciona bien, excepto en el caso de que el espacio en blanco esté mal mantenido (por ejemplo, hay líneas aleatorias que solo tienen espacios en blanco) y desea ignorar el espacio en blanco. La solución de Superjer a continuación es mejor si a uno le preocupa ese caso.
nukeguy

Respuestas:


9

¿Qué tal esta función?

function FloatUp()
    while line(".") > 1
                \ && (strlen(getline(".")) < col(".")
                \ || getline(".")[col(".") - 1] =~ '\s')
        norm k
    endwhile
endfunction

Podría nnoremap gU :call FloatUp()<CR>( gUpara "subir"), y luego invocar con gU.

Aquí hay una explicación:

  • El código mueve repetidamente el cursor hacia arriba (con norm k) mientras se cumpla la whilecondición.
  • La whilecondición se cumple si esta no es la primera línea ( line(".") > 1) y
    • esta línea es demasiado corta (probablemente vacía); o
    • El carácter de la línea actual ( getline(".")) en la columna actual ( [col(".") - 1]) es un espacio en blanco ( =~ '\s'es decir, coincide con el patrón de espacios en blanco).

1
Esto parece funcionar perfectamente (y rápidamente), y también se modifica fácilmente en una FloatDownfunción. En mi .vimrc va, ¡gracias! github.com/alxndr/dotfiles/commit/0e25a302
alxndr

1
Acabo de descubrir que esta solución no funciona en modo visual (comportamiento ligeramente diferente dependiendo de qué modo visual, se mantendrá en la misma posición o se moverá solo una línea). ¿Alguna sugerencia sobre lo que está pasando allí?
alxndr

13

Me gusta usar la búsqueda de estas cosas, porque las expresiones regulares de Vim tienen una cantidad increíble de cosas que puede buscar, como números de columna virtuales específicos, en este caso:

nnoremap cd /\%<C-R>=virtcol(".")<CR>v\S<CR>

nnoremap cu ?\%<C-R>=virtcol(".")<CR>v\S<CR>

Use cdpara bajar y cupara subir. Estoy pensando "columna arriba" y "columna abajo" aquí. Estoy casi 100% seguro de que estas no son operaciones por defecto. O elige tus propios mapeos.

Esto debería funcionar si está usando pestañas o espacios o ambos.


1
Tengo problemas para analizar esos comandos. ¿Te importaría expandirlos un poco?
davidlowryduda

1
/ o? para buscar hacia abajo o hacia arriba, \% xv limita la búsqueda al número de columna virtual 'x', la 'x' en este caso es '<CR> = virtcol (".") <CR>' que ejecuta el comando virtcol e inserta el número de columna virtual en el que se encuentra el cursor en la expresión, \ S significa cualquier carácter que no sea un espacio en blanco.
Chad

1
Gracias por explicar Chad. Solo agregaré que <CR> en el modo Insertar o en el modo de línea de comandos toma el contenido de un registro. El =registro es el registro de expresión que evalúa una expresión en su lugar. Es muy útil, si no un poco raro.
superjer

1
Una desventaja de este enfoque es que si tiene resaltado de búsqueda activado, encontrará que todos los caracteres en la columna vertical del cursor ahora están resaltados después de "subir columna" o "bajar columna".
alxndr

3
Si desea proteger su búsqueda existente, puede anteponer :let searchbak=@/<CR>y agregar :let @/=searchbak<CR>. Pero en este punto se está volviendo algo largo e inaccesible y quizás debería ser una función.
superjer

7

Puede usar el complemento JumpToVerticalOccurrence (predeterminado asignado a ]|y [|). Hay pocos otros como el ]V{char}que funciona f, pero verticalmente. Por supuesto, puede reasignarlos según sea necesario.


Si no desea utilizar plugins, es posible que trate de usar :searchcon virtcol(.), por ejemplo:

:call search('\%' . virtcol('.') . 'v\S', 'bW')

dónde:

  • virtcol('.') te da la columna actual,
  • \S significa no espacio en blanco
  • bW es para buscar hacia atrás

Consulte :help searchpara obtener más información.

Para que sea más fácil de usar, puede asignarlo, por ejemplo:

:map <C-k> :call search('\%' . virtcol('.') . 'v\S', 'bW')<CR>
:map <C-j> :call search('\%' . virtcol('.') . 'v\S', 'W')<CR>

Alternativamente, si el código contiene soportes, uso %para saltar entre ellas a juego (por ejemplo {, }, [, ], etc.) o el uso párrafo entero salta ( {, }con Shiftsi es necesario).


Enlaces / fuentes:


De :h search(): wmedios wrap around the end of the filey Wmedios don't wrap around the end of the file. ¿Pero por qué los pusiste juntos en el segundo :map?
Jair López

@JairLopez Correcto, wno debería estar allí, así que lo eliminé , gracias. Probablemente estaba confundido por el significado de las teclas de movimiento.
kenorb

3

Utilizo una versión modificada del complemento vim-indent-object para proporcionar este comportamiento. Mis modificaciones se pueden ver aquí .

Esto me permite mapear [ipara ir al comienzo del nivel de sangría actual y ]ial final.


2

No es exactamente lo que usted pidió, porque no es un movimiento vertical, pero algo que es similar, rápido y puede ser que sea lo suficientemente bueno para que usted se está moviendo hacia atrás los párrafos 2: {{. Esto lo llevará a la línea justo antes module Bar.


2
Imagine que hay un número desconocido de líneas y / o párrafos entre el cursor y su modulelínea de nivel superior . (En concreto, esta situación surgió cuando navegaba recientemente código de terceros varios miles de líneas de largo, con muesca precisa, pero no hay líneas vacías, y tratando de encontrar el contexto exterior de la definición de un módulo.)
alxndr

Saltar por párrafos es mi forma preferida de moverme, pero no era una opción: todo el archivo era un "párrafo".
alxndr


1

Yo uso mi propio complemento move_until_char_changes.vim para eso.

Lo mapeo a gKy gJ.

Saltará sobre muchas líneas con el mismo carácter en la columna actual (no solo espacios en blanco), lo que puede ser útil en archivos de registro o volcados de SQL con cadenas repetidas.

Por defecto, primero mueve una línea, antes de seleccionar el carácter "buscar".

Funciona en modo Visual siempre que no intente usarlo dos veces y no esté en modo Visual en línea o en bloque ... (¡arreglos bienvenidos!)


1

Como no lo veo aquí como una respuesta ( edit solo notó que superjer mencionó algo muy similar). Puedes simplemente el / o? buscar.

Por ejemplo, puede buscar hacia abajo un carácter que no sea un espacio en blanco en la segunda columna de esta manera:

/\%2v\S

El desglose es:

/    "search downward (use ? for upward movement)
\%2v "for the following char in the 2nd virtual column
\S   "any non white space character

Luego puede usar los operadores normales para repetir la búsqueda.

Para más información sobre el tema ver :help \%cy :help \%v.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.