├── LICENSE ├── README.md └── plugin └── vimtux.vim /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Christian Brauner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vimtux 2 | 3 | ## Installation 4 | - `Vundle`: 5 | - In your `.vimrc` place `Plugin 'brauner/vimtux'` between 6 | `call vundle#begin()` and `call vundle#end()`. Then open 7 | `vim` and install with `:PluginInstall`. 8 | - `Pathogen`: 9 | - use: 10 | ```{.sh} 11 | cd ~/.vim/bundle 12 | git clone https://github.com/brauner/vimtux.git 13 | ``` 14 | 15 | This is a simple Vim script to send text, commands and keys from a Vim 16 | buffer to a running tmux session. its main objective is to stay as simple 17 | as possible following the famous KISS principle. This means it does not 18 | rely on the presence of any external files, programming languages 19 | whatsoever and it will stay that way. Forever. Period. It does exactly 20 | what it was designed for no more no less: Send text, commands and keys to 21 | any Tmux session via Vim. You will find the details below. 22 | 23 | **Note:** If you use version of tmux ealier than 1.3, you should use the stable 24 | branch. The version available in that branch isn't aware of panes so it 25 | will paste to pane 0 of the window. 26 | 27 | (1) vimtux provides the ability to send multiple keys to a tmux target at 28 | once. 29 | 30 | (2) The tmux target is set on buffer basis. This means that every tab in 31 | Vim can have its own tmux target. (E.g. you could have a tab in which you 32 | edit a Python script and send text and keys to a Python repl and another 33 | tab in which you edit an R script and send text and keys to an R repl.) 34 | 35 | (3) vimtux allows you to refer to panes and windows either via their 36 | dynamic identifier which is a simple number. Or via their unique 37 | identifier. For panes their unique identifier is a number prefixed with 38 | `%` and for windows a number prefixed with `@`. 39 | 40 | a) Demonstrative Reference/Dynamic Reference: 41 | 42 | · Panes: If you choose to refer to a pane via its dynamic identifier the 43 | target of any given send function in this script will change when you 44 | insert a new pane before the pane you used. 45 | 46 | · Windows (slightly more complex to explain): Assume you have set 47 | `set-window-option -g automatic-rename on` in your `~/.tmux.conf`. This is 48 | quite useful when you want to have an easy way of seeing what program is 49 | currently running in any given tmux window. But it is not very useful when 50 | you switch programs in a tmux window a lot but still want to be able to 51 | send commands and keys from the same window or pane to these different 52 | programs. Because refering to the window via its name given to it by the 53 | program currently running will break the connection between the window 54 | running the program and the window you are sending commands and keys from 55 | once that program is exited. 56 | 57 | b) Proper Name/Static Reference: If you choose to refer to a pane via its 58 | unique identifier the target of any given send function in this script 59 | will stay fixed. 60 | 61 | b) Proper Name/Static Reference: If you choose to refer to a window via 62 | its unique identifier the target of any given send function in this script 63 | will stay fixed while allowing that the program currently running in that 64 | window is setting the name for that session. 65 | 66 | Tip: You can find out the unique identifier of a pane by either passing 67 | `tmux list-panes -t x` where `x` is the name of the session. Or (the 68 | easier way) you let the unique identifier of every pane be shown in your 69 | tmux status bar with the option `#D`; e.g.: `set -g status-left '#D'`. 70 | (All possible options about what to display in the statusbar can be found 71 | via `man tmux` or some internet searching.) 72 | 73 | I suggest using something like this in your `.tmux.conf`: 74 | 75 | \# Status bar. 76 | 77 | `set -g status-interval 2` 78 | 79 | `set -g status-right '[#D|#P|#T] '` 80 | 81 | `set -g status-left '[#{session_id}|#S]'` 82 | 83 | `set-option -g status-justify centre` 84 | 85 | \# Disable showing the default window list component and trim it to a more 86 | specific format. 87 | 88 | `set-window-option -g window-status-current-format '[#F|#{window_id}|#I|#W|#{window_panes}]'` 89 | 90 | `set-window-option -g window-status-format '[#F|#{window_id}|#I|#W|#{window_panes}]'` 91 | 92 | which gives you: `#{session_id} := unique session ID`, `#S := session 93 | title`, `#F := window flags` (Info about which windows is active etc.), 94 | `#{window_id} := unique window ID`, `#I := window index`, `#W := window 95 | title`, `#{window_panes} := number of active panes in current window`, `#D 96 | := unique pane number`, `#P := dynamic pane number`, `#T := pane title`, 97 | The characters `[`, `]` and `|` are just used to secure visibility and do 98 | not have any further meaning. 99 | 100 | A last hint: If you fancy it you can rename panes. Just issue `printf 101 | '\033]2;%s\033\\' 'hello'` in any pane and observe how `#T` will change. 102 | 103 | (For fun: Consider including `#D` and `#P` in your statusbar for a moment 104 | in order to see how tmux changes the dynamic window number for every pane 105 | that comes after the one you just opened and how `#D` stays fixed.) 106 | 107 | (4) Keybindings are not set automatically for you. Instead, you can map 108 | whatever you'd like to one of the plugin-specific bindings in your 109 | `.vimrc` file. 110 | 111 | ## Setting Keybindings 112 | 113 | To get the old defaults, put the following in your `.vimrc`: 114 | 115 | ``` vim 116 | vmap SendSelectionToTmux 117 | nmap NormalModeSendToTmux 118 | nmap r SetTmuxVars 119 | ``` 120 | 121 | To send a selection in visual mode to vim, set the following in your `.vimrc`: 122 | 123 | ``` vim 124 | vmap SendSelectionToTmux 125 | ``` 126 | 127 | To grab the current method that a cursor is in normal mode, set the following: 128 | 129 | ``` vim 130 | nmap NormalModeSendToTmux 131 | ``` 132 | 133 | Use the following to reset the session, window, and pane info: 134 | 135 | ``` vim 136 | nmap SetTmuxVars 137 | ``` 138 | 139 | Have a command you run frequently, use this: 140 | 141 | ``` vim 142 | nmap :Tmux 143 | ``` 144 | 145 | More info about the `` and other mapping syntax can be found 146 | [here](http://vim.wikia.com/wiki/Mapping_keys_in_Vim_-_Tutorial_(Part_3) ). 147 | 148 | ## Tip 149 | 150 | You don't need to be in a `tmux` session in order to send text or keys to 151 | another tmux session. The only requirement is that you are in a `vim` 152 | session. Hence, you can send keys to any `tmux` session from any 153 | (non-`tmux`) `vim` session. 154 | -------------------------------------------------------------------------------- /plugin/vimtux.vim: -------------------------------------------------------------------------------- 1 | " File: vimtux.vim 2 | " Code by: C. Brauner , 3 | " C. Coutinho , 4 | " K. Borges 5 | " Maintainer: C. Brauner , 6 | 7 | if exists("g:loaded_vimtux") && g:loaded_vimtux 8 | finish 9 | endif 10 | 11 | let g:loaded_vimtux = 1 12 | 13 | " Send keys to tmux. 14 | function! ExecuteKeys(keys) 15 | if !exists("b:vimtux") 16 | if exists("g:vimtux") 17 | " This bit sets the target on buffer basis so every tab can have its 18 | " own target. 19 | let b:vimtux = g:vimtux 20 | else 21 | call TmuxVars() 22 | end 23 | end 24 | call system("tmux send-keys -t " . s:TmuxTarget() . " " . a:keys) 25 | endfunction 26 | 27 | function! SendKeysToTmux(keys) 28 | for k in split(a:keys, '\s') 29 | call ExecuteKeys(k) 30 | endfor 31 | endfunction 32 | 33 | " Function to send a key that asks for user input. 34 | function! ExecuteKeysPrompt() 35 | call inputsave() 36 | let l:command = input("Enter Keycode: ") 37 | call inputrestore() 38 | call ExecuteKeys(l:command) 39 | endfunction 40 | 41 | " Function to send text that asks for user input. 42 | function! SendToTmuxPrompt() 43 | call inputsave() 44 | let l:text = input("Enter Text: ") 45 | if empty(l:text) 46 | return 47 | endif 48 | call inputrestore() 49 | call SendToTmux(l:text) 50 | call ExecuteKeys("Enter") 51 | endfunction 52 | 53 | 54 | " Main function. 55 | function! SendToTmux(text) 56 | if !exists("b:vimtux") 57 | if exists("g:vimtux") 58 | " This bit sets the target on buffer basis so every tab can have its 59 | " own target. 60 | let b:vimtux = g:vimtux 61 | else 62 | call TmuxVars() 63 | end 64 | end 65 | let oldbuffer = system(shellescape("tmux show-buffer")) 66 | call SetTmuxBuffer(a:text) 67 | call system("tmux paste-buffer -t " . s:TmuxTarget()) 68 | call SetTmuxBuffer(oldbuffer) 69 | endfunction 70 | 71 | " Setting the target. 72 | function! s:TmuxTarget() 73 | if len(b:vimtux['pane']) == 1 74 | return '"' . b:vimtux['session'] . '":' . b:vimtux['window'] . "." . b:vimtux['pane'] 75 | else 76 | return b:vimtux['pane'] 77 | end 78 | endfunction 79 | 80 | function! s:SetTmuxBuffer(text) 81 | let buf = substitute(a:text, "'", "\\'", 'g') 82 | call system("tmux load-buffer -", buf) 83 | endfunction 84 | 85 | " Session completion. 86 | function! TmuxSessionNames(A,L,P) 87 | return TmuxSessions() 88 | endfunction 89 | 90 | " Window completion. 91 | function! TmuxWindowNames(A,L,P) 92 | return TmuxWindows() 93 | endfunction 94 | 95 | " Pane completion. 96 | function! TmuxPaneNumbers(A,L,P) 97 | return TmuxPanes() 98 | endfunction 99 | 100 | function! s:TmuxSessions() 101 | let sessions = system("tmux list-sessions | sed -e 's/:.*$//'") 102 | return sessions 103 | endfunction 104 | 105 | " To set the TmuxTarget globally rather than locally substitute 'g:' for all 106 | " instances of 'b:' below and delete the 'if exists("g:vimtux") let b:vimtux = 107 | " g:vimtux' condition in the definition of the 'SendToTmux(text)' function 108 | " above. 109 | function! s:TmuxWindows() 110 | return system('tmux list-windows -t "' . b:vimtux['session'] . '" | grep -e "^\w:" | sed -e "s/\s*([0-9].*//g"') 111 | endfunction 112 | 113 | function! s:TmuxPanes() 114 | return system('tmux list-panes -t "' . b:vimtux['session'] . '":' . b:vimtux['window'] . " | sed -e 's/:.*$//'") 115 | endfunction 116 | 117 | " Set variables for TmuxTarget(). 118 | function! s:TmuxVars() 119 | let names = split(s:TmuxSessions(), "\n") 120 | let b:vimtux = {} 121 | if len(names) == 1 122 | let b:vimtux['session'] = names[0] 123 | else 124 | let b:vimtux['session'] = '' 125 | endif 126 | while empty(b:vimtux['session']) 127 | call inputsave() 128 | let b:vimtux['session'] = input("session name: ", "", "custom,TmuxSessionNames") 129 | call inputrestore() 130 | endwhile 131 | 132 | let windows = split(s:TmuxWindows(), "\n") 133 | if len(windows) == 1 134 | let window = windows[0] 135 | else 136 | call inputsave() 137 | let window = input("window name: ", "", "custom,TmuxWindowNames") 138 | call inputrestore() 139 | if empty(window) 140 | let window = windows[0] 141 | endif 142 | endif 143 | 144 | let b:vimtux['window'] = substitute(window, ":.*$" , '', 'g') 145 | 146 | let panes = split(s:TmuxPanes(), "\n") 147 | if len(panes) == 1 148 | let b:vimtux['pane'] = panes[0] 149 | else 150 | let b:vimtux['pane'] = input("pane number: ", "", "custom,TmuxPaneNumbers") 151 | if empty(b:vimtux['pane']) 152 | let b:vimtux['pane'] = panes[0] 153 | endif 154 | endif 155 | endfunction 156 | 157 | 158 | " definition for SendToTmux(). 159 | vmap SendSelectionToTmux y :call SendToTmux(@") 160 | 161 | " definition for SendSelectionToTmu(). 162 | nmap NormalModeSendToTmux V SendSelectionToTmux 163 | 164 | " definition for SetTmuxVars(). 165 | nmap SetTmuxVars :call TmuxVars() 166 | 167 | " definition for "C-c" shortcut. 168 | nmap ExecuteKeysCc :call ExecuteKeys("c-c") 169 | 170 | " definition for "C-l" shortcut. 171 | nmap ExecuteKeysCv :call ExecuteKeys("c-l") 172 | 173 | " definition for "C-l" shortcut in bash vi editing mode. 174 | nmap ExecuteKeysCl :call ExecuteKeys("c-[ c-l i") 175 | 176 | 177 | " definition for ExecuteKeysPrompt(). 178 | nmap ExecuteKeysPlug :call ExecuteKeysPrompt() 179 | 180 | " definition for SendToTmuxPrompt(). 181 | nmap SendToTmuxPlug :call SendToTmuxPrompt() 182 | 183 | command! -nargs=* Tmux call SendToTmux('') 184 | 185 | " " One possible way to map keys in .vimrc. 186 | " " vimtux.vim variables. 187 | " " Key definition for SendToTmux() . 188 | " vmap SendSelectionToTmux 189 | " 190 | " " Key definition for SendSelectionToTmux() . 191 | " nmap NormalModeSendToTmux 192 | " 193 | " " Key definition for SetTmuxVars() 194 | " nmap r SetTmuxVars 195 | " 196 | " " Key definition for "C-c" shortcut. 197 | " nmap ExecuteKeysCc 198 | " 199 | " " Key definition for "C-l" shortcut in bash vi editing mode. 200 | " nmap ExecuteKeysCl 201 | " 202 | " " Key definition for "C-l" shortcut. 203 | " nmap ExecuteKeysCv 204 | " 205 | " " Key definition for ExecuteKeysPrompt() . 206 | " nmap sk ExecuteKeysPlug 207 | " 208 | " " Key definition for SendToTmuxPrompt() . 209 | " nmap sp SendTextToTmuxPlug 210 | " 211 | " " Key definition for ExecuteKeysPrompt() . 212 | " nmap sk ExecuteKeysPlug 213 | " 214 | " " Key definition for SendToTmuxPrompt() . 215 | " nmap sp SendToTmuxPlug 216 | --------------------------------------------------------------------------------