Làm cách nào để tôi tạo danh sách tự động hoàn thành cho một số loại tệp nhất định?
Ví dụ, tôi muốn css và html tự động hoàn thành từ danh sách các lớp css trong FontAwgie .
Làm cách nào để tôi tạo danh sách tự động hoàn thành cho một số loại tệp nhất định?
Ví dụ, tôi muốn css và html tự động hoàn thành từ danh sách các lớp css trong FontAwgie .
Câu trả lời:
Hoàn thành từ điển sẽ là một giải pháp rẻ tiền và không xâm phạm:
lưu fontawclaw.txt ở đâu đó trên máy của bạn,
đặt cái này vào after/ftplugin/css.vim
(tạo tập tin nếu nó không tồn tại):
setlocal complete+=k
setlocal dictionary+=/path/to/fontawesome.txt
setlocal iskeyword+=-
bắt đầu một phiên mới hoặc thực hiện :e
trong bộ đệm CSS để lấy nguồn mạnh ở trên,
nhấn <C-n>
hoặc <C-p>
trong chế độ chèn,
thưởng thức!
Tài liệu tham khảo:
:help ins-completion
:help 'complete'
:help 'dictionary'
:help 'iskeyword'
EDIT Nhờ nhận xét của romainl Tôi đã chỉnh sửa câu trả lời của mình để hiển thị cách tạo chức năng hoàn thành do người dùng xác định. Trong phiên bản trước, tôi đã ghi đè hoàn thành omni-in, điều này không tốt vì người dùng sẽ mất hoàn thành mặc định, điều này khá mạnh mẽ.
Một giải pháp vimscript
Một giải pháp là sử dụng vimscript và thực tế là vim cho phép bạn tạo một chức năng hoàn thành tùy chỉnh.
Ưu điểm của giải pháp này là bạn không cần một plugin bổ sung, bạn chỉ cần tạo một hàm hoàn thành do người dùng xác định và sử dụng tính năng hoàn thành tích hợp.
Tôi sẽ sử dụng ví dụ của bạn về các lớp fontAwgie trong css
các tệp:
Tạo tập tin ~/.vim/autoload/csscomplete.vim
và đặt các dòng sau vào nó:
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
Sau đó tạo tập tin ~/.vim/after/ftplugin/css.vim
và đặt nó vào dòng sau:
setlocal completefunc=csscomplete#CompleteFA
Sau đó, bạn có thể kích hoạt chức năng hoàn thành do người dùng xác định với <C-x><C-u>
. Nó sẽ cố gắng tìm một từ khớp với từ được gõ cuối cùng.
Trong ảnh chụp màn hình tôi đã gõ .fa-l
và sau đó kích hoạt chức năng với <C-x><C-u>
:
Làm thế nào nó hoạt động?
Đầu tiên ở đây là một số chủ đề tài liệu có liên quan:
Một câu trả lời tuyệt vời về việc tổ chức các tập tin.
Nếu bạn muốn tạo một hoàn thành tùy chỉnh cho một kiểu tệp cụ thể, bạn phải đặt nó vào tệp $HOME/.vim/autoload/{FILETYPE}complete.vim
.
Sau đó, trong tệp này, bạn phải tạo chức năng hoàn thành của mình được gọi là hai lần:
Trong lần gọi đầu tiên, đối số đầu tiên của nó là vị trí hiện tại của con trỏ và hàm sẽ xác định từ cần hoàn thành. Trong chức năng của mình, tôi đã sử dụng 3 so sánh để hoàn thành từ vì lớp có thể bao gồm các chữ cái .
và -
(tôi nghĩ có thể cải thiện kết hợp này nhưng tôi thực sự xấu với regex)
Trong cuộc gọi thứ hai, đối số thứ hai là từ phù hợp và sau đó hàm so sánh nó với danh sách các lớp có thể khớp với 1 . Ở đây bạn thấy rằng tôi trả lại một từ điển sẽ điền vào menu hoàn thành nhưng khi bạn đọc tài liệu bạn sẽ thấy rằng bạn có thể tạo một từ điển phức tạp hơn nhiều để tùy chỉnh nhiều hơn hành vi của chức năng của bạn.
Bạn cũng phải nói với Vim "đối với loại tệp này, hãy sử dụng chức năng hoàn chỉnh này mà tôi đã tạo". Để làm như vậy, bạn phải đặt thành completefunc
tên của chức năng bạn đã tạo (ở đây csscomplete#CompleteFA
) và cài đặt này phải được thực hiện trong tệp $HOME/.vim/after/ftplugin/{FILETYPE}.vim
.
1 Trong hàm của tôi, biến s:matches
chứa tất cả các kết quả khớp có thể. Ở đây tôi chỉ đưa ra một số gợi ý về tính dễ đọc nhưng bạn có thể đặt tất cả các lớp được cung cấp bởi FontAwgie (Bạn có thể tìm thấy danh sách đầy đủ trong tệp này được tạo bởi romainl).
Nếu tôi không thích Vimscript thì sao?
Một khả năng là sử dụng plugin YoucompleteMe cung cấp API để chơi với menu hoàn thành. Bạn có thể tạo chức năng python sẽ thực hiện công việc phù hợp và sẽ sử dụng API để điền giao diện Vim. Thêm chi tiết tại đây .
Đôi khi bạn muốn tự động hoàn thành tùy chỉnh mà không can thiệp vào bất kỳ tự động hoàn thành do người dùng xác định hoặc tích hợp nào. Điều này đặc biệt hữu ích cho các tập lệnh hoặc plugin được dự định hoạt động cho một loạt các kiểu tệp.
Điều này có thể được thực hiện khá dễ dàng với
complete()
chức năng và một trình bao bọc đơn giản; hầu hết các thủ tục giống như được mô tả trong
:help complete-functions
và câu trả lời của Statox, ngoại trừ việc bạn cần xác định ánh xạ của riêng mình và phải tự gọi complete()
mình thay vì trả về một giá trị.
Dưới đây là một ví dụ cơ bản, các ý kiến nên giải thích cách nó hoạt động.
" 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
.