¿Es posible canalizar comandos vim a vim?


18

Quiero ejecutar el siguiente shell.

wea-this is the end of the second word | vim j
exit 0

Lo que esperaba que canalizara las pulsaciones de teclas w(avanzar una palabra) luego e(final de la palabra) luego a(agregar) luego -this is the end of the second word(texto) al documento Vim nombrado jque ya tiene palabras.

El siguiente error ocurrió cuando ejecuté el script de shell.

/root/bin/tt.sh: line 1: wea-this: command not found
Vim: Warning: Input is not from a terminal

Estoy ejecutando Ubuntu 14.04. Se apreciarán dos tipos de respuestas:

  1. Cómo usar tuberías para lograr este resultado deseado.
  2. Otro método por el cual puedo usar "comandos Vim" (no comandos ed o sed) para editar un documento de texto desde un script de shell.

1
El |personaje canaliza la salida de un comando a otro. wea-thisNo es un comando. La tubería tampoco se puede utilizar para lograr lo que está buscando hacer; hará que el stdin de Vim sea la aplicación de la mano izquierda, no el teclado. Si usted desea conseguir la entrada estándar en un búfer en vim, comenzar con un signo menos para el nombre del archivo: echo Hello, world! | vim -.
dash-tom-bang

Respuestas:


15

Para insertar la cadena "hello"en la primera línea del archivo j, puede escribir en su shell el siguiente comando:

vim +"1 | put! ='hello'" j

  • :1 mueve el cursor a la primera línea del búfer
  • :put! ='hello' pega la cadena "hola" sobre la línea actual

Para insertar la cadena "hello"y luego guardar y salir del archivo:

vim +"1 | put! ='hello' | x" j

Lo mismo que antes, acabamos de agregar el comando Ex :xque guarda y cierra.

De manera más general, puede ejecutar cualquier secuencia de comandos Ex en un archivo, desde un shell interactivo o desde un script bash, como este:

vim +'Ex command1 | Ex command2 | ...' file

Si tiene muchos comandos Ex, puede escribirlos todos dentro de un archivo dedicado (llamado, por ejemplo myExCommands.vim), un comando por línea y luego desde el shell o un script puede obtenerlo (con el comando Ex :sourceo la versión corta :so) Me gusta esto:

vim +'so myExCommands.vim' file

Editar

Veo que has editado tu pregunta.
Creo que la respuesta anterior aún se aplica, porque puedes ejecutar cualquier comando normal desde el modo Ex con los comandos Ex :normaly :execute.

Por ejemplo, digamos que quieres:

  • mueve el cursor en la primera línea del búfer ( 1G)
  • mueva el cursor al primer carácter que no sea un espacio en blanco en la línea ( _)
  • mueva el cursor una palabra hacia adelante ( w)
  • mueve el cursor al final de la nueva palabra ( e)
  • ir al modo insertar después del carácter debajo del cursor ( a)
  • inserta la cuerda hello
  • guardar y salir ( :x)

Para hacer esto en el archivo j, escriba desde el shell:

vim +"execute 'normal! 1G_weahello' | x" j

Para más información, ver:

:help +cmd
:help :normal
:help :execute

No pude aclarar completamente mi objetivo. Quiero poder usar comandos vims, como w para avanzar una palabra y tal. Editaré mi pregunta para corregir.
Jason Basanese

@JasonBasanese He editado mi respuesta, ¿hago los comandos Ex :normaly :executehago lo que quieres?
saginaw

9

Aquí hay una forma en que puede usar comandos en modo normal, en lugar de solo comandos ex, para editar una secuencia presentada a Vim desde stdin. Este no es un ejemplo muy útil, pero ilustra las técnicas involucradas. Se supone que su caparazón es bash.

echo "The brown fox jumped." | vim -s <(printf 'wcwred\e:wq! foo\n') -

