6 ** 5

軽率なアウトプットを心がけます

VimでVisual Studio Codeのような括弧補完がしたい

1.

{ + Enterで括弧を補完して改行する

inoremap {<Enter> {}<ESC>i<Enter><ESC>x<S-o>

f:id:fun7776:20210621170238g:plain

2.

次の文字に依存して括弧を補完するかどうか決める

function! BracketComplement(num) abort
    let LList = ["(", "[", "{"]
    let RList = [")", "]", "}"]
    let pos = col(".") - 1
    let str = getline(".")
    let tmpl = pos == 0 ? "" : str[:pos - 1]
    let tmpr = str[pos:]

    let out = ""
    let flg = 0
   "次の文字がOKリストの要素であれば括弧を補完する
    let OK = [' ', '', ')', ']', '}']
    for c in OK
        if tmpr[0] == c
            let flg = 1
        endif
    endfor
    if flg
        let tmpl = tmpl . LList[a:num] . RList[a:num]
    else
        let tmpl = tmpl . LList[a:num]
    endif
    let str = tmpl . tmpr
    call setline('.', str)
    call cursor(line("."), pos+2)
    return out
endfunction

f:id:fun7776:20210621170353g:plain

3.

インサートモード中に閉じ括弧上で閉じ括弧を入力すると括弧から出る。

function! BracketOut(num) abort
    let List = [')', ']', '}']
    let pos = col(".") - 1
    let str = getline(".")
    let tmpl = pos == 0 ? "" : str[:pos - 1]
    let tmpr = str[pos:]
    if str[pos] == List[a:num]
        call cursor(line("."), pos+2)
    else 
        let str = tmpl . List[a:num] . tmpr
        call setline('.', str)
        call cursor(line("."), pos+2)
    endif
    return ''
endfunctio

f:id:fun7776:20210621170514g:plain

4.

2と3の内容をシングルクオーテーション、ダブルクオーテーションにも対応させる。

function! QuotationFunc(num) abort
    let List = ['"', "'"]
    let pos = col(".") - 1
    let str = getline(".")
    let tmpl = pos == 0 ? "" : str[:pos - 1]
    let tmpr = str[pos:]
    if str[pos] == List[a:num]
        call cursor(line("."), pos+2)
    else 
        let flg = 0
       "次の文字がOKリストの要素であれば括弧を補完する
        let OK = [' ', '', ')', ']', '}']
        for c in OK
            if tmpr[0] == c
                let flg = 1
            endif
        endfor
        if flg
            let tmpl = tmpl . List[a:num] . List[a:num]
        else
            let tmpl = tmpl . List[a:num]
        endif
        let str = tmpl . tmpr
        call setline('.', str)
        call cursor(line("."), pos+2)
    endif
    return ""
endfunction

f:id:fun7776:20210621170701g:plain

5.

隣接した括弧の開き記号を消すと同時に閉じ記号も削除する

function! DeleteParenthesesAdjoin() abort
    let pos = col(".") - 1
    let str = getline(".")
    let parentLList = ["(", "[", "{", "\'", "\""]
    let parentRList = [")", "]", "}", "\'", "\""]
    let cnt = 0

    let output = ""

   "カーソルが行末の場合
    if pos == strlen(str)
        return "\b"
    endif
    for c in parentLList
       "カーソルの左右が同種の括弧
        if str[pos-1] == c && str[pos] == parentRList[cnt]
            call cursor(line("."), pos + 2)
            let output = "\b"
            break
        endif
        let cnt += 1
    endfor
    return output."\b"
endfunction

引用:Vimで隣接した括弧の開き記号を消すと同時に閉じ記号も削除するスクリプト - Qiita f:id:fun7776:20210621170619g:plain

これらの関数を文字に割り当てる(これがないと動きません)

inoremap <silent> ( <C-r>=BracketComplement(0)<CR>
inoremap <silent> [ <C-r>=BracketComplement(1)<CR>
inoremap <silent> { <C-r>=BracketComplement(2)<CR>
inoremap <silent> ) <C-r>=BracketOut(0)<CR>
inoremap <silent> ] <C-r>=BracketOut(1)<CR>
inoremap <silent> } <C-r>=BracketOut(2)<CR>
inoremap <silent> " <C-r>=QuotationFunc(0)<CR>
inoremap <silent> ' <C-r>=QuotationFunc(1)<CR>
inoremap <silent> <BS> <C-r>=DeleteParenthesesAdjoin()<CR>

参考

Vimで隣接した括弧の開き記号を消すと同時に閉じ記号も削除するスクリプト - Qiita