Skip to content

Support tmux sessions with spaces, hyphens and slashes in name #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 53 additions & 55 deletions autoload/tmuxify.vim
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ if exists('g:autoloaded_tmuxify') || &compatible || !executable('tmux') || !exec
endif
let g:autoloaded_tmuxify = 1

" Uncommon separator
let s:separator = '__::__'
let s:list_panes = printf("tmux list-panes -a -F '#D%s#S%s#I%s#P'", s:separator, s:separator, s:separator)
let s:awk_cmd = printf('awk -F "%s"', s:separator)

" s:SID() {{{1
function s:SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
Expand All @@ -34,27 +39,43 @@ endfunction

" s:get_pane_descriptor_from_id() {{{1
function! s:get_pane_descriptor_from_id(pane_id) abort
let cmd = s:list_panes . " | " . s:awk_cmd . " 'substr($1, 2) == " . a:pane_id . " { print $2 FS $3 FS $4 }'"
if exists('*systemlist')
let descriptor_list = systemlist("tmux list-panes -a -F '#D #S #I #P' | awk 'substr($1, 2) == ". a:pane_id ." { print $2, $3, $4 }'")
let descriptor_list = systemlist(cmd)
else
let descriptor_list = split(system("tmux list-panes -a -F '#D #S #I #P' | awk 'substr($1, 2) == ". a:pane_id ." { print $2, $3, $4 }'"), '\n')
let descriptor_list = split(system(cmd), '\n')
endif
if empty(descriptor_list) || descriptor_list[0] == 'failed to connect to server: Connection refused'
return ''
else
" there should only ever be one item in descriptor_list, since it was filtered for matching the unique pane_id
let [session, window, pane] = split(descriptor_list[0],' ')
let [session, window, pane] = split(descriptor_list[0], s:separator)
return session . ':' . window . '.' . pane
endif
endfunction

" s:parse_pane_descriptor() {{{1
function! s:parse_pane_descriptor(descriptor) abort
let [session, window_and_pane] = split(a:descriptor, ':')
let [window, pane] = split(window_and_pane, '\W')
return [session, window, pane]
endfunction

" s:get_scope() {{{1
function! s:get_scope(bang) abort
return empty(a:bang) ? 'b:' : 'g:'
endfunction

" s:print_upgrade_message_if_shell_error() {{{1
function! s:print_upgrade_message_if_shell_error() abort
if v:shell_error
echoerr 'tmuxify: A certain version of tmux 1.6 or higher is needed. Consider updating to 1.7+.'
endif
endfunction

" tmuxify#pane_create() {{{1
function! tmuxify#pane_create(bang, ...) abort
if empty(a:bang)
let scope = "b:"
else
let scope = "g:"
endif
let scope = s:get_scope(a:bang)

if !exists('$TMUX')
echomsg 'tmuxify: This Vim is not running in a tmux session!'
Expand All @@ -70,10 +91,11 @@ function! tmuxify#pane_create(bang, ...) abort

" capture the pane_id, as well as session, window, and pane index information
" pane_id is unique, pane_index will change if the pane is moved
let [ pane_id, session, window, pane ] = map(split(system(get(g:, 'tmuxify_custom_command', 'tmux split-window -d') . " -PF '#D #S #I #P' | awk '{id=$1; session=$2; window=$3; pane=$4} END { print substr(id, 2), session, window, pane }'"), ' '), 'str2nr(v:val)')
if v:shell_error
echoerr 'tmuxify: A certain version of tmux 1.6 or higher is needed. Consider updating to 1.7+.'
endif
let tmuxify_command = get(g:, 'tmuxify_custom_command', 'tmux split-window -d') . printf(" -PF '#D%s#S%s#I%s#P'", s:separator, s:separator, s:separator)
let cmd = tmuxify_command . " | " . s:awk_cmd . " '{id=$1; session=$2; window=$3; pane=$4} END { print substr(id, 2) FS session FS window FS pane }'"
let [ pane_id, session, window, pane ] = map(split(system(cmd), s:separator), 'str2nr(v:val)')

call s:print_upgrade_message_if_shell_error()

if exists('a:1')
call tmuxify#pane_send(a:bang, a:1)
Expand All @@ -88,11 +110,7 @@ endfunction

" tmuxify#pane_kill() {{{1
function! tmuxify#pane_kill(bang) abort
if empty(a:bang)
let scope = "b:"
else
let scope = "g:"
endif
let scope = s:get_scope(a:bang)

if !exists(scope . 'pane_id')
echomsg "tmuxify: I'm not associated with any pane! Run :TxCreate, or check whether you're using bang commands consistently."
Expand All @@ -104,41 +122,37 @@ function! tmuxify#pane_kill(bang) abort
if empty(pane_descriptor)
echomsg 'tmuxify: The associated pane was already closed! Run :TxCreate.'
else
call system('tmux kill-pane -t '. pane_descriptor)
call system('tmux kill-pane -t ' . shellescape(pane_descriptor))
endif

execute 'unlet ' . scope . 'pane_id'
endfunction