Al -final le dice a Vim que lea el texto (no los comandos) de stdin. El -sle dice a Vim que ejecute las pulsaciones del archivo especificado. En este caso, el archivo es el resultado de una sustitución de proceso bash. El <(...)se reemplaza por el nombre de una tubería con nombre. La salida de la tubería es la salida del comando entre paréntesis. El wcwred\emueve el cursor una palabra y cambia la siguiente palabra a red. El :wq! foo\nguarda el resultado en el archivo fooincluso si ese archivo ya existe. El resultado final es un archivo llamado que foocontiene el textoThe red fox jumped.

Para obtener más información sobre algunos de esos temas, consulte

:help -file
:help -s

Consulte también la Process Substitutionsección de la bash(1)página del manual.


Añadido a mi ~ / .zshrc: vimx () { vi -s <(echo "$1"':wq') "$2" &> /dev/null; }. Ahora lo que pueda vimx 'iThe brow fox jumped.\e' foo; vimx 'wcwred\efjdwiclimbed\e' foo; cat foo. ¡Ordenado!
Leonard Pauli

4

He encontrado que el método de tomar la salida de un programa como redirigido desde sub-shell es muy fácil:

vim <( program )

Ejemplo:

 vim <( grep -nH  hello  myFile.cpp )
 vim <( find . -name '*.cpp' -exec grep -nH code_expr {} \+ )

4

Tenía exactamente el mismo deseo que tú: quería escribir comandos vim normales y hacer que editaran un flujo de canalización. Me decepcionó la dificultad de usar vim normal de esta manera (¡tantas banderas!), Como lo proporcionan las opciones de vim predeterminadas.

Por lo tanto, escribí un pequeño contenedor en vim para hacerlo: https://github.com/MilesCranmer/vim-stream/ . Se llama vims.

El corazón del contenedor es el siguiente comando:

vim - -nes "${vim_cmds[@]}" -c ':q!' | tail -n +2

Usando esto, con la generación de comandos que hago, resulta ser bastante conciso, y debido a que vim es un editor modal, hice vimsun editor de flujo modal. Hay tres modos principales que son útiles para la mentalidad de edición de canalización:

[-t|--turn-off-mode] - (Default mode)
                       Every string is a vim command line, e.g., '%g/foo/d' deletes
                       all lines with foo.
[-e|--exe-mode] -      Translated to '%g/$1/exe "norm $2"', see examples below
[-s|--simple-mode] -   Like exe-mode, but runs on 1st line only

Ver este:

$ echo "Hello World" | vims -s "ea Beautiful"
Hello Beautiful World

Entonces, eva al final de Hello, luego acomienza a agregar

Algo más elegante, en modo exe, para comentar líneas que contienen my_bad_vary eliminar la línea anterior.

cat my_script.cpp | vims -e 'my_bad_var' 'I//\<esc>kdd'

Lo que se traduce en vims '%g/my_bad_var/exe "norm I//\<esc>kdd"': el Iser el comando para comenzar a insertar al comienzo de la línea y //la secuencia de comentarios. \<esc>kddpresiona la tecla de escape, sube una línea y luego la borra.

Tengo 11 ejemplos totales en el repositorio, te animo a que los revises. Una vez más, esto se ejecuta sobre vim, es solo una forma de hacer que vim se parezca más a sed para la entrada de flujo (¡pero preservando todas sus queridas macros vim!)


3

Esta es una pregunta bastante antigua, pero sentí que valía la pena contribuir a que si su distribución / SO dada tiene acceso moreutils, entonces puede instalarla y simplemente usarla vipecomo una adición estándar a vim:

echo foo | vipe # Now you can edit "foo" to be "bar"!

moreutils¡también es muy útil para sus otras herramientas, y las recomiendo si eres un usuario serio de la línea de comandos! :) Eche un vistazo a la introducción del autor (enlace anterior) para obtener más detalles.

moreutilsdebería estar generalmente disponible para la mayoría de las distribuciones * nix-like a través de un administrador de paquetes y a través de Homebrew en Mac . Por ejemplo...

# Arch Linux and MSYS2 (more below) as part of the `community` repo
pacman -Sy moreutils


# Mac OS and Homebrew
brew install moreutils

moreutilstambién es parte del repositorio de paquetes MSYS2 , por lo que técnicamente también puede usarlo en Windows. :)

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.