diff --git a/autoload/tmuxify.vim b/autoload/tmuxify.vim index 911c007..e8a795c 100644 --- a/autoload/tmuxify.vim +++ b/autoload/tmuxify.vim @@ -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(''), '\zs\d\+\ze_SID$') @@ -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!' @@ -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) @@ -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." @@ -104,7 +122,7 @@ 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' @@ -112,33 +130,29 @@ 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,'. s:SID() .'_complete_descriptor') - let [session, window, pane] = split(descriptor, '\W') + let descriptor = input('Session:Window.Pane> ', '', 'custom,' . 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 @@ -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 @@ -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 @@ -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') @@ -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 @@ -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 @@ -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." @@ -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