Jak wywołać edytor vim i wyjście potoku do bash

34

Czasami muszę napisać tekst, a następnie potokować ten tekst do innego polecenia. Mój zwykły przepływ pracy wygląda mniej więcej tak:

vim
# I edit and save my file as file.txt
cat file.txt | pandoc -o file.pdf # pandoc is an example 
rm file.txt

Uważam to za kłopotliwe i staram się nauczyć pisania skryptów bashowych. Chciałbym uprościć ten proces, pisząc polecenie, które uruchamia edytor i kiedy edytor zamyka potok wyjściowy edytora na standardowe wyjście. Wtedy będę mógł uruchomić polecenie jako quickedit | pandoc -o file.pdf.

Nie jestem pewien, jak to by działało. Napisałem już funkcję automatyzującą to, postępując zgodnie z powyższym dokładnym przepływem pracy i kilkoma dodatkami. Generuje losowy ciąg znaków, który działa jak nazwa pliku, i przekazuje go do vim po wywołaniu funkcji. Gdy użytkownik wyjdzie z vima poprzez zapisanie pliku, funkcja drukuje plik na konsoli, a następnie usuwa plik.

function quickedit {
    filename="$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32)"
    vim $filename
    cat $filename
    rm $filename
}
# The problem:
# => Vim: Warning: Output is not to a terminal

Problem, z którym wkrótce się spotkałem, polega na tym, że kiedy robię coś takiego jak quickedit | commandsam vim, nie można go używać jako edytora, ponieważ wszystkie dane wyjściowe są ograniczone do potoku.

Zastanawiam się, czy są jakieś obejścia tego, aby móc przesyłać dane wyjściowe mojej quickeditfunkcji. Nieoptymalna alternatywa to uruchomienie osobnego edytora, powiedzmy wysublimowanego tekstu, ale naprawdę chcę pozostać w terminalu.

theideasmith
źródło
Z poziomu vima wydać polecenie :w !pandoc -o file.pdf? (Uwaga: odstęp między wi !jest niezbędny.)
John1024
Ok - to wspaniale. Nie wiedziałem, że możesz wyprowadzić wyjście vima z samego vima. Służy to moim celom, ale czy dla mojej przyszłej wiedzy możliwe jest rozwiązanie mojego problemu dokładnie tak, jak zamierzałem go rozwiązać?
theideasmith
Czy możesz opublikować swoją funkcję? Co masz na myśli, gdy mówisz o problemie, który wkrótce napotkałeś (akapit drugi od ostatniego)? Nie rozumiem tego
Lucas,
5
Na marginesie, powinieneś raczej używać gomktemp zamiast odkrywać na nowo w niepewny sposób.
Wildcard
Jako nowy użytkownik bash, jakie są zagrożenia bezpieczeństwa związane z ponownym wynalezieniem mktemp?
theideasmith

Odpowiedzi:

42

vipe to program do edycji potoków:

command1 | vipe | command2

Otrzymasz edytor z pełnym wyjściem command1, a kiedy wyjdziesz, zawartość jest przekazywana za command2pośrednictwem potoku.

W tym przypadku nie ma command1. Więc możesz zrobić:

: | vipe | pandoc -o foo.pdf

Lub:

vipe <&- | pandoc -o foo.pdf

vipezbiera zmienne EDITORi VISUAL, więc możesz użyć ich, aby otworzyć Vima.

Jeśli nie masz go zainstalowanego, vipejest dostępny w moreutilspakiecie; sudo apt-get install moreutilslub cokolwiek jest ekwiwalentem twojego smaku.

muru
źródło
1
Dla użytkowników komputerów Mac, którzy tu przybyli: moreutilsjest dostępny w Homebrew.
vergenzt
Dla użytkowników FreeBSD: moreutilsjest dostępny do zainstalowania za pomocą pkg (8) .
Mateusz Piotrowski
20

Możesz to zrobić z poziomu Vima:

:w !pandoc -o file.pdf

Lub nawet zapisz bufor w złożonym potoku:

:w !grep pattern | somecommand > file.txt

Następnie możesz wyjść z Vima bez zapisywania:

:q!

Jednak biorąc pod uwagę konkretny przypadek użycia, prawdopodobnie istnieje lepsze rozwiązanie, viponieważ jest ono edytorem wiersza poleceń. Zakładając, że używasz bash:

set -o vi

