이 maparg()
기능을 사용할 수 있습니다 .
사용자 <C-c>
가 일반 모드에서 무언가를 매핑했는지 테스트하려면 다음과 같이 작성하십시오.
if !empty(maparg('<C-c>', 'n'))
사용자가 무언가를 매핑 {rhs}
하면 변수에 변수 를 저장하려면 다음 과 같이 작성하십시오.
let rhs_save = maparg('<C-c>', 'n')
다음과 같이 매핑에 대한 자세한 정보를 원하는 경우
- 침묵
<silent>
입니까 ( 논쟁)?
- 현재 버퍼에 로컬
<buffer>
입니까 ( 인수)?
- 은
{rhs}
식 (평가 <expr>
인자)?
{rhs}
( nnoremap
vs nmap
)를 다시 매핑 합니까?
- 사용자에게로 시작하는 다른 매핑이있는 경우
<C-c>
Vim은 더 많은 문자가 입력 될 때까지 기다 립 <nowait>
니까 ( 인수)?
- ...
그런 다음 세 번째와 네 번째 인수를 줄 수 : 0
와 1
.
0
약어가 아닌 매핑을 찾고 1
있기 때문에 {rhs}
값 뿐만 아니라 최대 정보를 가진 사전을 원하기 때문입니다 .
let map_save = maparg('<C-c>', 'n', 0, 1)
사용자가 자신의 매핑에 특별한 인수를 사용하지 않고을 다시 매핑하지 않고 {rhs}
복원하기 위해 간단히 다음과 같이 작성할 수 있습니다.
let rhs_save = maparg('<C-c>', 'n')
" do some stuff which changes the mapping
exe 'nnoremap <C-c> ' . rhs_save
또는 가능한 모든 인수를 확인하고 복원하십시오.
let map_save = maparg('<C-c>', 'n', 0, 1)
" do some stuff which changes the mapping
exe (map_save.noremap ? 'nnoremap' : 'nmap') .
\ (map_save.buffer ? ' <buffer> ' : '') .
\ (map_save.expr ? ' <expr> ' : '') .
\ (map_save.nowait ? ' <nowait> ' : '') .
\ (map_save.silent ? ' <silent> ' : '') .
\ ' <C-c> ' .
\ map_save.rhs
편집 : 죄송합니다. 사용자가 {rhs}
매핑 에서 스크립트 로컬 함수를 호출하면 예상대로 작동하지 않는다는 것을 알았습니다 .
사용자가 자신의 내부에 다음과 같은 매핑이 있다고 가정합니다 vimrc
.
nnoremap <C-c> :<C-U>call <SID>FuncA()<CR>
function! s:FuncA()
echo 'hello world!'
endfunction
때리면 <C-c>
메시지를 표시합니다 hello world!
.
플러그인에서 모든 정보가 담긴 사전을 저장 한 다음 일시적으로 다음과 같이 매핑을 변경하십시오.
let map_save = maparg('<C-c>', 'n', 0, 1)
nnoremap <C-c> :<C-U>call <SID>FuncB()<CR>
function! s:FuncB()
echo 'bye all!'
endfunction
이제가 표시됩니다 bye all!
. 플러그인이 작동하며 끝났을 때 이전 명령으로 매핑을 복원하려고 시도합니다.
아마도 다음과 같은 메시지로 실패 할 것입니다.
E117: Unknown function: <SNR>61_FuncA
61
매핑 명령이 실행될 스크립트의 식별자 일뿐입니다. 다른 숫자 일 수 있습니다. 플러그인이 사용자 시스템에서 제공 한 42 번째 파일 인 경우이 파일은입니다 42
.
스크립트 내에서 매핑 명령이 실행될 때 Vim은 자동으로 표기법 <SID>
을 특수 키 코드로 변환 한 <SNR>
다음 스크립트 고유의 숫자와 밑줄을 표시합니다. 사용자가을 때 <C-c>
매핑이 스크립트 외부에서 실행되므로 어떤 스크립트 FuncA()
가 정의 되어 있는지 알 수 없기 때문에이 작업을 수행해야합니다 .
문제는 원래 매핑이 플러그인과 다른 스크립트로 제공 되었기 때문에 자동 번역이 잘못되었습니다. 스크립트의 식별자를 사용하지만 사용자의 식별자를 사용해야합니다 vimrc
.
그러나 수동으로 번역을 할 수 있습니다. 사전 map_save
에는 'sid'
값이 올바른 식별자 인 키가 포함되어 있습니다 .
따라서 이전 복원 명령을보다 강력하게 만들려면 다음 map_save.rhs
과 같이 바꾸십시오 .
substitute(map_save.rhs, '<SID>', '<SNR>' . map_save.sid . '_', 'g')
경우 {rhs}
원래의 매핑이 포함 된 <SID>
, 그것은 제대로 번역해야합니다. 그렇지 않으면 아무것도 변경되지 않아야합니다.
코드를 약간 줄이려면 특수 인수를 처리하는 4 줄을 다음과 같이 바꿀 수 있습니다.
join(map(['buffer', 'expr', 'nowait', 'silent'], 'map_save[v:val] ? "<" . v:val . ">": ""'))
map()
기능은 목록에서 각 항목을 변환해야 ['buffer', 'expr', 'nowait', 'silent']
대응하는 매핑 인수에 있지만, 주요 내부는 경우에만 map_save
비 제로이다. 그리고 join()
모든 항목을 문자열로 결합해야합니다.
따라서 맵핑을 저장하고 복원하는보다 강력한 방법은 다음과 같습니다.
let map_save = maparg('<C-c>', 'n', 0, 1)
" do some stuff which changes the mapping
exe (map_save.noremap ? 'nnoremap' : 'nmap') .
\ join(map(['buffer', 'expr', 'nowait', 'silent'], 'map_save[v:val] ? "<" . v:val . ">": ""')) .
\ map_save.lhs . ' ' .
\ substitute(map_save.rhs, '<SID>', '<SNR>' . map_save.sid . '_', 'g')
편집 2 :
드로잉 플러그인에서 매핑을 저장하고 복원하는 방법과 동일한 문제에 직면하고 있습니다. 그리고 나는 그것을 작성할 당시 초기 답변에서 보지 못한 두 가지 문제를 발견했다고 생각합니다. 죄송합니다.
첫 번째 문제는 사용자가 <C-c>
전역 매핑뿐만 아니라 버퍼 로컬 매핑에도 사용한다고 가정합니다 . 예:
nnoremap <C-c> :echo 'global mapping'<CR>
nnoremap <buffer> <C-c> :echo 'local mapping'<CR>
이 경우 maparg()
로컬 매핑에 우선 순위를 부여합니다.
:echo maparg('<C-c>', 'n', 0, 1)
---> {'silent': 0, 'noremap': 1, 'lhs': '<C-C>', 'mode': 'n', 'nowait': 0, 'expr': 0, 'sid': 7, 'rhs': ':echo ''local mapping''<CR>', 'buffer': 1}
다음에서 확인됩니다 :h maparg()
:
The mappings local to the current buffer are checked first,
then the global mappings.
그러나 버퍼 로컬 매핑에 관심이 없거나 전역 맵을 원할 수도 있습니다.
글로벌 매핑에 대한 정보를 확실하게 얻는 유일한 방법은 동일한 키를 사용하여 잠재적 인 섀도 잉 버퍼 로컬 매핑을 일시적으로 매핑 해제하는 것입니다.
4 단계로 수행 할 수 있습니다.
- 키를 사용하여 (잠재적) 버퍼 로컬 매핑 저장
<C-c>
:silent! nunmap <buffer> <C-c>
(잠재적) 버퍼 로컬 매핑을 삭제하기 위해 실행
- 전역 매핑 저장 (
maparg('<C-c>', 'n', 0, 1)
)
- 버퍼 로컬 매핑을 복원
두 번째 문제는 다음과 같습니다. 사용자가에 아무것도 매핑하지 않았다고 가정 하면 빈 사전이 <C-c>
출력 maparg()
됩니다. 이 경우 복원 프로세스는 매핑 설치 ( :nnoremap
)가 아니라 매핑 파괴 ( :nunmap
)로 구성됩니다.
이 두 가지 새로운 문제를 해결하기 위해이 기능을 사용하여 매핑을 저장할 수 있습니다.
fu! Save_mappings(keys, mode, global) abort
let mappings = {}
if a:global
for l:key in a:keys
let buf_local_map = maparg(l:key, a:mode, 0, 1)
sil! exe a:mode.'unmap <buffer> '.l:key
let map_info = maparg(l:key, a:mode, 0, 1)
let mappings[l:key] = !empty(map_info)
\ ? map_info
\ : {
\ 'unmapped' : 1,
\ 'buffer' : 0,
\ 'lhs' : l:key,
\ 'mode' : a:mode,
\ }
call Restore_mappings({l:key : buf_local_map})
endfor
else
for l:key in a:keys
let map_info = maparg(l:key, a:mode, 0, 1)
let mappings[l:key] = !empty(map_info)
\ ? map_info
\ : {
\ 'unmapped' : 1,
\ 'buffer' : 1,
\ 'lhs' : l:key,
\ 'mode' : a:mode,
\ }
endfor
endif
return mappings
endfu
... 그리고 이것들은 그것들을 복원합니다 :
fu! Restore_mappings(mappings) abort
for mapping in values(a:mappings)
if !has_key(mapping, 'unmapped') && !empty(mapping)
exe mapping.mode
\ . (mapping.noremap ? 'noremap ' : 'map ')
\ . (mapping.buffer ? ' <buffer> ' : '')
\ . (mapping.expr ? ' <expr> ' : '')
\ . (mapping.nowait ? ' <nowait> ' : '')
\ . (mapping.silent ? ' <silent> ' : '')
\ . mapping.lhs
\ . ' '
\ . substitute(mapping.rhs, '<SID>', '<SNR>'.mapping.sid.'_', 'g')
elseif has_key(mapping, 'unmapped')
sil! exe mapping.mode.'unmap '
\ .(mapping.buffer ? ' <buffer> ' : '')
\ . mapping.lhs
endif
endfor
endfu
이 Save_mappings()
함수는 매핑을 저장하는 데 사용될 수 있습니다.
세 가지 주장이 필요합니다.
- 키 목록; 예:
['<C-a>', '<C-b>', '<C-c>']
- 모드; 예 :
n
일반 모드 또는 x
시각 모드
- 부울 플래그; 이 경우
1
전역 매핑에 관심이 0
있고 로컬 매핑에 관심이 있음을 의미 합니다.
그것으로, 당신은 키를 사용하여 글로벌 매핑을 절약 할 수 C-a
, C-b
및 C-c
사전 내에서, 정상 모드에서 :
let your_saved_mappings = Save_mappings(['<C-a>', '<C-b>', '<C-c>'], 'n', 1)
그런 다음 나중에 매핑을 복원하려는 경우 Restore_mappings()
모든 정보를 포함하는 사전을 인수로 전달하여을 호출 할 수 있습니다 .
call Restore_mappings(your_saved_mappings)
버퍼 로컬 맵핑을 저장 / 복원 할 때 세 번째 문제점이있을 수 있습니다. 맵핑을 저장 한 시점과이를 복원하려고하는 시점 사이에 현재 버퍼가 변경되었을 수 있습니다.
이 경우 Save_mappings()
현재 버퍼 수 ( bufnr('%')
) 를 저장하여 기능을 향상시킬 수 있습니다 .
그런 다음 Restore_mappings()
이 정보를 사용하여 올바른 버퍼에서 버퍼 로컬 매핑을 복원합니다. 우리는 아마도 :bufdo
명령을 사용하고 , 후자를 접두어로 카운트하고 (이전에 저장된 버퍼 번호와 일치) 맵핑 명령으로 접미사를 붙일 수 있습니다.
아마도 다음과 같은 것입니다 :
:{original buffer number}bufdo {mapping command}
그 동안 버퍼를 bufexists()
삭제할 수 있기 때문에 함수를 사용하여 버퍼가 여전히 존재하는지 먼저 확인해야합니다 .