Як використовувати зовнішню команду у 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.