È possibile reindirizzare i comandi di VIM a VIM?


18

Voglio eseguire la seguente shell.

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

Il che avevo sperato avrebbe convogliato i tasti premuti w(spostati in avanti di una parola), quindi e(fine della parola), quindi a(accodamento), quindi -this is the end of the second word(testo) al documento Vim chiamato jche contiene già delle parole.

Il seguente errore si è verificato quando ho eseguito lo script della shell.

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

Sto eseguendo Ubuntu 14.04. Saranno apprezzati due tipi di risposte:

  1. Come utilizzare le tubazioni per ottenere questo risultato desiderato.
  2. Un altro metodo con il quale posso usare i "comandi Vim" (non i comandi ed o sed) per modificare un documento di testo da uno script di shell.

1
Il |personaggio convoglia l'output di un comando verso un altro. wea-thisnon è un comando. Le tubazioni non possono essere utilizzate neanche per ottenere ciò che stai cercando di fare; farà sì che lo stdin di Vim sia l'applicazione per la mano sinistra, non la tastiera. Se si desidera ottenere standard input in un buffer in vim, avviarlo con un meno per il nome del file: echo Hello, world! | vim -.
dash-tom-bang

Risposte:


15

Per inserire la stringa "hello"sulla prima riga del file j, è possibile digitare nella shell il seguente comando:

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

  • :1 sposta il cursore sulla prima riga del buffer
  • :put! ='hello' incolla la stringa "ciao" sopra la riga corrente

Per inserire la stringa "hello"e quindi salvare ed uscire dal file:

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

La stessa cosa di prima, abbiamo appena aggiunto il comando Ex :xche salva ed esce.

Più in generale è possibile eseguire qualsiasi sequenza di comandi Ex su un file, da una shell interattiva o da uno script bash, in questo modo:

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

Se hai molti comandi Ex, puoi scriverli tutti all'interno di un file dedicato (chiamato ad esempio myExCommands.vim), un comando per riga, e poi dalla shell o da uno script potresti generarlo (con il comando Ex :sourceo la versione breve :so) come questo:

vim +'so myExCommands.vim' file

modificare

Vedo che hai modificato la tua domanda.
Penso che la risposta precedente sia ancora valida, perché puoi eseguire qualsiasi comando normale dalla modalità Ex con i comandi Ex :normale :execute.

Ad esempio, supponiamo che tu voglia:

  • sposta il cursore sulla prima riga del buffer ( 1G)
  • sposta il cursore sul primo carattere non bianco sulla riga ( _)
  • sposta il cursore di una parola in avanti ( w)
  • sposta il cursore alla fine della nuova parola ( e)
  • entra in modalità inserimento dopo il carattere sotto il cursore ( a)
  • inserire la stringa hello
  • save and quit ( :x)

Per fare questo sul file j, digitare dalla shell:

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

Per ulteriori informazioni, vedere:

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

Non sono riuscito a chiarire completamente il mio obiettivo. Voglio essere in grado di usare i comandi di vims, come w per andare avanti di una parola e simili. Modificherò la mia domanda per correggere.
Jason Basanese,

@JasonBasanese Ho modificato la mia risposta, fai i comandi Ex :normale :executefai quello che vuoi?
Saginaw,

9

Ecco un modo in cui puoi usare i comandi in modalità normale, piuttosto che solo i comandi ex, per modificare uno stream presentato a Vim da stdin. Questo non è un esempio molto utile, ma illustra le tecniche coinvolte. Presuppone che la tua shell sia bash.

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

Alla -fine dice a Vim di leggere il testo (non i comandi) dallo stdin. Il -sdice a Vim di eseguire i tasti dal file specificato. In questo caso, il file è l'output di una sostituzione del processo bash. Il <(...)viene sostituito dal nome di una pipe denominata. L'output del pipe è l'output del comando tra parentesi. Le wcwred\esposta il cursore di una parola e modifiche che accanto parola red. Il :wq! foo\nsalva il risultato al file fooanche se il file esiste già. Il risultato finale è un file denominato foocontenente il testoThe red fox jumped.

Per ulteriori informazioni su alcuni di questi argomenti, vedere

:help -file
:help -s

Vedi anche la Process Substitutionsezione della bash(1)pagina man.


Aggiunto al mio ~ / .zshrc: vimx () { vi -s <(echo "$1"':wq') "$2" &> /dev/null; }. Adesso posso vimx 'iThe brow fox jumped.\e' foo; vimx 'wcwred\efjdwiclimbed\e' foo; cat foo. ! Neat
Leonard Pauli,

4

Ho trovato molto semplice il metodo di prendere l'output di un programma reindirizzato dalla sotto-shell:

vim <( program )

Esempio:

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

4

Avevo lo stesso tuo desiderio: volevo scrivere normali comandi vim e fare in modo che quelli modificassero un flusso di pipeline. Sono stato deluso dalla difficoltà di usare Vim normale in questo modo (così tante bandiere!), Come fornito dalle opzioni di vim predefinite.

Pertanto, ho scritto un piccolo wrapper su vim per farlo: https://github.com/MilesCranmer/vim-stream/ . Si chiama vims.

Il cuore del wrapper è il seguente comando:

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

Usando questo, con la generazione del comando che faccio, risulta abbastanza conciso, e poiché vim è un editor modale, ho creato vimsun editor di flusso modale. Esistono tre modalità principali utili per la mentalità di modifica della pipeline:

[-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

Guarda questo:

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

Quindi, eva fino alla fine Hello, quindi ainizia ad aggiungere.

Qualcosa di più elaborato, in modalità exe, per commentare le righe contenenti my_bad_vared eliminare la riga precedente.

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

Il che si traduce in vims '%g/my_bad_var/exe "norm I//\<esc>kdd"': l' Iessere il comando per iniziare l'inserimento all'inizio della riga e //la sequenza di commenti. \<esc>kddpreme il tasto Esc, si sposta su una riga, quindi elimina la riga.

Ho 11 esempi totali sul repository, ti incoraggio a verificarli. Ancora una volta, questo è in esecuzione su vim, è solo un modo per rendere vim più simile a sed per l'input di streaming (ma preservando tutte le tue amate macro di vim!)


3

Questa è una domanda abbastanza vecchia, ma ho ritenuto che valesse la pena contribuire al fatto che se la tua data distribuzione / sistema operativo ha accesso moreutils, puoi installarla e utilizzarla semplicemente vipecome aggiunta standard a vim:

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

moreutilsè super utile anche per gli altri suoi strumenti e li consiglio vivamente se sei un utente serio della riga di comando! :) Dai un'occhiata all'introduzione dell'autore (link precedente) per maggiori dettagli.

moreutilsdovrebbe essere generalmente disponibile per la maggior parte delle distribuzioni simili a * nix tramite un gestore di pacchetti e tramite Homebrew su Mac . Per esempio...

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


# Mac OS and Homebrew
brew install moreutils

moreutilsfa anche parte del repository di pacchetti MSYS2 , quindi è possibile utilizzarlo tecnicamente anche su Windows. :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.