Como iniciar o Vim de uma armadilha e ainda ser capaz de reiniciá-lo depois de suspendê-lo?

2

Eu tenho o seguinte código no meu ~/.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
)

Sua finalidade é instalar uma função nv para iniciar uma instância Vim, bem como um servidor Vim. E se um servidor Vim já estiver em execução, a função deve enviar os argumentos do arquivo que recebeu para o servidor.

Até agora, funcionou bem.

Eu tenho o seguinte mapeamento no meu ~/.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

Sua finalidade é reiniciar o Vim, enviando o sinal USR1 para o shell pai.

Eu também tenho a seguinte armadilha no meu ~/.zshrc que reinicia o Vim quando pega o sinal USR1 .

catch_signal_usr1() {
  trap catch_signal_usr1 USR1
  clear
  vim
}
trap catch_signal_usr1 USR1

Até agora, funcionou bem também.

Mas notei que, se eu suspenso o Vim pressionando C-z , a partir do shell, mesmo que o processo do Vim ainda esteja em execução, não consigo resumi-lo (com $ fg ) porque o shell não possui qualquer trabalho.

Aqui está um zshrc mínimo com o qual posso reproduzir o problema:

catch_signal_usr1() {
  trap catch_signal_usr1 USR1
  vim
}
trap catch_signal_usr1 USR1
func() {
  vim
}

E aqui está um mínimo de vimrc :

nnoremap  <space>R  :call Func()<cr>
function! Func()
    call system('kill -USR1 $(ps -p $(ps -p $$ -o ppid=) -o ppid=)')
    qa!
endfunction

Se eu iniciar o Vim com a função:

$ func

Em seguida, reinicie o Vim pressionando Space R e, em seguida, suspenda-o pressionando C-z , assim que eu voltar ao shell, posso ver o processo do Vim sendo executado:

$ 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

Mas não consigo continuar:

$ fg
fg: no current job

Se eu iniciar o Vim com o comando $ vim em vez da função $ func , posso reiniciar o processo do Vim, suspendê-lo e reiniciá-lo. O problema parece vir da função $ func .

Aqui está o meu ambiente:

  • vim --version : VIM - Vi IMproved 8.1 Compilado pelo usuário
  • Sistema operacional: Ubuntu 16.04.4 LTS
  • Emulador de terminal: rxvt-unicode v9.22
  • Multiplexador de terminais: tmux 2.7
  • $TERM : tmux-256color
  • Shell: zsh 5.5.1

Como iniciar o Vim a partir de uma função e ainda ser capaz de reiniciá-lo depois de suspendê-lo?

Editar:

Mais informações:

(1) What shows up on your terminal when you type Ctrl+Z?

Nada é exibido quando digito C-z .

(A) Se eu iniciar o Vim com o comando $ vim , aqui está o que é exibido depois de pressionar C-z :

ubuntu% vim

zsh: suspended  vim

Posso continuar com $ fg .

(B) Se eu iniciar o Vim com a função $ func :

ubuntu% func
zsh: suspended  func

Também posso retomar com $ fg .

(C) Se eu iniciar o Vim com o comando $ vim , reinicie o Vim pressionando Space R :

ubuntu% vim
zsh: suspended  catch_signal_usr1

Novamente, posso continuar com $ fg .

(D) Mas, se eu iniciar o Vim com a função $ func e reiniciá-lo pressionando Space R :

ubuntu% func
ubuntu%

Nada é exibido quando estou de volta ao prompt e não consigo continuar o Vim com $ fg .

(2) What does your shell say if you type jobs?

$ jobs não tem saída. Aqui está sua saída nos quatro casos anteriores:

(A)

ubuntu% jobs
[1]  + suspended  vim

(B)

ubuntu% jobs
[1]  + suspended (signal)  func

(C)

ubuntu% jobs
[1]  + suspended (signal)  catch_signal_usr1

(D)

ubuntu% jobs
ubuntu%

Parece que o problema é específico de zsh , pelo menos até 5.5.1 , pois não consigo reproduzir com bash 4.4 .

    
por user938271 21.05.2018 / 04:06

1 resposta

1

O problema é iniciar um trabalho em segundo plano a partir de uma armadilha. O trabalho parece ficar "perdido" às vezes. Alterar vim para vim & faz com que o trabalho seja retido algumas vezes, portanto, pode haver uma condição de corrida.

Você pode evitar isso não iniciando o trabalho de uma armadilha. Defina uma bandeira na armadilha e ative o vim fora da armadilha, no gancho precmd . Aqui está uma adaptação do seu exemplo mínimo.

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
}

Você perde a capacidade de abrir o Vim até o primeiro plano enquanto edita um prompt de comando, mas isso não funciona de qualquer maneira, já que o vim e o zsh competiriam pelo terminal.

No seu código real, você pode ter problemas porque está começando a partir de um subshell. Não execute a função nv em um subshell: use chaves {…} around the body, not parentheses. Use local variável IFS to make the IFS 'local.

    
por 21.05.2018 / 23:18