Доступ к локальным переменным оболочки в vim - PullRequest
0 голосов
/ 25 октября 2018

В vim я могу получить доступ к моим переменным окружения bash, таким как $ PWD и $ PATH.Я хотел бы знать, как получить доступ к моим временным переменным оболочки в vim.

Например, предположим, что я был в моем терминале и определил переменную foo="bar".Затем я ввожу vim и пытаюсь получить доступ к этой переменной с помощью следующей команды :!echo $foo, но она не распознает эту переменную.Насколько я понимаю, vim запускает новую оболочку каждый раз, когда вызывается команда bash, а затем сразу же закрывает ее.Есть ли способ использовать ту же оболочку в vim, в которой была определена моя локальная переменная foo?

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

Объяснение

Переменные среды и переменные оболочки - это две совершенно разные концепции, но, поскольку мы манипулируем ими аналогичным образом в bash, легко запутаться.

  • Всякий раз, когда процесс создается (с помощью fork), он может включать в себя среду, предоставляемую его родителем во время разветвления.Затем дочерний процесс может получить доступ и изменить свое содержимое.То, как это делается для пользователя, зависит от программы:

    • В vim вы можете получить доступ к переменной окружения , например: :echo $foo
    • В bashвы можете получить к нему доступ следующим образом: $ echo "$foo"
    • В большинстве языков программирования вы можете получить к нему доступ с помощью синтаксиса, связанного с остальным языком, например ENV['foo'] в ruby ​​
  • С другой стороны, программа может выделять память для любого внутреннего использования, но, в частности, она будет часто определять и использовать переменные.Еще раз, это зависит от программы:

    • В vim вы должны использовать команду: let для назначения внутренней переменной
    • В bash вы быприсвойте переменную с $ foo='bar', а затем прочитайте ее с $ echo "$foo"
    • В большинстве языков программирования у вас есть вариация синтаксиса foo='bar', иногда с объявлениями типов и т. д.

Как вы можете видеть, bash использует тот же синтаксис для чтения переменной окружения и одной из своих личных переменных , что может привести к некоторой путанице.

Когда вы выполняете vim из оболочки bash, среда копируется из родительского процесса (bash) в дочерний процесс (vim), но личная память bash (включая переменные, которые вы, возможно, определили) - нет.

Таким образом, для доступа к ним из дочернего процесса потребуется некоторый механизм межпроцессного взаимодействия между родителем и дочерним процессом.Хотя это технически выполнимо, эта опция не реализована в bash или vim.


Решение

Для того, чтобы ваша переменная была доступна из vim (или любого разветвленного процесса, в этом отношении)вам нужно, чтобы он присутствовал в среде вашего процесса vim.

Несколько вариантов сделать это:

  • $ export foo='bar': это пометит вашу переменную для экспорта в средувпоследствии выполненных команд.Это то, что вам нужно в большинстве случаев.
  • $ foo='bar' vim: это добавляет вашу переменную в среду этой команды vim.Очень полезно для устранения неполадок или для однострочников.
  • $ set -a: Как видно из bash manpage , это помечает каждое последующее определение для экспорта в среду последующих команд.По сути это эквивалентно добавлению каждого последующего определения к export.

Чтобы идти дальше

  • В вопросе используется синтаксис :!echo $foo для отображениязначение foo, которое является еще одним вариантом использования.! здесь на самом деле является escape-последовательностью, которая позволяет вам выполнить команду оболочки из vim.

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

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

  • Существует другой синтаксис vim , использующий expand, который позволяет искать переменные: :echo expand("$foo")

    Однако он работает совершенно иначе.

    Если не существует внутренней переменной с именем foo, vim вызовет оболочку для ее поиска (аналогично тому, что сделал бы !).

    Этот параметр способ медленнее, чем поиск среды, и не рекомендуется для большинства случаев использования.

0 голосов
/ 05 апреля 2019

Если вы хотите использовать значение из вашей оболочки в команде :substitute, на самом деле есть способ сделать это.

Я не знаю, решает ли это вашу проблему, но здесь мы идем.

Допустим, мы хотим заменить Mydir на PWD:

:s/Mydir/\=expand($PWD)/g
0 голосов
/ 25 октября 2018

Нет, вы не можете взаимодействовать с родительской оболочкой из подпроцесса, который она породила (без активного участия этой оболочки, что недоступно разумно / практически недоступно в данном сценарии) - но вы можете экспортируйте переменные, чтобы сделать их доступными для новых оболочек, запущенных в дочерних процессах.

Выполнение

set -a

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


Поскольку (в отличие от функции C system()) vim's system() учитывает переменную окружения SHELL, если SHELL=/bin/bash (или :set shell=/bin/bash былозапустить в vim), вы также можете вызывать экспортированные функции из vim.То есть, если вы определяете функцию и экспортируете ее следующим образом:

foo() { echo "bar"; }
export -f foo

... тогда вы можете вызвать ее с помощью !foo изнутри vim.

Даже тогда, однако,это выполняется в новом, временном экземпляре оболочки, а не в исходном родительском процессе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...