From e729607de6136ee2982db468ec6854e0dcebc7df Mon Sep 17 00:00:00 2001 From: benmills Date: Wed, 3 Apr 2013 13:03:03 -0500 Subject: [PATCH 1/4] Rewrite vimux using VimL. This commit also drops the deprecated functions and removes some rarely used functions such as VimuxClosePanes. --- plugin/vimux.vim | 375 ++++++++++------------------------------------- 1 file changed, 81 insertions(+), 294 deletions(-) diff --git a/plugin/vimux.vim b/plugin/vimux.vim index 99871f4..46adad8 100644 --- a/plugin/vimux.vim +++ b/plugin/vimux.vim @@ -3,16 +3,8 @@ if exists("g:loaded_vimux") || &cp endif let g:loaded_vimux = 1 -if !has("ruby") - finish -end - - -" New style commands with 'normalized' names command VimuxRunLastCommand :call VimuxRunLastCommand() command VimuxCloseRunner :call VimuxCloseRunner() -command VimuxClosePanes :call VimuxClosePanes() -command VimuxCloseWindows :call VimuxCloseWindows() command VimuxInspectRunner :call VimuxInspectRunner() command VimuxScrollUpInspect :call VimuxScrollUpInspect() command VimuxScrollDownInspect :call VimuxScrollDownInspect() @@ -20,341 +12,136 @@ command VimuxInterruptRunner :call VimuxInterruptRunner() command VimuxPromptCommand :call VimuxPromptCommand() command VimuxClearRunnerHistory :call VimuxClearRunnerHistory() -" DEPRECATED -command RunLastVimTmuxCommand :call VimuxRunLastCommand() -command CloseVimTmuxRunner :call VimuxCloseRunner() -command CloseVimTmuxPanes :call VimuxClosePanes() -command CloseVimTmuxWindows :call VimuxCloseWindows() -command InspectVimTmuxRunner :call VimuxInspectRunner() -command InterruptVimTmuxRunner :call VimuxInterruptRunner() -command PromptVimTmuxCommand :call VimuxPromptCommand() +function! VimuxRunLastCommand() + if exists("g:VimuxRunnerPaneIndex") + call VimuxRunCommand(g:VimuxLastCommand) + else + echo "No last vimux command." + endif +endfunction +function! VimuxRunCommand(command, ...) + if !exists("g:VimuxRunnerPaneIndex") || _VimuxHasPane(g:VimuxRunnerPaneIndex) == -1 + call VimuxOpenPane() + endif -" new style functions -function VimuxRunCommand(command, ...) let l:autoreturn = 1 - if exists("a:1") let l:autoreturn = a:1 endif - let s:_VimTmuxCmd = substitute(a:command, '`', '\\`', 'g') - let s:_VimTmuxCmdAutoreturn = l:autoreturn + let resetSequence = _VimuxOption("g:VimuxResetSequence", "q C-u") + let g:VimuxLastCommand = a:command + + call VimuxSendKeys(resetSequence) + call VimuxSendText(a:command) if l:autoreturn == 1 - ruby CurrentTmuxSession.new.run_shell_command(Vim.evaluate("s:_VimTmuxCmd")) - else - ruby CurrentTmuxSession.new.run_shell_command(Vim.evaluate("s:_VimTmuxCmd"), false) + call VimuxSendKeys("Enter") endif endfunction -" deprecated! -function RunVimTmuxCommand(command, ...) - " TODO replace me with the direct function call! - let l:autoreturn = 1 - - if exists("a:1") - let l:autoreturn = a:1 - endif - - let s:_VimTmuxCmd = substitute(a:command, '`', '\\`', 'g') - let s:_VimTmuxCmdAutoreturn = l:autoreturn +function! VimuxSendText(text) + call VimuxSendKeys(shellescape(a:text)) +endfunction - if l:autoreturn == 1 - ruby CurrentTmuxSession.new.run_shell_command(Vim.evaluate("s:_VimTmuxCmd")) +function! VimuxSendKeys(keys) + if exists("g:VimuxRunnerPaneIndex") + call system("tmux send-keys -t ".g:VimuxRunnerPaneIndex." ".a:keys) else - ruby CurrentTmuxSession.new.run_shell_command(Vim.evaluate("s:_VimTmuxCmd"), false) + echo "No vimux runner pane. Create one with VimuxOpenPane" endif endfunction +function! VimuxOpenPane() + let height = _VimuxOption("g:VimuxHeight", 20) + let orientation = _VimuxOption("g:VimuxOrientation", "v") + let nearestIndex = _VimuxNearestPaneIndex() -function VimuxRunLastCommand() - if exists("s:_VimTmuxCmd") - if s:_VimTmuxCmdAutoreturn == 1 - ruby CurrentTmuxSession.new.run_shell_command(Vim.evaluate("s:_VimTmuxCmd")) - else - ruby CurrentTmuxSession.new.run_shell_command(Vim.evaluate("s:_VimTmuxCmd"), false) - endif + if _VimuxOption("g:VimuxUseNearestPane", 1) == 1 && nearestIndex != -1 + let g:VimuxRunnerPaneIndex = nearestIndex else - echo "No last command" + call system("tmux split-window -p ".height." -".orientation) + let g:VimuxRunnerPaneIndex = _VimuxTmuxPaneIndex() + call system("tmux last-pane") endif endfunction -" deprecated! -function RunLastVimTmuxCommand() - call VimuxRunLastCommand() -endfunction - - -function VimuxClearWindow() - if exists("s:_VimTmuxRunnerPane") - unlet s:_VimTmuxRunnerPane - end +function! VimuxCloseRunner() + if exists("g:VimuxRunnerPaneIndex") + call system("tmux kill-pane -t ".g:VimuxRunnerPaneIndex) + unlet g:VimuxRunnerPaneIndex + endif endfunction -" deprecated! -function ClearVimTmuxWindow() - call VimuxClearWindow() +function! VimuxInspectRunner() + call system("tmux select-pane -t ".g:VimuxRunnerPaneIndex) + call system("tmux copy-mode") endfunction - -" deprecated! -function CloseVimTmuxWindows() - call VimuxCloseWindows() +function! VimuxScrollUpInspect() + call VimuxInspectRunner() + call system("tmux last-pane") + call VimuxSendKeys("C-u") endfunction - -function VimuxCloseRunner() - ruby CurrentTmuxSession.new.close_runner_pane - call VimuxClearWindow() +function! VimuxScrollDownInspect() + call VimuxInspectRunner() + call system("tmux last-pane") + call VimuxSendKeys("C-d") endfunction -" deprecated! -function CloseVimTmuxRunner() - call VimuxCloseRunner() +function! VimuxInterruptRunner() + call VimuxSendKeys("^c") endfunction - -function VimuxClosePanes() - ruby CurrentTmuxSession.new.close_other_panes - call VimuxClearWindow() +function! VimuxClearRunnerHistory() + if exists("g:VimuxRunnerPaneIndex") + call system("tmux clear-history -t ".g:VimuxRunnerPaneIndex) + endif endfunction -" deprecated! -function CloseVimTmuxPanes() - call VimuxClosePanes() +function! VimuxPromptCommand() + let l:command = input(_VimuxOption("g:VimuxPromptString", "Command? ")) + call VimuxRunCommand(l:command) endfunction - -function VimuxInterruptRunner() - ruby CurrentTmuxSession.new.interrupt_runner +function! _VimuxTmuxSession() + return _VimuxTmuxProperty("S") endfunction -" deprecated! -function InterruptVimTmuxRunner() - call VimuxInterruptRunner() +function! _VimuxTmuxPaneIndex() + return _VimuxTmuxProperty("P") endfunction -function VimuxScrollDownInspect() - ruby CurrentTmuxSession.new.inspect_scroll_down +function! _VimuxTmuxWindowIndex() + return _VimuxTmuxProperty("I") endfunction -function VimuxScrollUpInspect() - ruby CurrentTmuxSession.new.inspect_scroll_up -endfunction +function! _VimuxNearestPaneIndex() + let panes = split(system("tmux list-panes"), "\n") -function VimuxInspectRunner() - ruby CurrentTmuxSession.new.inspect_runner -endfunction + for i in panes + if match(panes[i], "(active)") == -1 + return split(panes[i], ":")[0] + endif + endfor -" deprecated! -function InspectVimTmuxRunner() - call VimuxInspectRunner() + return -1 endfunction - -function VimuxPromptCommand() - let l:command = input("Command? ") - if exists("g:VimuxPromptString") - let l:command = input(g:VimuxPromptString) +function! _VimuxOption(option, default) + if exists(a:option) + return eval(a:option) + else + return a:default endif - call VimuxRunCommand(l:command) endfunction -" deprecated! -function PromptVimTmuxCommand() - call VimuxPromptCommand() +function! _VimuxTmuxProperty(property) + return substitute(system("tmux display -p '#".a:property."'"), '\n$', '', '') endfunction - -function VimuxClearRunnerHistory() - ruby CurrentTmuxSession.new.clear_runner_history +function! _VimuxHasPane(index) + return match(system("tmux list-panes"), a:index.":") endfunction - -ruby << EOF -class TmuxSession - def initialize(session, window, pane) - @session = session - @window = window - @pane = pane - @runner_pane = vim_cached_runner_pane - end - - def vim_cached_runner_pane - if Vim.evaluate('exists("s:_VimTmuxRunnerPane")') != 0 - Vim.evaluate('s:_VimTmuxRunnerPane') - else - nil - end - end - - def vim_cached_runner_pane=(runner_pane) - Vim.command("let s:_VimTmuxRunnerPane = '#{runner_pane}'") - end - - def clear_vim_cached_runner_pane - Vim.command("unlet s:_VimTmuxRunnerPane") - end - - def clear_runner_history - _run("clear-history -t #{target(:pane => runner_pane)}") - end - - def height - if Vim.evaluate('exists("g:VimuxHeight")') != 0 - Vim.evaluate('g:VimuxHeight') - else - 20 - end - end - - def orientation - if Vim.evaluate('exists("g:VimuxOrientation")') != 0 && ["h", "v"].include?(Vim.evaluate('g:VimuxOrientation')) - "-#{Vim.evaluate('g:VimuxOrientation')}" - else - "-v" - end - end - - def reset_sequence - if Vim.evaluate('exists("g:VimuxResetSequence")') != 0 - "#{Vim.evaluate('g:VimuxResetSequence')}" - else - "q C-u" - end - end - - def inspect_runner - _run("select-pane -t #{target(:pane => runner_pane)}") - _run("copy-mode") - end - - def inspect_send_command(cmd) - t = target(:pane => runner_pane) - _run("select-pane -t #{t}") - _run("copy-mode") - _send_command(cmd, t, false) - _move_up_pane - end - - def inspect_scroll_up - inspect_send_command("C-u") - end - - def inspect_scroll_down - inspect_send_command("C-d") - end - - def current_panes - _run('list-panes').split("\n").map do |line| - line.split(':').first - end - end - - def active_pane_id - _run('list-panes').split("\n").map do |line| - return line.split[-2] if line =~ /\(active\)/ - end - end - - def target(args={}) - "'#{args.fetch(:session, @session)}':'#{args.fetch(:window, @window)}'.#{args.fetch(:pane, @pane)}" - end - - def runner_pane - if @runner_pane.nil? - use_nearest_pane = Vim.evaluate('exists("g:VimuxUseNearestPane")') != 0 - if use_nearest_pane && nearest_inactive_pane_id - _run("select-pane -t #{target(:pane => nearest_inactive_pane_id)}") - else - _run("split-window -p #{height} #{orientation}") - end - @runner_pane = active_pane_id - _send_command("cd #{`pwd`}", target(:pane => runner_pane)) - Vim.command("let s:_VimTmuxRunnerPane = '#{@runner_pane}'") - end - - _run('list-panes').split("\n").map do |line| - return line.split(':').first if line =~ /#{@runner_pane}/ - end - - @runner_pane = nil - runner_pane - end - - def interrupt_runner - _run("send-keys -t #{target(:pane => runner_pane)} ^c") - end - - def run_shell_command(command, auto_return = true) - reset_shell - _send_command(command, target(:pane => runner_pane), auto_return) - _move_up_pane - end - - def close_runner_pane - _run("kill-pane -t #{target(:pane => runner_pane)}") unless @runner_pane.nil? - end - - def close_other_panes - if _run("list-panes").split("\n").length > 1 - _run("kill-pane -a") - end - end - - def reset_shell - _run("send-keys -t #{target(:pane => runner_pane)} #{reset_sequence}") - end - - def nearest_inactive_pane_id - panes = _run("list-pane").split("\n") - pane = panes.find { |p| p !~ /active/ } - pane ? pane.split(':').first : nil - end - - def _move_up_pane - _run("select-pane -t #{target}") - end - - def _send_command(command, target, auto_return = true) - _run("send-keys -t #{target} \"#{_escape_command(command)}\"") - _run("send-keys -t #{target} Enter") if auto_return - end - - def _escape_command(command) - command.gsub('"', '\"').gsub('$', '\$') - end - - def _run(command) - `tmux #{command}` - end -end - -class CurrentTmuxSession < TmuxSession - def initialize - if tmux? - session = self.get_session - window = self.get_property(:active, :window) - pane = self.get_property(:active, :pane) - - super(session, window, pane) - else - raise "You are not in a tmux session" - end - end - - def get_property(match, type) - _run("list-#{type.to_s}").split("\n").each do |line| - return line.split(':').first if line =~ /\(#{match.to_s}\)/ - end - end - - def get_session - _run("display -p '#S'").strip - end - - def tmux? - `echo $TMUX` =~ /.+/ ? true : false - end -end -EOF From 173fcda85d2b69d015f59d4c4348e1694ac34824 Mon Sep 17 00:00:00 2001 From: benmills Date: Wed, 3 Apr 2013 13:03:57 -0500 Subject: [PATCH 2/4] Update help docs for 1.0.0. --- doc/vimux.txt | 83 +++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/doc/vimux.txt b/doc/vimux.txt index 37de16a..dc0483c 100644 --- a/doc/vimux.txt +++ b/doc/vimux.txt @@ -61,7 +61,10 @@ process finishes and will see the output in the pane when it's finished. Furthermore there are several handy commands all starting with 'Vimux': - |VimuxRunCommand| - - |VimuxRunLastCommand| + - |VimuxSendText| + - |VimuxSendKeys| + - |VimuxOpenPane| + - |VimuxRunLastCommand| - |VimuxCloseRunner| - |VimuxClosePanes| - |VimuxCloseWindows| @@ -70,22 +73,7 @@ Furthermore there are several handy commands all starting with 'Vimux': - |VimuxPromptCommand| - |VimuxClearRunnerHistory| - -Note: -Earlier the all commands had different names. There are still aliases for -convenience. Please chang your configuration according to the new naming -conventions! - -The DEPRECATED commands: - - |PromptVimTmuxCommand| - - |RunLastVimTmuxCommand| - - |InspectVimTmuxRunner| - - |CloseVimTmuxRunner| - - |CloseVimTmuxPanes| - - |InterruptVimTmuxRunner| - ------------------------------------------------------------------------------ - *RunVimTmuxCommand* *VimuxRunCommand* VimuxRunCommand~ @@ -100,7 +88,32 @@ vimux from automatically sending a return after the command. < ------------------------------------------------------------------------------ - *PromptVimTmuxCommand* + *VimuxSendText* +VimuxSendText~ + +Send raw text to the runer pane. This command will *not* open a new pane if one +does not already exist. You will need to use VimuxOpenPane to do this. This +command can be used to interact with REPLs or other interactive terminal +programs that are not shells. + + +------------------------------------------------------------------------------ + *VimuxSendKeys* +VimuxSendKeys~ + +Send keys to the runner pane. This command will *not* open a new pane if one +does not already exist. You will need to use VimuxOpenPane to do this. You can +use this command to send keys such as "Enter" or "C-c" to the runner pane. + +------------------------------------------------------------------------------ + *VimuxOpenPane* +VimuxOpenPane~ + +This will either opne a new pane or use the nearest pane and set it as the +vimux runner pane for the other vimux commands. You can control if this command +uses the nearest pane or always creates a new one with g:VimuxUseNearestPane + +------------------------------------------------------------------------------ *VimuxPromptCommand* VimuxPromptCommand~ @@ -112,7 +125,6 @@ pane. < ------------------------------------------------------------------------------ - *RunLastVimTmuxCommand* *VimuxRunLastCommand* VimuxRunLastCommand~ @@ -123,7 +135,6 @@ Run the last command executed by `VimuxRunCommand` < ------------------------------------------------------------------------------ - *InspectVimTmuxRunner* *VimuxInspectRunner* VimuxInspectRunner~ @@ -135,7 +146,6 @@ pmode (scroll mode). < ------------------------------------------------------------------------------ - *CloseVimTmuxRunner* *VimuxCloseRunner* VimuxCloseRunner~ @@ -146,18 +156,6 @@ Close the tmux runner created by `VimuxRunCommand` < ------------------------------------------------------------------------------ - *CloseVimTmuxPanes* - *VimuxClosePanes* -VimuxClosePanes~ - -Close all other tmux panes in the current window. -> - " Close all other tmux panes in current window - map vx :VimuxClosePanes -> - ------------------------------------------------------------------------------- - *InterruptVimTmuxRunner* *VimuxInterruptRunner* VimuxInterruptRunner~ @@ -194,22 +192,19 @@ Full Keybind Example~ map rb :call VimuxRunCommand("clear; rspec " . bufname("%")) " Prompt for a command to run - map rp :VimuxPromptCommand + map vp :VimuxPromptCommand " Run last command executed by VimuxRunCommand - map rl :VimuxRunLastCommand + map vl :VimuxRunLastCommand " Inspect runner pane - map ri :VimuxInspectRunner - - " Close all other tmux panes in current window - map rx :VimuxClosePanes + map vi :VimuxInspectRunner " Close vim tmux runner opened by VimuxRunCommand - map rq :VimuxCloseRunner + map vq :VimuxCloseRunner " Interrupt any command running in the runner pane - map rs :VimuxInterruptRunner + map vx :VimuxInterruptRunner > ------------------------------------------------------------------------------ @@ -220,11 +215,13 @@ Here is how to use vimux to send code to a REPL. This is similar to tslime. First, add some helpful mappings. > - " Prompt for a command to run - map vp :VimuxPromptCommand + function! VimuxSlime() + call VimuxSendText(@v) + call VimuxSendKeys("Enter") + endfunction " If text is selected, save it in the v buffer and send that buffer it to tmux - vmap vs "vy :call VimuxRunCommand(@v . "\n", 0) + vmap vs "vy :call VimuxSlime() " Select current paragraph and send it to tmux nmap vs vipvs From 6e909a24396d335527678ac0c05498da1d341d03 Mon Sep 17 00:00:00 2001 From: benmills Date: Wed, 3 Apr 2013 13:05:15 -0500 Subject: [PATCH 3/4] Fix typo in 1.0.0 docs. --- doc/vimux.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/vimux.txt b/doc/vimux.txt index dc0483c..df6d305 100644 --- a/doc/vimux.txt +++ b/doc/vimux.txt @@ -91,7 +91,7 @@ vimux from automatically sending a return after the command. *VimuxSendText* VimuxSendText~ -Send raw text to the runer pane. This command will *not* open a new pane if one +Send raw text to the runer pane. This command will not open a new pane if one does not already exist. You will need to use VimuxOpenPane to do this. This command can be used to interact with REPLs or other interactive terminal programs that are not shells. @@ -101,7 +101,7 @@ programs that are not shells. *VimuxSendKeys* VimuxSendKeys~ -Send keys to the runner pane. This command will *not* open a new pane if one +Send keys to the runner pane. This command will not open a new pane if one does not already exist. You will need to use VimuxOpenPane to do this. You can use this command to send keys such as "Enter" or "C-c" to the runner pane. From 064ca8693afd11ef0185dbb21691d641acabb782 Mon Sep 17 00:00:00 2001 From: benmills Date: Fri, 31 May 2013 12:27:06 -0700 Subject: [PATCH 4/4] Only escale double quotes. Thanks @pgr0ss --- plugin/vimux.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/vimux.vim b/plugin/vimux.vim index 46adad8..6bcdde4 100644 --- a/plugin/vimux.vim +++ b/plugin/vimux.vim @@ -42,7 +42,7 @@ function! VimuxRunCommand(command, ...) endfunction function! VimuxSendText(text) - call VimuxSendKeys(shellescape(a:text)) + call VimuxSendKeys('"'.escape(a:text, '"').'"') endfunction function! VimuxSendKeys(keys)