내 코드는 다음과 같습니다 ~/.zshrc
.
nv() (
if vim --serverlist | grep -q VIM; then
if [[ $# -eq 0 ]]; then
vim
elif [[ $1 == -b ]]; then
shift 1
IFS=' '
vim --remote "$@"
vim --remote-send ":argdo setl binary ft=xxd<cr>"
vim --remote-send ":argdo %!xxd<cr><cr>"
elif [[ $1 == -d ]]; then
shift 1
IFS=' '
vim --remote-send ":tabnew<cr>"
vim --remote "$@"
vim --remote-send ":argdo vsplit<cr>:q<cr>"
vim --remote-send ":windo diffthis<cr>"
elif [[ $1 == -o ]]; then
shift 1
IFS=' '
vim --remote "$@"
vim --remote-send ":argdo split<cr>:q<cr><cr>"
elif [[ $1 == -O ]]; then
shift 1
IFS=' '
vim --remote "$@"
vim --remote-send ":argdo vsplit<cr>:q<cr><cr>"
elif [[ $1 == -p ]]; then
shift 1
IFS=' '
vim --remote "$@"
vim --remote-send ":argdo tabedit<cr>:q<cr>"
elif [[ $1 == -q ]]; then
shift 1
IFS=' '
vim --remote-send ":cexpr system('$*')<cr>"
else
vim --remote "$@"
fi
else
vim -w /tmp/.vimkeys --servername VIM "$@"
fi
)
nv
그 목적은 Vim 인스턴스와 Vim 서버를 시작하기 위한 기능을 설치하는 것입니다 . Vim 서버가 이미 실행 중이라면 이 함수는 수신된 파일 인수를 서버로 보내야 합니다.
여태까지는 그런대로 잘됐다.
내 매핑은 다음과 같습니다 ~/.vimrc
.
nno <silent><unique> <space>R :<c-u>sil call <sid>vim_quit_reload()<cr>
fu! s:vim_quit_reload() abort
sil! update
call system('kill -USR1 $(ps -p $(ps -p $$ -o ppid=) -o ppid=)')
qa!
endfu
USR1
그 목적은 상위 셸에 신호를 보내 Vim을 다시 시작하는 것입니다.
내 프로그램에는 다음과 같은 트랩이 있는데, ~/.zshrc
이는 신호를 포착하면 Vim을 다시 시작합니다 USR1
.
catch_signal_usr1() {
trap catch_signal_usr1 USR1
clear
vim
}
trap catch_signal_usr1 USR1
여태까지는 그런대로 잘됐다.
C-z
하지만 셸에서 를 눌러 Vim을 일시 중지하면 Vim 프로세스가 계속 실행 중임에도 불구하고 $ fg
셸이 아무 작업도 수행하지 않기 때문에 를 사용하여 Vim을 다시 시작할 수 없다는 것을 알았습니다 .
zshrc
이것은 문제를 재현할 수 있는 최소한의 방법입니다.
catch_signal_usr1() {
trap catch_signal_usr1 USR1
vim
}
trap catch_signal_usr1 USR1
func() {
vim
}
최소한의 내용은 다음과 같습니다 vimrc
.
nnoremap <space>R :call Func()<cr>
function! Func()
call system('kill -USR1 $(ps -p $(ps -p $$ -o ppid=) -o ppid=)')
qa!
endfunction
다음 기능으로 Vim을 시작하면:
$ func
그런 다음 Vim 재시작을 누르고 Space R
일시 중지를 눌러 C-z
Vim 프로세스가 실행되는 것을 볼 수 있습니다.
$ ps -efH | grep vim
user 24803 24684 10 03:56 pts/9 00:00:01 vim
user 24990 24684 0 03:56 pts/9 00:00:00 grep vim
하지만 복원할 수 없습니다.
$ fg
fg: no current job
$ vim
함수 대신 명령을 사용하여 Vim을 시작하면 $ func
Vim 프로세스를 다시 시작하고 일시 중지했다가 다시 시작할 수 있습니다. 문제는 기능에 있는 것 같습니다 $ func
.
내 환경은 다음과 같습니다.
vim --version
:VIM - 사용자가 컴파일한 Vi 향상된 8.1- 운영 체제: 우분투 16.04.4 LTS
- 터미널 에뮬레이터: rxvt-unicode v9.22
- 터미널 멀티플렉서: tmux 2.7
$TERM
:tmux-256color- 쉘: zsh 5.5.1
함수에서 Vim을 시작하고 일시 중지한 후에도 다시 시작할 수 있는 방법은 무엇인가요?
편집하다:
추가 정보:
(1) Ctrl+Z를 입력하면 터미널에 무엇이 나타날까요?
입력해도 아무 것도 표시되지 않습니다 C-z
.
(A) $ vim
다음 명령으로 Vim을 시작하면 누르면 다음이 표시됩니다 C-z
.
ubuntu% vim
zsh: suspended vim
나는 그것을 계속 사용할 수 있습니다 $ fg
.
(B) $ func
다음 기능으로 Vim을 시작하면:
ubuntu% func
zsh: suspended func
나도 계속 사용할 수 있어요 $ fg
.
$ vim
(C) Vim을 다음과 같이 시작 하면 Space R
:
ubuntu% vim
zsh: suspended catch_signal_usr1
이번에도 계속 사용할 수 있습니다 $ fg
.
(D) 그러나 $ func
이 기능을 사용하여 Vim을 시작하고 다음을 눌러 다시 시작 하면 Space R
:
ubuntu% func
ubuntu%
프롬프트로 돌아가면 아무것도 표시되지 않으며 Restore Vim을 사용할 수 없습니다 $ fg
.
(2) jobs를 입력하면 쉘에서 무엇을 말합니까?
$ jobs
출력이 없습니다. 이전 네 가지 사례에 대한 출력은 다음과 같습니다.
(ㅏ)
ubuntu% jobs
[1] + suspended vim
(둘)
ubuntu% jobs
[1] + suspended (signal) func
(씨)
ubuntu% jobs
[1] + suspended (signal) catch_signal_usr1
(4)
ubuntu% jobs
ubuntu%
이 문제는 bash로 재현할 수 없기 때문에 zsh
적어도 까지인 것 같습니다 .5.5.1
4.4
답변1
문제는 트랩에서 백그라운드 작업을 시작하는 것입니다. 작업은 때때로 "분실"되는 것 같습니다. 경쟁 조건이 발생할 수 있도록 가끔 작업을 유지 vim
하도록 변경되었습니다 .vim &
트랩에서 작업을 시작하지 않음으로써 이를 방지할 수 있습니다. 트랩에 플래그를 설정하고 트랩 외부의 후크에서 vim을 시작하십시오 precmd
. 이것은 최소한의 예를 적용한 것입니다.
restart_vim=
catch_signal_usr1() {
trap catch_signal_usr1 USR1
restart_vim=1
}
precmd () {
if [[ -n $restart_vim ]]; then
restart_vim=
vim
fi
}
trap catch_signal_usr1 USR1
func() {
vim
}
명령 프롬프트를 편집할 때 Vim을 전경에 표시하는 기능을 잃게 되지만 vim과 zsh가 터미널을 놓고 경쟁하기 때문에 실제로는 작동하지 않습니다.
실제 코드에서는 서브셸에서 vim을 시작하기 때문에 문제가 발생할 수 있습니다. 서브셸에서는 이 함수를 실행 하지 마세요 nv
. 중괄호 { … }를 사용하세요. around the body, not parentheses. Use
로컬 IFS to make the
IFS` 변수 local.