Как запускать команды/скрипты vim из корня проекта?

У меня есть множество команд, которые я хотел бы запускать не в текущем каталоге, а в корневом каталоге проекта. то есть переход по каталогам, пока я не достигну какого-либо признака корня, например, каталога .git.

Например, запуск vimgrep -r (рекурсивный) для всего моего проекта или рекурсивный запуск генерации тегов для всего проекта.

Как получить этот путь? Единственное близкое указание, которое я нашел, это: set tags=./tags;~/Projects Но это просто сохраняет строку в тегах. Назначение чего-то подобного, но для описанного варианта использования, дает мне строку дословно.

Любая помощь приветствуется! Спасибо!


person PsyFish    schedule 16.01.2015    source источник
comment
Обычно рекомендуется запускать Vim в корне вашего проекта и не менять рабочий каталог.   -  person romainl    schedule 16.01.2015
comment
Это интересное предложение, хотя и менее гибкое. Не могли бы вы уточнить некоторые причины, по которым не рекомендуется менять рабочий каталог?   -  person PsyFish    schedule 16.01.2015
comment
Ну… почему вы постоянно меняете свой рабочий каталог? Рабочий каталог — это ваш проект: здесь вы строите, где запускаете свои тесты, где существует ваш каталог VCS, где вы размещаете свой файл tags, где вы можете получить доступ к каждому файлу в вашем проекте…   -  person romainl    schedule 16.01.2015
comment
ctrlp позволяет получить доступ к каждому файлу в моем проекте. Автоматическое изменение рабочего каталога в зависимости от текущего буфера дает мне две вещи, которые приходят мне на ум: 1. при создании нового файла через :e я знаю, где он будет размещен, без необходимости мысленно напоминать себе, где я открыл в gvim (что не всегда находится в корне какого-либо проекта). 2. при работе более чем над одним проектом в одном vim с разделенными окнами В ваших словах определенно есть смысл. Просто менее гибко ссылаться на мой рабочий каталог vim как на рабочий каталог проекта.   -  person PsyFish    schedule 16.01.2015


Ответы (3)


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

Единственные инструменты, которые это делают (например, git), - это те, которые не заботятся о текущем каталоге с самого начала.

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

Лучший подход — открыть новые сеансы Vim внутри каталогов, где вы хотите выполнять «локальные» действия, и переключиться обратно на сеанс «проекта» для запуска команд проекта. Vim защитит вас от случайной перезаписи изменений в другом сеансе.

Альтернативой является перенос команд в оболочки, чтобы они могли иметь свои «собственные» рабочие каталоги, например:

:!cd ../../..; ctags -R

(Что позволит вам регенерировать файл тегов для проекта, а не только для текущего каталога)

or:

