Я работаю с некоторыми файлами, похожими на DokuWiki . Файлы имеют сопутствующие файлы PNG в одном каталоге. На них ссылаются в следующем синтаксисе:

{{filename.png}}

Я хочу написать макрос, который бы взял filename.png и в идеале путь редактируемого файла и передавал эти параметры в xdg-open .

Самое близкое, что мне удалось сделать, это:

:'<,'>!sed s/\{\\\|\}//g|xargs xdg-open

который является грубым, стирает текущую строку, требует, чтобы я был в пути к файлу, и требует, чтобы я использовал визуальный режим, чтобы выделить текст .... но это работает.

У меня возникают проблемы с поиском документации, которая может помочь мне безопасно проанализировать текущую строку для имени файла, а затем передать путь к текущему файлу и целевому имени файла в xdg-open в командной строке vim.

Когда это будет сделано ... в идеале это позволит мне запустить макрос для просмотра встроенного файла.


Согласно ответу G-Man и некоторому обману, хорошо работает следующее:

:.w !sed -e 's|.*{{|%{{|' -e 's|[^/]*{{||' -e 's/^/"/' -e 's/}}.*/"/' | xargs xdg-open

Он вставляет символы двойной кавычки (") в начале и конце пути / имени файла, поэтому он поддерживает имена, которые включают пробелы, апострофы (одинарные кавычки) и некоторые другие специальные символы.

1 ответ1

1
  • : диапазон !команда

    записывает текст из диапазона в канал (удаляя его из буфера файлов), запускает команду для канала, считывает стандартный вывод команды и вставляет его в буфер, в котором находился диапазон .  Это функция vim которую вы используете.  Эта функция очень полезна с командой sort .  Я не могу вспомнить, чтобы когда-либо видел какую-либо другую ситуацию, где эта функция vim полезна; это, кажется, не один.

    Ты хочешь

    : диапазон w!команда
    который записывает диапазон в канал (но не удаляет его из буфера файлов), запускает команду в канале и позволяет стандартному выводу команды (если есть) просто перейти на экран (т. е. vim стандартный вывод).  (Расстояние между диапазоном и w необязательно.)
  • Диапазон может быть от одной метки до другой ('< и '> - фактически метки), от одной строки к другой или только от одной строки.  Пока у вас есть только один {{…}} в строке, вы можете просто перейти к строке (вам не нужно выделять ее) и использовать . как ваш диапазон.  Если у вас есть только один {{…}} в этом файле, вы можете использовать в качестве диапазона действия //{{.*}}/ (или даже /{{/ , если он уникален).  Так ваша команда становится
    : /{{/w!седь бла бла бла
  • Я предпочитаю заключать в кавычки строки, которые нужно заключать в кавычки , а не бросать в них миллион обратных косых черт.  Я думаю, это просто личное предпочтение; если обратная косая черта работает на вас, используйте их.
  • Необычные регулярные выражения (использующие | для поиска того или иного шаблона) имеют свое место в мире.  Я склоняюсь к использованию нескольких команд sed .  Опять что угодно.
  • Так что моя версия того, что вы делаете сейчас, будет выглядеть примерно так:
    : /{{/w!Sed -e 's /. xargs xdg-open
    который удаляет {{ и все до него, и удаляет }} и все после него.  Но это все еще требует, чтобы вы были в каталоге, где находится файл PNG.
  • Файл PNG находится в том же каталоге, что и текстовый файл.  Полезно отметить, что при запуске команды оболочки с ! из vim , неэкранированный % в командной строке заменяется именем файла, который вы в данный момент редактируете.  (Попробуйте: наберите :!echo abc%def .)  Мы можем использовать это, чтобы определить путь к каталогу, в котором находятся файлы.  Таким образом, мы можем улучшить приведенную выше команду, чтобы:

    : /{{/w!sed -e 's.. * {{|% {{|' -e 's | [^ /] * {{||' -e 's |}}. * ||' | xargs xdg-open
    Первая подкоманда sed, s|.*{{|%{{| , удаляет все до {{ и заменяет его именем файла, и оставляет {{ .  Обратите внимание, что эта подкоманда должна использовать (непустой) разделитель, который не будет отображаться в пути /имени файла, поэтому мы не можем использовать / .  Если у вас есть имена каталогов или имена файлов с вертикальными чертами в них, выберите какой-либо другой символ для использования в качестве разделителя.  Вторая подкоманда s|[^/]*{{|| , удаляет часть имени файла % filename, оставляя часть каталога (если есть), и удаляет {{ .  Третья подкоманда s|}}.*|| , то же самое, что и вторая подкоманда (s/}}.*//) из предыдущей команды; он удаляет }} и все после него.

    Хотя командам s/pattern/replacement/ всегда нужно использовать разделитель, которого нет в pattern или тексте replacement (или экранировать символ разделителя, когда он появляется), это проблема только для первой команды s .  Я использовал | во всех трех только для согласованности.

TL; DR

Использование:

:/{{/w !sed -e 's|.*{{|%{{|' -e 's|[^/]*{{||' -e 's|}}.*||' | xargs xdg-open

PS Я предполагаю, что вы понимаете, что они не будут работать, если имя файла содержит пробелы.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .