トラップでVimを起動して一時停止した後でも再起動する方法は?

トラップでVimを起動して一時停止した後でも再起動する方法は?

私のコードは次のとおりです~/.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-zVimプロセスが実行されていることを確認できます。

$ 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 を起動すると、$ funcVim プロセスを再起動し、一時停止して再起動できます。問題は機能にあるようです$ 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.14.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 theIFS`変数local。

関連情報