Можно ли передать команды vim в vim?

18

Я хочу запустить следующую оболочку.

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

Я надеялся, что это будет wнаправлять нажатия клавиш (двигаться вперед по слову), затем e(конец слова), затем a(добавлять), затем -this is the end of the second word(текст) в документ Vim с именем, в jкотором уже есть слова.

Следующая ошибка произошла, когда я запустил скрипт оболочки.

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

Я использую Ubuntu 14.04. Будут оценены два типа ответов:

  1. Как использовать трубопровод для достижения желаемого результата.
  2. Другой метод, с помощью которого я могу использовать «команды Vim» (не команды ed или sed) для редактирования текстового документа из сценария оболочки.
Джейсон Басанезе
источник
1
На |характер трубы вывода одной команды к другой. wea-thisэто не команда. Трубопровод не может быть использован для достижения того, что вы хотите сделать; это приведет к тому, что стандартный ввод Vim будет левой рукой, а не клавиатурой. Если вы хотите , чтобы получить стандартный ввод в буфер в Vim, запустите его с минусом для имени файла: echo Hello, world! | vim -.
dash-tom-bang

Ответы:

15

Чтобы вставить строку "hello"в первую строку файла j, вы можете набрать в своей оболочке следующую команду:

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

  • :1 перемещает курсор на первую строку буфера
  • :put! ='hello' вставляет строку "привет" над текущей строкой

Чтобы вставить строку, "hello"а затем сохранить и выйти из файла:

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

То же самое, что и раньше, мы только что добавили команду Ex, :xкоторая сохраняет и выходит.

В более общем случае вы можете выполнить любую последовательность команд Ex для файла, из интерактивной оболочки или из сценария bash, например:

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

Если у вас много Ex-команд, вы можете написать их все внутри выделенного файла (например myExCommands.vim, по одному), по одной команде на строку, а затем из оболочки или сценария вы можете получить его (с помощью команды Ex :sourceили краткой версии). :so) как это:

vim +'so myExCommands.vim' file

редактировать

Я вижу, вы редактировали свой вопрос.
Я думаю, что предыдущий ответ все еще применим, потому что вы можете выполнить любую обычную команду из режима Ex с помощью команд Ex :normalи :execute.

Например, допустим, вы хотите:

  • переместите курсор на первую строку буфера ( 1G)
  • переместите курсор к первому непробельному символу в строке ( _)
  • переместите курсор на одно слово вперед ( w)
  • переместите курсор в конец нового слова ( e)
  • перейти в режим вставки после символа под курсором ( a)
  • вставить строку hello
  • сохранить и выйти ( :x)

Чтобы сделать это в файле j, введите из оболочки:

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

Для получения дополнительной информации см .:

:help +cmd
:help :normal
:help :execute
Сагино
источник
Я не смог полностью уточнить мою цель. Я хочу иметь возможность использовать команды vims, такие как w, чтобы переместить слово вперед и тому подобное. Я отредактирую свой вопрос, чтобы исправить.
Джейсон Басанезе
@JasonBasanese Я отредактировал свой ответ, делай команды Ex :normalи :executeделай что хочешь?
сагино
9

Вот способ, которым вы можете использовать команды обычного режима, а не только команды ex, чтобы редактировать поток, представленный Vim из stdin. Это не очень полезный пример, но он иллюстрирует используемые методы. Предполагается, что ваша оболочка bash.

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

В -конце команда Vim сообщает текст (не команды) из стандартного ввода. -sГоворит Vim выполнять нажатия клавиш из указанного файла. В этом случае файл является результатом подстановки процесса bash. <(...)Заменяется именем именованного канала. Вывод канала является выводом команды в скобках. В wcwred\eперемещает курсор на одно слово и изменения , которые в следующем слово red. :wq! foo\nСохраняет результат в файл , fooдаже если этот файл уже существует. Конечным результатом является файл с именем, fooсодержащим текстThe red fox jumped.

Подробнее о некоторых из этих тем см.

:help -file
:help -s

Смотрите также Process Substitutionраздел bash(1)справочной страницы.

garyjohn
источник
Добавлено в мой ~ / .zshrc: vimx () { vi -s <(echo "$1"':wq') "$2" &> /dev/null; }. Теперь я могу vimx 'iThe brow fox jumped.\e' foo; vimx 'wcwred\efjdwiclimbed\e' foo; cat foo. Ухоженная!
Леонард Паули
4

Я обнаружил, что способ получения выходных данных программы, перенаправленной из вложенной оболочки, очень прост:

vim <( program )

Пример:

 vim <( grep -nH  hello  myFile.cpp )
 vim <( find . -name '*.cpp' -exec grep -nH code_expr {} \+ )
J Jorgenson
источник
4

У меня было то же самое желание, что и у вас: я хотел написать обычные команды vim, чтобы они редактировали поток конвейера. Я был разочарован трудностью использования обычного vim таким образом (так много флагов!), Как это предусмотрено параметрами vim по умолчанию.

Поэтому я написал небольшую оболочку для vim, чтобы сделать это: https://github.com/MilesCranmer/vim-stream/ . Это называется vims.

Сердцем оболочки является следующая команда:

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

Используя это, с генерацией команд, которые я делаю, получается довольно лаконично, и поскольку vim является модальным редактором, я создал vimsмодальный потоковый редактор. Есть три основных режима, которые полезны для менталитета редактирования конвейера:

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

Смотри:

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

Итак, eдоходит до конца Hello, затем aначинается добавление.

Что-то более необычное в exe-режиме, чтобы закомментировать строки, содержащие my_bad_var, и удалить предыдущую строку.

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

Что переводится как vims '%g/my_bad_var/exe "norm I//\<esc>kdd"'- Iналичие команды на начало вставки в начале строки и //последовательность комментариев. \<esc>kddнажимает клавишу escape, перемещается вверх по строке, затем удаляет строку.

У меня есть всего 11 примеров по репо, я призываю вас проверить их. Опять же, это работает поверх vim, это просто способ сделать vim более похожим на sed для потокового ввода (но сохранив все ваши любимые макросы vim!)

миль
источник
3

Это довольно старый вопрос, но я чувствовал, что стоит добавить, что если у вашего дистрибутива / ОС есть доступ moreutils, вы можете установить его и просто использовать vipeкак стандартное дополнение к vim:

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

moreutilsочень удобен и для других инструментов, и я очень рекомендую их, если вы серьезный пользователь командной строки! :) Посмотрите на введение автора (предыдущая ссылка) для более подробной информации.

moreutilsдолжен быть общедоступен для большинства * nix-подобных дистрибутивов через менеджер пакетов и через Homebrew на Mac . Например...

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


# Mac OS and Homebrew
brew install moreutils

moreutilsтакже является частью репозитория MSYS2 , так что вы можете технически использовать его и в Windows. :)

Эрих Гублер
источник