Як використовувати зовнішню команду у Vim для зміни вибраних слів і рядків?


22

Щось мені здалося корисним в інших редакторах - це можливість:

  • візьміть вибраний текст
  • запустіть зовнішню команду та передайте вибір її stdin
  • візьміть зовнішні команди stdoutта замініть поточний вибір на нього.

Таким чином, ви можете написати корисні текстові інструменти, які діють на вибір, використовуючи будь-яку мову, яка може виконувати основні io.

Як це можна зробити з vim за допомогою вибору? ... один символ, слово, абзац ... і т.д.

(Безпосередньо в командному рядку або через прив'язку ключа?)


Примітка

Такі команди, як !sortробота на рівні рядків, тому я задаю це питання тому, що я хотів би оперувати вибором. (тобто текст, який буде видалений при xнатисканні).

Відповіді:


17

Я вважаю, що часто найпростішим способом є використання візуального режиму з v(або великої літери Vдля вибору цілих рядків) та вибору тексту, який ви хочете передати.

Потім введіть:

:!cat

Це не дає нічого корисного як такого. Корисною командою, яку я часто використовую, є:

:!python -m json.tool

відформатувати JSON.

Ви також можете просто ввести (без візуального режиму):

:<range>!command

Наприклад, для всього файлу:

:%!python -m json.tool

Або для поточного рядка:

:.!python -m json.tool

Іншим дійсно корисним інструментом для використання є sortкоманда.
опитування Коді

4
@CodyPoll Що не так з Vim :sort?
Мартін Турноїй

5
@Carpetsmoker Команда зовнішнього сортування має набагато більше опцій і (залежно від локальної локації тощо) створює інший порядок.
derobert

1
Це не працює для вибору одного слова в рядку. (див. питання згадує вибір рівня слів)
ideaman42

@ Ideman42 Правильно ... Я думаю, що я спочатку читав це запитання як "рядки або слова" замість "рядків і слів" ... У будь-якому випадку, робити це зі словами не очевидно, програми UNIX працюють на рядках, а Vim не є винятком. Я дещо експериментував і начебто мав рішення, але це не дуже добре працює ... Можливо, мій підхід невірний, тому я просто залишу його на кілька днів і повернуся до нього пізніше.
Мартін Турнойж

7

Я написав плагін під назвою express.vim, який може допомогти у цьому. Плагін визначає оператора, g=який дозволяє оцінити вираз VimScript за допомогою руху (або візуального вибору). З'являється запит на вираз, в якому ви можете використовувати v:valяк заповнювач тексту, охопленого рухом (або, знову ж таки, Візуальний вибір).

У цьому випадку корисним виразом буде використовувати system()функцію, яка виконує зовнішню команду.

system('tr a-z A-Z', v:val)

(Тут я використав trяк простий приклад зовнішньої команди.)

Способом використання express.vim для цієї проблеми було б вибрати текст у візуальному режимі, потім ввести текст, g=за яким слідує цей вираз, та натисніть Enter:

g=system('tr a-z A-Z', v:val)<CR>

Я визнаю, це не просто у використанні. (Насправді я рідко використовую сам цей плагін!) Я розглядаю можливість додавання ярлика для виклику зовнішньої команди, наприклад, запуску виразу з !. Я опублікую оновлення тут, якщо закінчу це робити.

EDIT

Я змінив express.vim, щоб розглядати вирази, починаючи з !зовнішніх команд. Отже, дотримуючись trприкладу, вищесказане стає набагато простішим. Після виділення Visual введіть наступне:

g=!tr a-z A-Z<CR>

Пояснення:

  1. Викликати оператора експресу за допомогою g=
  2. Введіть !tr a-z A-Zяк вираз
  3. Натисніть Enter

4

Ви шукаєте команди фільтра у Vim. Див :help filter. Ось відповідна документація:

!{motion}{filter}   Filter {motion} text lines through the external
                    program {filter}.
!!{filter}          Filter [count] lines through the external program
                    {filter}.
{Visual}!{filter}   Filter the highlighted lines through the external
                    program {filter} (for {Visual} see |Visual-mode|).
                    {not in Vi}

:{range}![!]{filter} [!][arg]               *:range!*
                    Filter {range} lines through the external program
                   {filter}.  ...[See documentation for details]

Отже, набравши 5!!sortсортувати наступні 5 рядків, починаючи від курсору.


Чи можна фільтрувати одне слово? (не рівень лінії)
ideaman42

Так. Третій варіант (візуальний режим) працює для того, що виділяється (слова, часткова лінія, кілька рядків, прямокутний блок тощо).
Самер

1
Третій варіант також фільтрує цілі рядки. Якщо вибрати одне слово і відфільтрувати його, наприклад, через tr [:lower:] [:upper], то vim замінить не лише це слово, а й увесь рядок.
maria s

0

Зауважте, що це можна зробити за допомогою:

  1. візуально виберіть все, що завгодно
  2. s^R=system('tr a-z A-Z', @")[:-2]^M^RCTRL + R і ^ M - ENTER)

Він також може працювати з усім, що робить вибір + замінити подібне ci"^R=....


Запускаючи це на багаторядковому виділенні тексту (після натискання vта переміщення курсору), я отримую помилку E16: Invalid range\nE16: Invalid range\nE476: Invalid command(в Linux так trі інші основні команди існують).
ideaman42

Ви натиснули, sщо переходить у режим вставки чи :sкоманди?
Люк Ермітт

Не підозрюєте, але також не знаєте, як ви маєте на увазі, можливо, приклад може показати, як прив’язати це до ключа?
ideaman42

Ви потрапляєте прямо sз візуального режиму, чи ви б'єте :першим? У :послідовності написаних мною ключів немає участі. Відображення буде: vnoremap µ s<c-r>=system('tr a-z A-Z', @")[:-2]<cr>.
Люк Ермітт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.