:!cd ../../..; grep -r foo **/*

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

Итак, вы можете предпочесть:

:!cd ../../..; vim

который создает новый сеанс Vim внутри текущего, но в контексте корневого каталога.

Или вы можете предпочесть обратное (при условии, что Vim работает в корневом каталоге проекта):

:!cd $(dirname %); vim

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

Таким образом, вместо «изменения» каталогов вы «меняете сеансы vim» (либо имея 2 сеанса, либо «вкладывая» один в другой, как указано выше).

person Cezary Baginski    schedule 16.01.2015
comment
Это последнее предложение довольно простое, поэтому я пойду с ним. В сочетании с тем, что я нашел в советах Vim: cabbr ‹expr› %% expand('%:p:h') ввод %%/ расширяет его до каталога файла, который я редактирую - person PsyFish; 16.01.2015
comment
Будьте осторожны с этой аббревиатурой, она будет расширяться в маловероятных местах, например, когда вы ищете, например. /%%. Возможно, вы ошиблись с отображением: cnoremap <c-r><c-d> <c-r>=expand('%:p:h')<cr> - person Peter Rincker; 16.01.2015

Я использую плагин local_vimrc для установки переменных, связанных с проектом. Затем я использую (/write) плагины, которые полагаются на (buffer/project)-локальные переменные, чтобы делать что-то. (К сожалению, большинство плагинов полагаются на глобальные переменные, что не лучший выбор для специализации их поведения для текущего проекта в сеансах с несколькими проектами)

Что касается генерации ctags, то используются lh-tags, для которого требуется установить несколько переменных.

Что касается grepping, как и прочего, я обычно начинаю с текущего каталога, который часто является корневым каталогом моего проекта. Но вы также можете легко иметь плагин/команду, которая будет запускать что-то вроде:

exe "vimgrep -r ".pattern." ".
  \ map(file_extensions, 
  \     string(lh#option#get('project_root_directory').'/**').'v:val')

РЕДАКТИРОВАТЬ:

Если вам не нужны другие файлы конфигурации, и если каталога .git/ достаточно для идентификации корневого каталога вашего проекта, вы можете использовать такую ​​функцию для получения корневого каталога вашего проекта:

function! ProjectRootDirectory()
   return fnamemodify(finddir('.git', '.;'), ':h')
endfunction

Затем, когда вы будете запускать ctags, вам придется выполнять ctags из результата этой функции vim. Я не знаю, какой плагин вы используете для запуска ctags в данный момент. Мои lh-теги не поддерживают функции через переменные конфигурации. При необходимости его можно легко добавить.
Однако я не вижу простого способа настроить &tags один раз из .vimrc, чтобы настроить этот параметр для каждого проекта отдельно.

person Luc Hermitte    schedule 16.01.2015
comment
Спасибо, Люк, это действительно решит проблему. Однако это решит больше, чем я рассчитывал, за счет необходимости еще одного файла для каждого проекта. Хотя это не большая цена, поскольку все, что мне сейчас нужно, это просто возможность подниматься по каталогам, я предпочитаю простую команду и/или сценарий, который я могу запустить перед такими вещами, как vimgrep и/или генерация тегов. - person PsyFish; 16.01.2015
comment
Существует способ получить корневой каталог проекта, если есть файл или каталог, который его отмечает. Затем этот корневой каталог может быть вычислен динамически и использован плагинами. Тем не менее, я вижу возможность адаптировать &tags на лету для использования обнаруженного корневого каталога, кроме плагинов local_vimrc. Я отредактировал свое сообщение с более подробной информацией по этому вопросу. - person Luc Hermitte; 16.01.2015
comment
Это интересно. Однако я не слишком хорошо знаком с ограничениями того, где я могу выполнять vimscript. Я должен расследовать это. - person PsyFish; 16.01.2015

Лично мне нравится, чтобы это было просто, и чтобы мой текущий каталог был корнем моего проекта. Я могу использовать % для представления текущего файла в командах, например. :!git add %. Наряду с % вы можете использовать модификаторы имени файла, например. :e %:h/foo.txt. См. :h filename-modifiers.

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

Вот что я бы порекомендовал:

  • Обновите свои теги с помощью git hooks. См. раздел Простые C-теги с Git.
  • Если ваши теги находятся в .git/tags, fugitive.vim автоматически настроит эти теги для вас.
  • Используйте :Ggrep, который использует git grep, чтобы он уже знал о корневом каталоге вашего проекта и, в качестве бонуса, работал намного быстрее, чем :vimgrep.
  • Выполнение произвольных команд из-под рута сложнее. Я использую projectionist для управления своими проектами. Киномеханик предоставляет команду :ProjectDo, которая делает именно то, что вам нужно.

Теперь предостережение: Vim не понимает понятия "проект". Ближе всего к этому вариант 'exrc' (см. :h 'exrc'), который довольно хромает.

person Peter Rincker    schedule 16.01.2015
comment
Это креативно! Однако мне понадобится некоторое время, прежде чем я смогу сесть и освоить все эти инструменты. Спасибо, что познакомили меня с этими инструментами! - person PsyFish; 16.01.2015
comment
Я настоятельно рекомендую использовать fugitive.vim, если вы используете git. На Vimcasts есть набор скринкастов о том, как использовать беглеца: Серия "Беглецы" – ретроспектива - person Peter Rincker; 16.01.2015
comment
Спасибо Питер! Беглец действительно шикарен! - person PsyFish; 19.01.2015