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 nv
função para iniciar uma instância do Vim, bem como um servidor Vim. E se um servidor Vim já estiver em execução, a função deve enviar os argumentos de arquivo recebidos 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 ele 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 suspender o Vim pressionando C-z
, no shell, mesmo que o processo do Vim ainda esteja em execução, não consigo retomá-lo (com $ fg
) porque o shell não tem nenhum trabalho.
Aqui está um mínimo zshrc
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 vai um mínimo 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
, em seguida, suspenda-o pressionando C-z
, quando voltar ao shell, posso ver o processo do Vim em execução:
$ 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 resumir:
$ fg
fg: no current job
Se eu iniciar o Vim com o $ vim
comando em vez da $ func
função, posso reiniciar o processo do Vim, suspendê-lo e retomá-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 terminal: tmux 2.7
$TERM
: tmux-256color- Shell: zsh 5.5.1
Como iniciar o Vim a partir de uma função e ainda poder retomá-lo após suspendê-lo?
Editar:
Mais Informações:
(1) O que aparece no seu terminal quando você digita Ctrl+Z?
Nada é exibido quando eu digito C-z
.
(A) Se eu iniciar o Vim com o $ vim
comando, aqui está o que é exibido depois de pressionar C-z
:
ubuntu% vim
zsh: suspended vim
Posso retomar com $ fg
.
(B) Se eu iniciar o Vim com a $ func
função:
ubuntu% func
zsh: suspended func
Eu também posso retomar com $ fg
.
(C) Se eu iniciar o Vim com o $ vim
comando, reinicie o Vim pressionando Space R
:
ubuntu% vim
zsh: suspended catch_signal_usr1
Mais uma vez, posso continuar com $ fg
.
(D) Mas, se eu iniciar o Vim com a $ func
função e reiniciá-lo pressionando Space R
:
ubuntu% func
ubuntu%
Nada é exibido quando volto ao prompt e não consigo retomar o Vim com $ fg
.
(2) O que seu shell diz se você digitar jobs?
$ jobs
não tem saída. Aqui está sua saída nos quatro casos anteriores:
(UMA)
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
.
O problema é iniciar um trabalho em segundo plano a partir de uma armadilha. O trabalho parece ficar “perdido” às vezes. Mudar
vim
paravim &
faz com que o trabalho seja retido às vezes, então 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 acione o vim fora da armadilha, no
precmd
gancho. Aqui está uma adaptação do seu exemplo mínimo.Você perde a capacidade de colocar o Vim em primeiro plano ao editar um prompt de comando, mas isso realmente não funciona, pois o vim e o zsh estariam competindo pelo terminal.
Em seu código real, você pode ter problemas porque está iniciando o vim a partir de um subshell. Não execute a
nv
função em um subshell: use chaves { … }around the body, not parentheses. Use
local IFSto make the
IFS` variável local.