अपने स्वयं के स्वत: पूर्ण कार्य कैसे बनाएं?


22

मैं कुछ फ़िल्टरों के लिए ऑटो-पूर्ति की अपनी सूची कैसे बनाऊं?

उदाहरण के लिए, मैं FontAwesome में सीएसएस कक्षाओं की सूची से स्वत: पूर्ण करने के लिए css और html चाहूंगा ।

जवाबों:


22

शब्दकोश पूरा करना एक सस्ता और गैर-घुसपैठ समाधान होगा:

  1. अपनी मशीन पर कहीं भी fontawesome.txt बचाएं ,

  2. इसे डालें after/ftplugin/css.vim(यदि मौजूद नहीं है तो फ़ाइल बनाएं):

    setlocal complete+=k
    setlocal dictionary+=/path/to/fontawesome.txt
    setlocal iskeyword+=-
    
  3. एक नया सत्र शुरू करें या :eऊपर की फ़ाइल को जबरदस्ती स्रोत करने के लिए CSS बफ़र में करें,

  4. प्रेस <C-n>या <C-p>इन्सर्ट मोड में,

  5. का आनंद लें!

    शब्दकोश पूरा करना

संदर्भ:

:help ins-completion
:help 'complete'
:help 'dictionary'
:help 'iskeyword'

17

EDIT धन्यवाद रोमेल की टिप्पणी के लिए मैंने अपना उत्तर यह दिखाने के लिए संपादित किया है कि उपयोगकर्ता-निर्धारित पूरा होने का कार्य कैसे करें। पिछले संस्करण में मैं बिल्ड-इन-ओमनी-ओवर को ओवरराइड कर रहा था जो कि अच्छा नहीं था क्योंकि उपयोगकर्ता डिफ़ॉल्ट डिफ़ॉल्ट को पूरा करेगा जो कि बहुत शक्तिशाली है।


एक vimcript समाधान

एक समाधान विम्सस्क्रिप्ट और इस तथ्य का उपयोग करना है कि चलो आप एक स्वनिर्धारित पूरा होने वाला फ़ंक्शन बनाते हैं।

इस समाधान का लाभ यह है कि आपको एक अतिरिक्त प्लगइन की आवश्यकता नहीं है जिसे आप केवल एक उपयोगकर्ता-निर्धारित पूरा होने वाला फ़ंक्शन बना सकते हैं और अंतर्निहित पूर्ण सुविधा का उपयोग कर सकते हैं।

मैं आपके उदाहरणों का उपयोग करूँगा 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 से मिलान करने के लिए संभावित वर्गों की सूची से तुलना करता है । यहाँ आप देखते हैं कि मैं एक शब्दकोश लौटाता हूं, जो पूरा होने वाले मेनू को पॉप्युलेट करेगा, लेकिन जब आप प्रलेखन को पढ़ेंगे तो आप देखेंगे कि आप अपने फ़ंक्शन के व्यवहार को और भी अधिक अनुकूलित करने के लिए एक अधिक जटिल शब्दकोश बना सकते हैं।

आपको इस तरह की फ़ाइल के लिए विम को बताना होगा, इस पूर्ण फ़ंक्शन का उपयोग करें जिसे मैंने बनाया था "। ऐसा करने के लिए आपको completefuncआपके द्वारा बनाए गए फ़ंक्शन (यहां csscomplete#CompleteFA) के नाम पर सेट करना होगा और यह सेटिंग फ़ाइल में होनी चाहिए $HOME/.vim/after/ftplugin/{FILETYPE}.vim

1 मेरे फंक्शन में वेरिएबल s:matchesमें सभी संभावित मैच होते हैं। यहां मैंने केवल पठनीयता के लिए कुछ सुझाव दिए हैं, लेकिन आप FontAwesome द्वारा प्रस्तुत सभी कक्षाएं डाल सकते हैं (आप रोमेलिन द्वारा बनाई गई इस फ़ाइल में पूरी सूची पा सकते हैं )।


अगर मुझे विम्सस्क्रिप्ट पसंद नहीं है तो क्या होगा?

एक संभावना प्लगइन YoucompleteMe का उपयोग करना है जो पूर्ण मेनू के साथ खेलने के लिए एक एपीआई प्रदान करता है। आप अजगर फ़ंक्शन बना सकते हैं जो मिलान कार्य करेगा और विम इंटरफ़ेस को पॉप्युलेट करने के लिए एपीआई का उपयोग करेगा। अधिक जानकारी यहाँ


2
CSS और HTML के लिए डिफ़ॉल्ट ओमनी पूर्णता पहले से ही काफी उपयोगी है और आपके पास केवल एक समय में एक ही हो सकता है इसलिए मैं इसके बजाय "उपयोगकर्ता-परिभाषित समापन" का उपयोग करने का सुझाव दूंगा। देख लो :help i_ctrl-x_ctrl-u
रोमेनल

@romainl: आप बिल्कुल सही कह रहे हैं, मैं देखता हूँ कि मैं अपने उत्तर को कैसे ढालूँ।
statox

5

कभी-कभी आप एक कस्टम ऑटो-पूर्णता चाहते हैं जो बिल्ट-इन या उपयोगकर्ता-परिभाषित ऑटोकॉमप्लेयन में से किसी के साथ हस्तक्षेप नहीं करता है। यह स्क्रिप्ट या प्लगइन्स के लिए विशेष रूप से उपयोगी है जो कि कई प्रकार के फ़िलेपेट्स के लिए काम करने का इरादा है।

यह complete() फ़ंक्शन और एक साधारण आवरण के साथ काफी आसान किया जा सकता है ; अधिकांश प्रक्रिया समान है :help complete-functions और स्टेटोक्स के उत्तर में वर्णित है , सिवाय इसके कि आपको अपने स्वयं के मानचित्रण को परिभाषित करने की आवश्यकता है और complete()मूल्य वापस करने के बजाय खुद को कॉल करना होगा ।

यहां एक मूल उदाहरण है, टिप्पणियों को यह बताना चाहिए कि यह कैसे काम करता है।

" 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.