私のコードは次のとおりです~/.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- オペレーティングシステム:Ubuntu 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
出力がありません。前の4つのケースの出力は次のとおりです。
(ㅏ)
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。