make casts local
This commit is contained in:
116
content/posts/vim-stt/index.md
Normal file
116
content/posts/vim-stt/index.md
Normal file
@ -0,0 +1,116 @@
|
||||
---
|
||||
title: Vim Send To Terminal
|
||||
date: 2023-07-26T15:23:22-04:00
|
||||
asciinema: true
|
||||
tags:
|
||||
- vim
|
||||
categories:
|
||||
- development
|
||||
---
|
||||
|
||||
### Semi automatic scripts with vim `:terminal`
|
||||
|
||||
<!--more-->
|
||||
|
||||
Sometimes, fully automating a task is not worth the effort. So I end up running
|
||||
a set of commands usually from a cheat sheet text file slightly modifying the
|
||||
arguments each time. I used the below in vim to send line under cursor to vim's
|
||||
`:terminal` open in a split
|
||||
```vim
|
||||
:call term_list()[0]->term_sendkeys(getline('.') .. "\<CR>")
|
||||
```
|
||||
To send another line `@:` and then for every other line `@@`. This works because, last
|
||||
command run is stored in `register :` and the last macro executed using `@` is
|
||||
stored in `register @`.
|
||||
|
||||
To do the same another day, `:call te<UP arrow>` to recall from vim's command
|
||||
history. Or better, add a function and mapping.
|
||||
|
||||
```vim
|
||||
def SendToTerminal()
|
||||
if term_list()->empty()
|
||||
echomsg "No Terminal windows found"
|
||||
return
|
||||
endif
|
||||
terms[0]->term_sendkeys(getline(.) .. "\<CR>")
|
||||
enddef
|
||||
|
||||
nnoremap <silent><leader>s call SendToTerminal()<CR>
|
||||
```
|
||||
|
||||
### More cool features
|
||||
|
||||
For most use-cases that was enough. However added a few more nice features
|
||||
which is very helpful when you need it
|
||||
|
||||
1. Support sending a range of lines (visual selection) at a time. E.g. Send a
|
||||
function block to a python shell
|
||||
2. Add a delay between lines in milliseconds. This is useful when the previous
|
||||
command reads from standard input and takes some time to complete
|
||||
3. Support sending `ctrl` characters like `ctrl d`, `ctrl c` etc,
|
||||
|
||||
```vim
|
||||
def g:SendRangeToTerminal(start_line: number, end_line: number)
|
||||
const terms = term_list()
|
||||
if terms->empty()
|
||||
echomsg "No Terminal windows found"
|
||||
return
|
||||
endif
|
||||
var line_num = start_line
|
||||
for line in getline(start_line, end_line)
|
||||
line_num += 1
|
||||
const spl_cmd = line->matchlist('\vVIMST (sleep|ctrl) ([0-9]+|[a-z])')
|
||||
if !spl_cmd->empty()
|
||||
const [_, cmd, arg1; _] = spl_cmd
|
||||
if cmd == "sleep"
|
||||
timer_start(str2nr(arg1), (_) => g:SendRangeToTerminal(line_num, end_line))
|
||||
return
|
||||
elseif cmd == "ctrl"
|
||||
terms[0]->term_sendkeys(nr2char(char2nr(arg1) - 96))
|
||||
continue
|
||||
endif
|
||||
endif
|
||||
terms[0]->term_sendkeys(line .. "\<CR>")
|
||||
endfor
|
||||
enddef
|
||||
|
||||
command -range -bar SendToTerm :call g:SendRangeToTerminal(<line1>, <line2>)
|
||||
vnoremap <silent><leader>s :SendToTerm<CR>
|
||||
nnoremap <silent><leader>s :SendToTerm<CR>
|
||||
```
|
||||
|
||||
### More cool mapping
|
||||
|
||||
Wouldn't it be nice to just double-click commands with mouse? Like a simple GUI! ;)
|
||||
|
||||
```vim
|
||||
nnoremap <silent><2-LeftMouse> :SendToTerm<CR>
|
||||
```
|
||||
|
||||
Or just hit `Enter`?
|
||||
|
||||
```vim
|
||||
nnoremap <buffer> <CR> :SendToTerm \| norm j<CR>
|
||||
```
|
||||
|
||||
Automatically add those mappings for `cheat.sh`
|
||||
```vim
|
||||
autocmd BufNewFile,BufRead cheat.sh nnoremap <buffer> <CR> :SendToTerm \| norm j<CR>
|
||||
autocmd BufNewFile,BufRead cheat.sh nnoremap <buffer> <silent><2-LeftMouse> :SendToTerm<CR>
|
||||
```
|
||||
|
||||
### Demo
|
||||
|
||||
{{< asciinema key="vimstt" >}}
|
||||
|
||||
### Using
|
||||
|
||||
Copying above snippets to your vimrc should work in a recent vim. Checked in
|
||||
ubuntu 22.04 and archlinux. Git: [repo](https://gitea.balki.me/balki/vimfun/src/branch/main/stt/stt8.vim)
|
||||
|
||||
### neovim/tmux/screen
|
||||
|
||||
Since neovim uses a different terminal API, above snippets don't work in
|
||||
neovim. [vim-slime](https://github.com/jpalardy/vim-slime) plugin (available
|
||||
since 2007!) supports different types of terminal. However it does not support
|
||||
adding delay and `ctrl` characters in text.
|
Reference in New Issue
Block a user