2017-02-24 55 views
2

我經常將文本行轉換爲數組。例如,這樣的:Vim:創建需要移動的自定義命令

Monday 
Tuesday 
Wednesday 

變爲:

[ 
    'Monday', 
    'Tuesday', 
    'Wednesday', 
] 

我可以使地圖改變所述線中的一個(例如Monday'Monday',)像這樣:

:nnoremap gsa ^i'<Esc>A,

我想要做的是讓該命令採取移動或文本對象,以便我可以執行它,如gsaipgsip3j

我該如何做到這一點?

回答

1

您可以使用'operatorfunc'[email protected]來製作帶有 議案的地圖。該幫助給出了關於 :map-operator主題下的完整說明和示例。基本上你可以在地圖上設置你想要的功能 ,然後使用[email protected]。 Vim將等待一個動作,然後設置 標記'[']並調用你的函數。

在你的功能裏面你可以發揮創意,在這裏我只是簡單地提出了一個例子,說明如何將這個原理應用到你需要的東西上。

:nnoremap <silent> gsa :set opfunc=TransformToArray<cr>[email protected] 

function! TransformToArray(type) 
    if a:type == 'line' 
    let s=line("'[") " saving beginning mark 
    ']s/\(\s*\).*\zs/\r\1] 
    exec s ",']-1s/\\s*\\zs.*/ '&'," 
    exec s 's/\(\s*\)\zs\ze /[\r\1' 
    elseif a:type == 'char' 
    " ... 
    endif 
endfunction 
+0

爲什麼不改變'「轉到\ ]」'去''去]''? –

+1

@ Meninx-メネンックス對我來說是需要的,因爲縮進設置。由於前一行縮進2,因此在插入右大括號之前,先用bs將其刪除。這只是一個快速的解決方案,需要更多的思想來提高:) – sidyll

+0

@ Meninx-メネンックス我改變了它,現在看起來更加緊湊和更少冗餘。 – sidyll

0

準確地說,您似乎想要將映射應用於運動或文本對象所覆蓋的每條線。 vipv2j

可以經由視覺模式建立這樣範圍。然後,您可以使用:normal gsa(鍵入;如果從可視模式進入命令行模式,Vim將自動插入選定範圍(:'<,'>))將自定義映射應用於每一行(光標位於每個行的第一列行,根據:help :normal-range)。

1

將這個到您的.vimrc文件:

vnoremap <silent> gsa :call Brackets()<CR> 

function! Brackets() 
    execute "normal! I'" 
    if line(".") == a:lastline 
     execute "normal! A'\<cr>]" 
     execute a:firstline."s:^:[\r:" 
    else 
     execute "normal! A'," 
    endif 
endfunction 

選擇您想例如vip的視線塊,然後按gsa

0

如果你真的想在最後一項後面添加一個逗號,我會這樣做,以保持寄存器不變。

function! s:to_list() range abort 
    let words = getline(a:firstline, a:lastline) 
    exe a:firstline.','.a:lastline.'d _' " remove the "_" to fill the unnamed register 
    let lines = ['['] + map(words, '" ".string(v:val).","') + [']'] 
    call append(a:firstline-1, lines) 
endfunction 

command! -nargs=0 -range=% ToList <line1>,<line2>call s:to_list() 

爲了擺脫最後兩行的,我已經編輯的map()結果的最後一個項目或玩join()

let lines = "[\n" . join(map(words, '" ".string(v:val)'), ",\n") . "\n]" 
    put!=lines