Як викликати редактор VIM і вихідну трубу в Bash


34

Іноді мені потрібно написати текст, а потім передати цей текст в іншу команду. Мій звичайний робочий процес йде приблизно так:

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

Я вважаю це громіздким і прагну навчитись баш сценаріїв, я хотів би зробити процес набагато простішим, написавши команду, яка запускає редактор і коли редактор закриває трубку вихід редактора в stdout. Тоді я зможу виконати команду як quickedit | pandoc -o file.pdf.

Я не впевнений, як це буде працювати. Я вже написав функцію для автоматизації цього, дотримуючись точного робочого процесу вище, а також деяких доповнень. Він генерує випадковий рядок, який виконує функцію імені файлу, і передає його vim, коли функція викликається. Коли користувач виходить з vim, зберігаючи файл, функція друкує файл на консолі, а потім видаляє файл.

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

Проблема, з якою я незабаром стикався, полягає в тому, що коли я роблю щось на кшталт quickedit | commandvim, сам не може бути використаний як редактор, оскільки весь вихід обмежений на трубу.

Мені цікаво, чи є якісь вирішення цього питання, щоб я міг передати висновок своєї quickeditфункції. Неоптимальна альтернатива - запустити окремий редактор, сказати піднесений текст, але я дуже хочу залишитися в терміналі.


Зсередини vim, видайте команду :w !pandoc -o file.pdf? (Примітка: простір між wі !є істотним.)
John1024

Гаразд - це чудово. Я не знав, що ви можете передати vim вихід із самого vim. Це служить моїм цілям, але для моїх подальших знань чи можна вирішити мою проблему саме так, як я мав намір її вирішити?
theideasmith

Чи можете ви розмістити свою функцію? Що ви маєте на увазі під час розмови про проблему, з якою ви незабаром стикалися (другий останній абзац)? Я цього не розумію.
Лукас

5
Як сторону, ви повинні використовувати,mktemp а не винаходити це невпевнено.
Wildcard

Як новий користувач bash, які небезпеки для безпеки відновлюють mktemp?
theideasmith

Відповіді:


42

vipe це програма для редагування трубопроводів:

command1 | vipe | command2

Ви отримуєте редактор з повним виходом command1, і коли ви виходите, вміст передається command2в канал.

У цьому випадку немає command1. Отже, ви можете зробити:

: | vipe | pandoc -o foo.pdf

Або:

vipe <&- | pandoc -o foo.pdf

vipeпідбирає змінні EDITORта VISUALзмінні, тож ви можете використовувати їх, щоб відкрити Vim.

Якщо ви не встановили його, vipeє в moreutilsкомплекті; sudo apt-get install moreutilsабо будь-який еквівалент вашого аромату.


1
Для користувачів Mac, які приїхали сюди: moreutilsдоступний на домашній мові.
vergenzt

Для користувачів FreeBSD: moreutilsможна встановити через pkg (8) .
Матеуш Піотровський

20

Це можна зробити з Vim:

:w !pandoc -o file.pdf

Або навіть записати буфер у складний конвеєр:

:w !grep pattern | somecommand > file.txt

І тоді ви можете вийти з Vim без збереження:

:q!

Однак, враховуючи ваш конкретний випадок використання, можливо, краще рішення буде використовувати viяк редактор вашого командного рядка. Припустимо, що ви використовуєте bash:

set -o vi

Це встановлює ваші зв'язки клавіш до vi. Таким чином , ви можете редагувати свої команди прямо з командного рядка з основними viприв'язками, натиснувши <Esc>і потім ввести viкоманди , такі як x, cwі т.д. (Ви можете повернутися в режимі вставки, натиснувши i.)

Ще краще і відповідніше цьому питанню, ви можете відкрити Vim, щоб створити вміст вашого командного рядка безпосередньо. Просто введіть <Esc>vі ви отримаєте порожній буфер Vim. Коли ви зберігаєте та виходите, це команда у вашому командному рядку, і вона негайно виконується. Це набагато гнучкіше, ніж редагування в командному рядку безпосередньо, оскільки ви можете написати цілий міні-скрипт, якщо хочете.


Наприклад, якщо ви хочете написати якийсь хитрий текст і передати його в pandoc негайно, ви можете просто ввести:

<Esc>v

Потім відредагуйте буфер Vim, поки у вас є щось на зразок:

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

Потім збережіть і вийдіть (з :x), і вся справа буде виконуватися як команда оболонки.

Він також буде доступний в історії команд вашої оболонки.


1
Якщо ви віддаєте перевагу зберігати прив’язки клавіш Emacs, ви все одно можете використовувати Vim для редагування командних рядків, встановивши EDITORзмінну середовища vimта натиснувши її, Ctrl-Xпісля чого Ctrl-Eредагуючи командний рядок.
Ентоні Г - справедливість для Моніки

18

Запуск в трубопровід

Спробуйте:

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

Ключовим є те, що для vimнормального використання vimпотрібно stdout, щоб бути терміналом. Ми це робимо за допомогою переадресації >/dev/tty.

З метою безпеки я поміщаю тимчасовий файл у домашній каталог користувача. Докладніше про це дивіться у Грегові запитання 062 . Це виключає необхідність використання незрозумілого імені файлу.

Приклад:

Коли vimвідкриється, я набираю This function succeeded.і зберігаю файл. Результат на екрані виглядає так:

$ quickedit | grep succeeded
This function succeeded.

Навіть незважаючи на те, що вихід quickeditперенаправлений на трубопровід, він vimвсе ще працює нормально, тому що ми дали йому прямий доступ до нього /dev/tty.

Запуск програми зсередини vim

Як я вже згадував у коментарях, vim може передавати файл команді. Наприклад, зсередини vim, видайте команду :w !pandoc -o file.pdf(Примітка: пробіл між w і! Є важливим).


2
Гарна відповідь. Це безпосередньо стосується питання користувача та пропонує швидке та елегантне рішення: перенаправити vim на / dev / tty! Просто!
Майк S

Я використовую Zsh; trap '...' exitне працює, але, trap '...' EXITздається, працює. Я не знаю багато про лову, але мій загальний підхід для тимчасових файлів полягає у використанні mktmp [--suffix=...]. Крім того, vim <outfile> -c '...' >/dev/ttyпрацює як звичайно до завантаження файлу, після чого виконує заданий ланцюжок команд, включаючи, :wqякщо ви хочете пропустити етап редагування. Я також використовував set | grep -a EXITі знаходив signals=(EXIT ... DEBUG).
Джон П

5

Переконайтеся, що vimвін встановлений як ваш редактор за замовчуванням (наприклад, export EDITOR=vimу вашому .bash_profileабо .bashrc. Потім, у будь-якому запиті, ви можете ввести Ctrl- Xа потім Ctrl- E. Це відкриє ваш поточний командний рядок у налаштованому редакторі (наприклад vim). Зробіть свої зміни, збережіть і вихід, і команда буде виконуватися так, ніби ви її ввели в командному рядку, включаючи трубопроводи тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.