특정 파일 형식에 대한 자체 자동 완성 목록을 작성하려면 어떻게합니까?
예를 들어 FontAwesome 의 CSS 클래스 목록에서 css 및 html을 자동 완성하고 싶습니다 .
특정 파일 형식에 대한 자체 자동 완성 목록을 작성하려면 어떻게합니까?
예를 들어 FontAwesome 의 CSS 클래스 목록에서 css 및 html을 자동 완성하고 싶습니다 .
답변:
사전 완성은 저렴하고 방해가되지 않는 솔루션입니다.
컴퓨터 어딘가에 fontawesome.txt를 저장 하십시오.
이것을 넣으 after/ftplugin/css.vim
십시오 (파일이 존재하지 않으면 파일을 만드십시오).
setlocal complete+=k
setlocal dictionary+=/path/to/fontawesome.txt
setlocal iskeyword+=-
새 세션을 시작하거나 :e
CSS 버퍼에서 위의 파일을 강제로 소싱하십시오.
를 눌러 <C-n>
또는 <C-p>
삽입 모드에서,
즐겨!
참고:
:help ins-completion
:help 'complete'
:help 'dictionary'
:help 'iskeyword'
편집 romainl의 의견 덕분에 사용자 정의 완료 함수를 만드는 방법을 보여주기 위해 답변을 편집했습니다. 이전 버전에서는 사용자가 기본 완성 기능을 느슨하게 만들었 기 때문에 좋지 않은 내장 완료 옴니 완성을 재정의했습니다.
vimscript 솔루션
한 가지 해결책은 vimscript와 vim을 사용하여 사용자 정의 완료 함수를 작성하는 것입니다.
이 솔루션의 장점은 추가 플러그인이 필요하지 않기 때문에 사용자 정의 완료 기능을 만들고 내장 완료 기능을 사용할 수 있다는 것입니다.
css
파일 에서 fontAwesome 클래스의 예를 사용하겠습니다 .
파일을 작성하고 ~/.vim/autoload/csscomplete.vim
다음 행을 넣으십시오.
let s:matches=".fa-lg .fa-2x .fa-3x .fa-4x .fa-5x .fa-fw .fa-ul .fa-ul .fa-li .fa-li.fa-lg .fa-border .fa-pull-left .fa-pull-right .fa.fa-pull-left"
function! csscomplete#CompleteFA(findstart, base)
if a:findstart
" locate the start of the word
let line = getline('.')
let start = col('.') - 1
while start > 0 && (line[start - 1] =~ '\a' || line[start - 1] =~ '.' || line[start - 1] =~ '-')
let start -= 1
endwhile
return start
else
" find classes matching "a:base"
let res = []
for m in split(s:matches)
if m =~ '^' . a:base
call add(res, m)
endif
endfor
return res
endif
endfun
그런 다음 파일을 작성하여 ~/.vim/after/ftplugin/css.vim
다음 행에 넣으십시오.
setlocal completefunc=csscomplete#CompleteFA
그런 다음을 사용하여 사용자 정의 완료 기능을 트리거 할 수 있습니다 <C-x><C-u>
. 마지막으로 입력 한 단어와 일치하는 것을 찾으려고 시도합니다.
스크린 샷에서 .fa-l
다음을 입력 하여 함수를 트리거했습니다 <C-x><C-u>
.
어떻게 작동합니까?
먼저 여기에 몇 가지 관련 문서 주제가 있습니다.
큰 응답 파일의 조직에 대한.
특정 파일 유형에 대해 사용자 정의 완료를 작성하려면 파일에 입력해야합니다 $HOME/.vim/autoload/{FILETYPE}complete.vim
.
그런 다음이 파일에서 완료 함수를 두 번 작성해야합니다.
첫 번째 호출에서 첫 번째 인수는 커서의 현재 위치이며 함수는 완료 할 단어를 결정합니다. 내 기능에서 나는 클래스가 문자로 구성 할 수 있기 때문에 전체에 단어를 얻기 위해 3 개 비교를 사용 .
하고 -
(나는이 매칭을 향상시킬 수있다 생각하지만 난 정규식 정말 나쁜거야)
두 번째 호출에서 두 번째 인수는 일치시킬 단어이고 함수는이를 일치하는 가능한 클래스 목록과 비교하여 1 과 일치 합니다. 여기서 완성 메뉴를 채울 사전을 반환 하지만 설명서를 읽으면 훨씬 더 복잡한 사전을 만들어 함수의 동작을 더 많이 사용자 지정할 수 있음을 알 수 있습니다.
또한 Vim에 "이런 종류의 파일에는 내가 만든이 완전한 기능을 사용하십시오"라고 알려야합니다. 그렇게하려면 completefunc
생성 한 기능의 이름 (여기 csscomplete#CompleteFA
)으로 설정해야하며이 설정은 파일에서 수행해야합니다 $HOME/.vim/after/ftplugin/{FILETYPE}.vim
.
1 내 함수에서 변수 s:matches
는 가능한 모든 일치 항목을 포함합니다. 여기에서는 가독성에 대한 몇 가지 제안 만 제시했지만 FontAwesome에서 제공하는 모든 클래스를 넣을 수 있습니다 (romainl 이 작성한 이 파일 에서 전체 목록을 찾을 수 있음).
Vimscript가 마음에 들지 않으면 어떻게합니까?
한 가지 가능성은 완성 메뉴를 가지고 노는 API를 제공하는 YoucompleteMe 플러그인을 사용하는 것 입니다. 일치하는 작업을 수행하고 API를 사용하여 Vim 인터페이스를 채우는 Python 함수를 작성할 수 있습니다. 자세한 내용은 여기를 참조 하십시오 .
때로는 내장 또는 사용자 정의 자동 완성을 전혀 방해하지 않는 사용자 지정 자동 완성을 원할 때가 있습니다. 이 기능은 다양한 파일 형식에 사용할 수있는 스크립트 또는 플러그인에 특히 유용합니다.
이것은 complete()
함수와 간단한 래퍼로 상당히 쉽게 수행 할 수 있습니다
. :help complete-functions
자신의 매핑을 정의해야 complete()
하고 값을 반환하는 대신 자신 을 호출해야한다는 점을 제외하면 대부분의 절차는 Statox의 답변과 설명 과 동일
합니다.
다음은 기본적인 예입니다. 의견은 작동 방식을 설명해야합니다.
" Map <C-x><C-m> for our custom completion
inoremap <C-x><C-m> <C-r>=MyComplete()<CR>
" Make subsequent <C-m> presses after <C-x><C-m> go to the next entry (just like
" other <C-x>* mappings)
inoremap <expr> <C-m> pumvisible() ? "\<C-n>" : "\<C-m>"
" Complete function for addresses; we match the name & address
fun! MyComplete()
" The data. In this example it's static, but you could read it from a file,
" get it from a command, etc.
let l:data = [
\ ["Elmo the Elk", "daring@brave.com"],
\ ["Eek the Cat", "doesnthurt@help.com"]
\ ]
" Locate the start of the word and store the text we want to match in l:base
let l:line = getline('.')
let l:start = col('.') - 1
while l:start > 0 && l:line[l:start - 1] =~ '\a'
let l:start -= 1
endwhile
let l:base = l:line[l:start : col('.')-1]
" Record what matches − we pass this to complete() later
let l:res = []
" Find matches
for m in l:data
" Check if it matches what we're trying to complete; in this case we
" want to match against the start of both the first and second list
" entries (i.e. the name and email address)
if l:m[0] !~? '^' . l:base && l:m[1] !~? '^' . l:base
" Doesn't match
continue
endif
" It matches! See :help complete() for the full docs on the key names
" for this dict.
call add(l:res, {
\ 'icase': 1,
\ 'word': l:m[0] . ' <' . l:m[1] . '>, ',
\ 'abbr': l:m[0],
\ 'menu': l:m[1],
\ 'info': len(l:m) > 2 ? join(l:m[2:], "\n") : '',
\ })
endfor
" Now call the complete() function
call complete(l:start + 1, l:res)
return ''
endfun
:help i_ctrl-x_ctrl-u
.