To ustawia twoje skróty klawiszowe na vi. Więc można edytować polecenia tuż przy linii poleceń z podstawowych viskróty klawiszowe, naciskając <Esc>, a następnie wpisanie vipolecenia, takie jak x, cwitd (można wrócić w trybie wstawiania naciskając i).

Jeszcze lepiej i bardziej odpowiednie dla tego pytania, możesz otworzyć Vima, aby bezpośrednio utworzyć treść wiersza poleceń. Po prostu wpisz, <Esc>va otrzymasz pusty bufor Vima. Podczas zapisywania i zamykania jest to polecenie w wierszu polecenia i jest ono natychmiast uruchamiane. Jest to o wiele bardziej elastyczne niż edytowanie bezpośrednio w wierszu poleceń, ponieważ możesz napisać cały mini-skrypt, jeśli chcesz.


Na przykład, jeśli chcesz napisać jakiś trudny tekst i natychmiast wstawić go do pandoc, możesz po prostu wpisać:

<Esc>v

Następnie edytuj bufor Vima, aż będziesz mieć coś takiego:

cat <<EOF | pandoc -o file.pdf
stuff for pandoc
more stuff for pandoc
EOF

Następnie zapisz i wyjdź (z :x), a całość zostanie uruchomiona jako polecenie powłoki.

Będzie również dostępny w historii poleceń twojej powłoki.

Dzika karta
źródło
1
Jeśli wolisz zachować powiązania klawiszy Emacsa, nadal możesz używać Vima do edycji wierszy poleceń, ustawiając EDITORzmienną środowiskową na vimi naciskając, Ctrl-Xa następnie Ctrl-Eedytując wiersz poleceń.
Anthony G - sprawiedliwość dla Moniki
18

Uruchamianie w przygotowaniu

Próbować:

quickedit() (  trap 'rm ~/temp$$' exit; vim ~/temp$$ >/dev/tty; cat ~/temp$$ )

Kluczem jest to, że aby móc vimnormalnie korzystać , vimmusi być stdout jako terminal. Osiągamy to tutaj dzięki przekierowaniu >/dev/tty.

Ze względów bezpieczeństwa umieszczam plik tymczasowy w katalogu osobistym użytkownika. Więcej informacji na ten temat znajduje się w pytaniu 062 do Grega . Eliminuje to potrzebę użycia niejasnej nazwy pliku.

Przykład:

Po vimotwarciu wpisuję This function succeeded.i zapisuję plik. Wynik na ekranie wygląda następująco:

$ quickedit | grep succeeded
This function succeeded.

Mimo że dane wyjściowe quickeditsą przekierowywane do potoku, vimnadal działają normalnie, ponieważ daliśmy mu bezpośredni dostęp do /dev/tty.

Uruchamianie programu z poziomu vima

Jak wspomniałem w komentarzach, vim może potokować plik do polecenia. Na przykład z poziomu vima wydaj polecenie :w !pandoc -o file.pdf(uwaga: niezbędna jest spacja między w i!).

John1024
źródło
2
Niezła odpowiedź. Ten odpowiada bezpośrednio na pytanie użytkownika i oferuje szybkie i eleganckie rozwiązanie: przekieruj vima do / dev / tty! Prosty!
Mike S,
Używam Zsh; trap '...' exitzawiesza się, ale trap '...' EXITwydaje się działać. Nie wiem dużo o zalewkowaniu, ale moim ogólnym podejściem do plików tymczasowych jest użycie mktmp [--suffix=...]. Również vim <outfile> -c '...' >/dev/ttydziała normalnie, aż plik zostanie załadowany, a następnie wykonuje dany łańcuch dowodzenia, w tym :wqjeśli chcesz pominąć fazę edycji. Użyłem również set | grep -a EXITi znalazłem signals=(EXIT ... DEBUG).
John P
5

Upewnij się, że vimjest ustawiony jako domyślny edytor (np. export EDITOR=vimW twoim .bash_profilelub .bashrc. Następnie, w dowolnym monicie, możesz wpisać Ctrl- Xa następnie Ctrl- E. Otworzy to twój bieżący wiersz poleceń w skonfigurowanym edytorze (np vim.). Dokonaj edycji, zapisz i zakończ, a polecenie zostanie wykonane tak, jakbyś wpisał je w wierszu poleceń, w tym potoków i tym podobnych.

DopeGhoti
źródło