" tmuxify#pane_set() {{{1
function! tmuxify#pane_set(bang, ...) abort
if empty(a:bang)
let scope = "b:"
else
let scope = "g:"
endif
let scope = s:get_scope(a:bang)

if a:0 == 1
if a:1[0] == '%'
let descriptor_string = s:get_pane_descriptor_from_id(strpart(a:1, 1))
if descriptor_string == ''
echo 'tmuxify: Invalid Pane ID!'
if empty(descriptor_string)
echomsg 'tmuxify: Invalid Pane ID!'
return
endif
let [session, window, pane] = split(descriptor_string, '\W')
let [session, window, pane] = s:parse_pane_descriptor(descriptor_string)
else
let [session, window, pane] = split(a:1, '\W')
let [session, window, pane] = s:parse_pane_descriptor(a:1)
endif
else
let descriptor = input('Session:Window.Pane> ', '', 'custom,<SNR>'. s:SID() .'_complete_descriptor')
let [session, window, pane] = split(descriptor, '\W')
let descriptor = input('Session:Window.Pane> ', '', 'custom,<SNR>' . s:SID() . '_complete_descriptor')
let [session, window, pane] = s:parse_pane_descriptor(descriptor)
endif

execute "let " . scope . "session = session"
execute "let " . scope . "window = window"
execute "let " . scope . "pane = pane"

let pane_id = system("tmux list-panes -a -F '#D #S #I #P' | awk '$2 == \"". session ."\" && $3 == \"". window ."\" && $4 == \"". pane ."\" {print substr($1, 2)}'")
let pane_id = system(s:list_panes . " | " . s:awk_cmd . " '$2 == \"" . session . "\" && $3 == \"" . window . "\" && $4 == \"" . pane . "\" {print substr($1, 2)}'")
if empty(pane_id)
redraw | echomsg 'tmuxify: There is no pane '. pane .'!'
return
Expand All @@ -149,11 +163,7 @@ endfunction

" tmuxify#pane_run() {{{1
function! tmuxify#pane_run(bang, ...) abort
if empty(a:bang)
let scope = "b:"
else
let scope = "g:"
endif
let scope = s:get_scope(a:bang)

if !exists(scope . 'pane_id') && !tmuxify#pane_create(a:bang)
return
Expand All @@ -179,11 +189,7 @@ endfunction

" tmuxify#pane_send() {{{1
function! tmuxify#pane_send(bang, ...) abort
if empty(a:bang)
let scope = "b:"
else
let scope = "g:"
endif
let scope = s:get_scope(a:bang)

if !exists(scope . 'pane_id') && !tmuxify#pane_create(a:bang)
return
Expand All @@ -196,12 +202,12 @@ function! tmuxify#pane_send(bang, ...) abort
return
endif

let pane_descriptor = shellescape(pane_descriptor)

if exists('a:1')
for line in split(a:1, '\n')
call system('tmux send-keys -t '. pane_descriptor .' -l '. shellescape(s:fixstr(line)) .' && tmux send-keys -t '. pane_descriptor .' C-m')
if v:shell_error
echoerr 'tmuxify: A certain version of tmux 1.6 or higher is needed. Consider updating to 1.7+.'
endif
call s:print_upgrade_message_if_shell_error()
endfor
else
call system('tmux send-keys -t '. pane_descriptor .' '. shellescape(s:fixstr(input('TxSend> '))) .' C-m')
Expand All @@ -215,11 +221,7 @@ endfunction

" tmuxify#pane_send_raw() {{{1
function! tmuxify#pane_send_raw(cmd, bang) abort
if empty(a:bang)
let scope = "b:"
else
let scope = "g:"
endif
let scope = s:get_scope(a:bang)

if !exists(scope . 'pane_id') && !tmuxify#pane_create(a:bang)
return
Expand All @@ -238,7 +240,7 @@ function! tmuxify#pane_send_raw(cmd, bang) abort
let keys = a:cmd
endif

call system('tmux send-keys -t '. pane_descriptor ." '". keys . "'")
call system('tmux send-keys -t ' . shellescape(pane_descriptor) . " '" . keys . "'")
endfunction

" tmuxify#set_run_command_for_filetype() {{{1
Expand Down Expand Up @@ -270,11 +272,7 @@ endfunction

" tmuxify#pane_command() {{{1
function! tmuxify#pane_command(bang, ...) abort
if empty(a:bang)
let scope = "b:"
else
let scope = "g:"
endif
let scope = s:get_scope(a:bang)

if !exists(scope . 'pane_id')
echomsg "tmuxify: I'm not associated with any pane! Run :TxCreate, or check whether you're using bang commands consistently."
Expand All @@ -288,7 +286,7 @@ function! tmuxify#pane_command(bang, ...) abort
return
endif

call system('tmux ' . a:1 . ' -t '. pane_descriptor)
call system('tmux ' . a:1 . ' -t ' . shellescape(pane_descriptor))
endfunction

" vim: et sw=2 sts=2 tw=80