Vim имя файла / завершение пути

11

Я знаю, что могу завершить имена файлов / пути из текущего каталога, используя Ctrl + X, Ctrl + F ( compl-filename). Это прекрасно работает в сочетании с set autochdir, который изменяет обновляет текущий каталог на каталог активного буфера.

Однако я начал использовать, airblade/vim-rooterчтобы сделать текущий каталог папкой «проекта». Теперь завершение имени файла всегда начинается с папки проекта.

Вопрос: есть ли способ заставить завершение имени файла использовать каталог активного буфера вместо текущего каталога? Или какой-то другой обходной путь?

Также спрашивается в stackoverflow

Рафаэль Барбоса
источник
5
C-xC-f всегда использует текущий каталог текущего буфера, без каких-либо опций для его настройки (он также не поддерживает path). Это зависит от того, что вы планируете использовать для vim-rooter. В зависимости от того, что вы хотите от него, мы можем использовать другие плагины. Кроме того: я использую youcompleteme, которая завершает пути из каталога текущего буфера, если вы начинаете печатать ./. См. Reddit.com/r/vim/comments/216jdd/…
Muru

Ответы:

7

Как уже упоминалось, @muru, нет никаких опций для настройки каталога, из которого следует указывать путь и имена файлов. Он всегда использует рабочий каталог окна.

Я написал несколько функций и сопоставлений, чтобы помочь с этим. За кулисами они :lcdвременно меняют локальный рабочий каталог (используя ), а затем восстанавливают предыдущий рабочий каталог по завершении.

слон

По неизвестным даже мне причинам я назвал этот микро-плагин Elephant .

Вот код (скопированный из моей конфигурации Vim на GitHub ):

let g:elephant_map = {
    \ 'f': function('elephant#current_file'),
    \ 'p': function('elephant#vcs_project')
\ }

function! elephant#prompt(base)
    let l:Fcn = get(g:elephant_map, a:base, function('elephant#identity'))
    let l:basedir = l:Fcn()
    execute 'lcd' l:basedir
    let l:file = fnamemodify(input(l:basedir.'/', '', 'file'), ':p')
    lcd -
    return fnamemodify(l:file, ':.')
endfunction

function! s:elephant_init()
    let l:base = getchar()
    return elephant#prompt(nr2char(l:base))
endfunction

function! elephant#identity()
    return '.'
endfunction

function! elephant#vcs_project()
    return fnamemodify(finddir('.git', '.;'), ':h')
endfunction

function! elephant#current_file()
    return expand('%:h')
endfunction

inoremap <silent> <expr> <C-R><C-E> <SID>elephant_init()
cnoremap <silent> <C-R><C-E> <C-R>=<SID>elephant_init()<CR>

Как это использовать

Использование этих сопоставлений происходит в 3 этапа.

1. Запустите отображение

В режиме вставки или режиме командной строки вызовите отображение с помощью <C-R><C-E>.

2. Выберите каталог

Введите один символ, чтобы выбрать, из какого корневого каталога вы хотите завершить. Код выше предоставляет два типа корней:

  • f - Каталог, в котором находится текущий файл (буфер)
  • p - Базовый каталог проекта Git, к которому принадлежит текущий файл

3. Введите путь или имя файла

Вам будет предложено ввести путь или имя файла относительно указанного каталога, с завершением доступно. Нажмите, Enterкогда закончите.

Некоторые заметки

  • Это не обеспечивает встроенное завершение в режиме вставки, как это <C-X><C-F>делается; вместо этого вы будете вводить путь или имя файла в командной строке (куда :идут команды). После нажатия Enterпуть будет вставлен в буфер.
  • То же самое верно и в режиме командной строки, который иногда может сбить с толку, когда вы нажимаете Enterи забываете, что вам все равно нужно нажать, Enterчтобы выполнить любую команду, которую вы только что набирали.
  • Другие функции каталога можно зарегистрировать, добавив их в g:elephant_map.
  • Вставленный путь будет полным, абсолютным путем. Сценарий может быть изменен, чтобы изменить это поведение, но я не дошел до него.
tommcdo
источник
Не совсем протестировал решение, но принял его из-за полноты. Вместо этого я использовал предложенный обходной путь: YouCompleteMe вместо ctrl + x, ctrl + f.
Рафаэль Барбоза