christoomey / vim-tmux-runner

Vim and tmux, sittin' in a tree...
MIT License
291 stars 37 forks source link

Automatically close pane after loosing focus #97

Closed pianocomposer321 closed 4 years ago

pianocomposer321 commented 4 years ago

I have the following mapping for python in vim: au FileType python nnoremap <buffer> <C-b> :wa<cr>:exec "VtrSendCommand! python " . expand('%')<cr>:exec "VtrFocusRunner!"<cr>

How can I make Vtr automatically close the runner pane after it loses focus?

christoomey commented 4 years ago

Unfortunately, I'm not sure this is possible. This plugin runs as vimscript that does it's best to keep in sync with the tmux panes it manages, but there isn't a way that I can think of for this plugin to know about the runner pane losing focus.

That said, I think you could get the workflow you're looking for with just normal tmux functionality. If you pass a command to tmux when running split-window, tmux will wait until that command completes and exit. E.g. tmux split-window htop will split open a new tmux pane with htop running. Once you exit htop, tmux will automatically close the pane.

With that in mind, I think you could use the following:

nnoremap <buffer> <C-b> :wa<cr>:call system("tmux split-window 'python " . expand('%') . "'"<cr>

Note - if the window opens and closes immediately then it means you have an error in your shell command.


Hope that helps! Since this isn't functionality for the plugin itself, I'm going to close this issue.

pianocomposer321 commented 4 years ago

For some reason, your mapping wasn't working for me (even after I added the missing closing parenthesis for the system function 😁) - the pane closed immediately even for commands like echo hi. Instead, I have the following function in my bashrc:

function pause(){
 read -s -n 1 -p "Press any key to continue . . ."
 echo ""
}

so that I can have the command pause just like in dos/windows cmd. I changed the mapping to

nnoremap <buffer> <C-b> :wa<Cr>:exec "VtrSendCommand! python " . expand('%') . " && pause && exit"<cr>:exec "VtrFocusRunner!"<cr>

and it works...sort of. The problem is that when I try to send a command after running exit in the VTR runner pane, I get an error: VTR: Runner pane setting (n) is invalid. Please reattach.

Any ideas?

pianocomposer321 commented 4 years ago

I have gotten something to work. Modified from https://github.com/christoomey/vim-tmux-runner/issues/73#issuecomment-509525771:

function! SendTmuxCommand(text)
  let panes = split(system("tmux list-panes"), '\n')
  let active = filter(copy(panes), 'v:val =~ "\\(active\\)"')
  let vimPane = str2nr(active[0])
  let cmdPane = vimPane + 1
  let panes = filter(panes, 'v:val =~ "^'.cmdPane.':.*"')
  if len(panes) == 0
    call system('tmux split-window -v -l 10')
    call system('tmux select-pane -t '.vimPane)
  endif

  let cmd = "tmux send-keys -t ".cmdPane." ".shellescape(a:text . " && read -s -n 1 -p 'Press any key to continue . . .' && echo && exit") . " C-m"
  call system(cmd)
  call system("tmux select-pane -t " . cmdPane)
endfunction

and in init.vim: au FileType python nnoremap <buffer> <C-b> :wa<cr>:call SendTmuxCommand("python " . expand('%'))<cr>

If you have a pure vim-tmux-runner solution, I might use it but otherwise, this will do for now.