5 ms·
Just for the other side of the picture, I live in vim and use it as my terminal multiplexer. Vim’s my shell. I have thousands of buffers in vim and practically
by qazxcvbnm 2y ago
Just for the other side of the picture, I live in vim and use it as my terminal multiplexer. Vim’s my shell. I have thousands of buffers in vim and practically never leave it. I’ve used terminal multiplexers for years before I switched to vim in that capacity and never looked back. The integration it’s allowed between all my buffers and commands and shells is difficult to match in my opinion.
- exogenousdata 2y agoAs a 3rd anecdote, I used vim for 10 years as my primary editor and “shell”. Then 10 years ago I learned tmux and fell in love with its window multiplexing. Now I use vim strictly as an editor/splitter. But I use tmux to split my code from my repl window. And maintain multiple windows where I’m working on different projects.
- rand0m4r 2y agoI'm going to try this. I use tmux but the idea of being able to use vim for everything seems nice. If you have tips/suggestions, I'm interested.
- qazxcvbnm 2y agoFor me, some of the things that's really important for a terminal multiplexer include: 1) Keybindings having no conflicts with other terminal applications. For that, vim's default window-management key of <C-w> is unfortunate, as it is very important for delete words in bash and readline. I remap that to <C-@> (CTRL-Space) instead, which is basically used by no terminal program that I am aware of. The other key binding that trips me up are the default vim keybindings to kill the terminal (<C-w><C-c>). If I am midway attempting a window action, but realise something is taking too long and want to stop the job, the keybinding kills my whole shell. If I really want to kill my terminal, I can always issue ZQ or :q! in normal mode. 2) Change my cursor shapes based on which mode I'm in (normal, insert, or terminal/command), which helps me easily tell the mode. 3) Improve the default keybinding for going from terminal back to terminal normal mode. I find the default keybindings <C-\><C-n> and <C-w>N too difficult to type because I need to use this binding very much. 4) Be able to move between windows with the same, consistent set of keybindings no matter which mode I'm in (e.g. not having to go back to normal mode first, from insert or terminal mode). In the same vein, when I land on a buffer I always expect to be in normal mode, so I can start moving around immediately and yank stuff without remembering whether I'm in a terminal or a non-terminal buffer. When I need to manipulate the terminal program I can always `i` or `a`. I have quite a few other customisations to my vim terminal, but I think these are the most essential ones. vimrc for 1) set termwinkey=<C-@> noremap <C-@> <C-w> noremap <C-@><CR> <C-w><CR> noremap! <C-@> <Esc><C-w> noremap <C-@>c <Nop> noremap <C-@><C-c> <Nop> noremap <C-@><C-q> <Nop> noremap! <C-@>c <Nop> noremap! <C-@><C-c> <Nop> noremap! <C-@><C-q> <Nop> tnoremap <C-@>c <Nop> tnoremap <C-@><C-c> <Nop> tnoremap <C-@><C-q> <Nop> noremap <C-@>q <Nop> noremap! <C-@>q <Nop> tnoremap <C-@>q <Nop> vimrc for 2) and 3) augroup term_normal au! autocmd WinNew * let w:winnew = 1 autocmd CmdlineEnter * let w:outcmd = 0 autocmd CmdlineLeave * let w:outcmd = 1 autocmd WinEnter * if exists ('w:winnew') | unlet w:winnew | if (mode() == 't') | call Termcursor () | endif | elseif get(w:, 'outcmd', 1) && (mode() == 't') | call feedkeys("\<C-@>N", "") | endif autocmd WinLeave * if (mode() == 't') && (! exists('w:tu')) | call feedkeys("\<C-@>N", 'x') | call Normalcursor () | elseif (mode(1) == 'nt') && (exists('w:tu')) | call feedkeys("i", 'ix') | endif tmap <expr> <C-@><C-@> ((mode() == 't') && get(w:, 'outcmd', 1)) ? '<C-@>N' : '<C-@><C-@>' augroup end let &t_SI = "\e[6 q\e]12;#FF00DF\<C-g>" let &t_EI = "\e[2 q\e]12;#FF00DF\<C-g>" let &t_ti = "\e[4 q\e]12;#FF00DF\<C-g>" let &t_te = "\e[2 q\e]12;#FF00DF\<C-g>" let &t_Us = "\e[4:2m" let &t_ds = "\e[4:4m" let &t_Ds = "\e[58:5:4m\e[4:5m" function! Normalcursor () let &t_ve ="\e[2 q\e]12;#FF00DF\<C-g>" let &t_vi ="\e[2 q\e]12;#FF00DF\<C-g>" endfunction function! Echonormalcursor () call echoraw("\e[2 q\e]12;#FF00DF\<C-g>") endfunction function! Termcursor () let &t_ve ="\e[4 q\e]12;#FF00DF\<C-g>" let &t_vi ="\e[4 q\e]12;#FF00DF\<C-g>" endfunction function! Echotermcursor () call echoraw("\e[4 q\e]12;#FF00DF\<C-g>") endfunction augroup termcursor au! autocmd ModeChanged *:n* let &t_ve ="\e[2 q\e]12;#FF00DF\<C-g>" autocmd ModeChanged *:n* let &t_vi ="\e[2 q\e]12;#FF00DF\<C-g>" autocmd ModeChanged i:* if &t_ve == "" | let &t_ve ="\e[2 q\e]12;#FF00DF\<C-g>" | endif autocmd ModeChanged i:* if &t_vi == "" | let &t_vi ="\e[2 q\e]12;#FF00DF\<C-g>" | endif autocmd ModeChanged *:i* let &t_ve ="" autocmd ModeChanged *:i* let &t_vi ="" autocmd ModeChanged *:t call echoraw("\e[4 q\e]12;#FF00DF\<C-g>") autocmd ModeChanged *:t let &t_ve ="\e[4 q\e]12;#FF00DF\<C-g>" autocmd ModeChanged *:t let &t_vi ="\e[4 q\e]12;#FF00DF\<C-g>" autocmd ModeChanged t:* call echoraw("\e[2 q\e]12;#FF00DF\<C-g>") autocmd ModeChanged t:* if (mode(1) != 'ct') | let &t_ve ="\e[2 q\e]12;#FF00DF\<C-g>" | endif autocmd ModeChanged t:* if (mode(1) != 'ct') | let &t_vi ="\e[2 q\e]12;#FF00DF\<C-g>" | endif let g:cmdlinedepth = 0 autocmd CmdlineEnter * let g:cmdlinedepth = g:cmdlinedepth + 1 | let &t_ve = "\e[4 q\e]12;#FF00DF\<C-g>" | let &t_vi = "\e[4 q\e]12;#FF00DF\<C-g>" autocmd CmdlineLeave * let g:cmdlinedepth = g:cmdlinedepth - 1 | if g:cmdlinedepth == 0 | if (mode(1) == 'ct') | call Termcursor () | else | call Normalcursor () | endif | endif autocmd CmdwinEnter * let &t_ve ="\e[2 q\e]12;#FF00DF\<C-g>" | let &t_vi ="\e[2 q\e]12;#FF00DF\<C-g>" autocmd CmdwinLeave * let &t_ve = "\e[4 q\e]12;#FF00DF\<C-g>" | let &t_vi = "\e[4 q\e]12;#FF00DF\<C-g>" " autocmd WinEnter * call echoraw("\e[2 q\e]12;#FF00DF\<C-g>")
- qazxcvbnm 2y ago(equivalently, if you use screen; the key point is the \eP and the \e\\ between which the real xterm escape codes go, or else screen will eat your escape codes which will never see the light of day) augroup term_normal au! autocmd WinNew * let w:winnew = 1 autocmd CmdlineEnter * let w:outcmd = 0 autocmd CmdlineLeave * let w:outcmd = 1 autocmd WinEnter * if exists ('w:winnew') | unlet w:winnew | if (mode() == 't') | call Termcursor () | endif | elseif get(w:, 'outcmd', 1) && (mode() == 't') | call feedkeys("\<C-@>N", "") | endif autocmd WinLeave * if (mode() == 't') && (! exists('w:tu')) | call feedkeys("\<C-@>N", 'x') | call Normalcursor () | elseif (mode(1) == 'nt') && (exists('w:tu')) | call feedkeys("i", 'ix') | endif tmap <expr> <C-@><C-@> ((mode() == 't') && get(w:, 'outcmd', 1)) ? '<C-@>N' : '<C-@><C-@>' augroup end let &t_SI = "\eP\e[6 q\e]12;#FF00DF\<C-g>\e\\" let &t_EI = "\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" let &t_ti = "\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" let &t_te = "\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" let &t_Us = "\eP\e[4:2m\e\\" let &t_ds = "\eP\e[4:4m\e\\" let &t_Ds = "\eP\e[58:5:3m\e[4:5m\e\\" function! Normalcursor () let &t_ve ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" let &t_vi ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" endfunction function! Echonormalcursor () call echoraw("\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\") endfunction function! Termcursor () let &t_ve ="\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" let &t_vi ="\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" endfunction function! Echotermcursor () call echoraw("\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\") endfunction augroup termcursor au! autocmd ModeChanged *:n* let &t_ve ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" autocmd ModeChanged *:n* let &t_vi ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" autocmd ModeChanged i:* if &t_ve == "" | let &t_ve ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" | endif autocmd ModeChanged i:* if &t_vi == "" | let &t_vi ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" | endif autocmd ModeChanged *:i* let &t_ve ="" autocmd ModeChanged *:i* let &t_vi ="" autocmd ModeChanged *:t call echoraw("\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\") autocmd ModeChanged *:t let &t_ve ="\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" autocmd ModeChanged *:t let &t_vi ="\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" autocmd ModeChanged t:* call echoraw("\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\") autocmd ModeChanged t:* if (mode(1) != 'ct') | let &t_ve ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" | endif autocmd ModeChanged t:* if (mode(1) != 'ct') | let &t_vi ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" | endif " TODO -- doesnt restore from redraw? let g:cmdlinedepth = 0 autocmd CmdlineEnter * let g:cmdlinedepth = g:cmdlinedepth + 1 | let &t_ve = "\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" | let &t_vi = "\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" autocmd CmdlineLeave * let g:cmdlinedepth = g:cmdlinedepth - 1 | if g:cmdlinedepth == 0 | if (mode(1) == 'ct') | call Termcursor () | else | call Normalcursor () | endif | endif autocmd CmdwinEnter * let &t_ve ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" | let &t_vi ="\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\" autocmd CmdwinLeave * let &t_ve = "\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" | let &t_vi = "\eP\e[4 q\e]12;#FF00DF\<C-g>\e\\" " autocmd WinEnter * call echoraw("\eP\e[2 q\e]12;#FF00DF\<C-g>\e\\") augroup end