Skip to content

Instantly share code, notes, and snippets.

@thinca
Last active November 23, 2017 12:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thinca/ac438e1139c054b70a740b8f29e5ba0d to your computer and use it in GitHub Desktop.
Save thinca/ac438e1139c054b70a740b8f29e5ba0d to your computer and use it in GitHub Desktop.
Support :command in zsh in Vim (experimental)
# put this code in your .zshrc
if [[ "${VIM_TERMINAL_SHELL}" != "" ]]; then
command_not_found_handler() {
if [[ "${1}" != :* ]]; then
echo "command not found: ${1}" > /dev/stderr
return 127
fi
echo -ne "\e_$*\e\\" > /dev/tty
while [[ ! -f "${VIM_TERMINAL_SHELL}" ]]; do
sleep 0.1
done
cat "${VIM_TERMINAL_SHELL}"
rm "${VIM_TERMINAL_SHELL}"
}
fi
function! s:out(ch, msg) abort
let cmd = matchstr(a:msg, "\e_:\\zs.\\{-}\\ze\e\\\\")
if empty(cmd)
return
endif
let result = ''
try
let result = execute(cmd)
let result = substitute(result, '^\n\(.*\)', '\1\n', '')
catch
let result .= v:exception . "\n"
finally
call writefile(split(result, "\n", 1), s:term_file, 'b')
endtry
endfunction
function! s:terminal() abort
let s:term_file = tempname()
call term_start(['/bin/zsh'], {
\ 'out_cb': function('s:out'),
\ 'env': {'VIM_TERMINAL_SHELL': s:term_file},
\ })
endfunction
command! Terminal call s:terminal()
@thinca
Copy link
Author

thinca commented Nov 4, 2017

Vim 内のターミナル内の zsh 内で :cmd と : 始まりのコマンドを実行するとホスト側の Vim でコマンドを実行して zsh 側に出力の結果を出すスクリプトのテスト。
まだまだいくつか問題がある。

  • Vim 内のターミナルが \e_...\e\\ を無視してくれないので出力に出てしまう
  • :echo 'foo''foo' のクォートが zsh に食われて :echo foo になってしまう
  • zsh しかサポートしていない上に、.zshrc にコードを書く必要がある
  • 別の zsh スクリプトで command_not_found_handler 関数が定義されていた場合、競合する
  • execute() を使っているので :redir を使っているコマンドを実行すると失敗する
  • sleep がちょっとダサい

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment