├── ftplugin ├── vimshell.vim └── int-ssh.vim ├── syntax └── int-ssh.vim ├── vimshell-ssh.vimup ├── README.md ├── autoload ├── neocomplcache │ └── sources │ │ └── int_ssh.vim └── vimshell_ssh.vim └── doc └── vimshell-ssh.txt /ftplugin/vimshell.vim: -------------------------------------------------------------------------------- 1 | call vimshell#hook#add('preinput', 'vimshell_ssh', 'vimshell_ssh#pre') 2 | call vimshell#hook#add('postinput', 'vimshell_ssh', 'vimshell_ssh#post') 3 | -------------------------------------------------------------------------------- /ftplugin/int-ssh.vim: -------------------------------------------------------------------------------- 1 | call vimshell#hook#add('preinput', 'vimshell_ssh', 'vimshell_ssh#pre') 2 | call vimshell#hook#add('postinput', 'vimshell_ssh', 'vimshell_ssh#post') 3 | 4 | if exists(':NeoComplCacheLockSource') 5 | NeoComplCacheLockSource filename_complete 6 | endif 7 | -------------------------------------------------------------------------------- /syntax/int-ssh.vim: -------------------------------------------------------------------------------- 1 | if version < 700 2 | syntax clear 3 | elseif exists("b:current_syntax") 4 | finish 5 | endif 6 | 7 | syn match vimShellSshPrompt '^.\{-}@.\{-}[$%] ' 8 | 9 | if has('gui_running') 10 | hi vimShellSshPrompt gui=UNDERLINE guifg=#80ffff guibg=NONE 11 | else 12 | hi def link vimShellSshPrompt Identifier 13 | endif 14 | 15 | 16 | let b:current_syntax = 'int-ssh' 17 | -------------------------------------------------------------------------------- /vimshell-ssh.vimup: -------------------------------------------------------------------------------- 1 | "script_name": vimshell-ssh 2 | "script_id": "3614" 3 | "script_type": ftplugin 4 | "script_package": "{script_name}-{version}.tgz" 5 | "required_vim_version": '7.3' 6 | "summary": You can run Vim over ssh on Vim! 7 | "detailed_description": | 8 | A vimshell plugin that enables you to use "vim" command over ssh on vimshell. 9 | 10 | See the detail below. 11 | https://github.com/ujihisa/vimshell-ssh 12 | "install_details": | 13 | After you install Shougo's vimshell and its dependencies, unarchive the tgz file into a directory that is under &rtp of your Vim, including ~/.vim dir. 14 | "versions": 15 | - '2.1': | 16 | * Bugfix and catching up the latest vimshell 17 | - '2.0': | 18 | * NeoComplCache integration: remote filename completion 19 | - '1.1': | 20 | * Follows changes in vimshell core 21 | * Supports empty file name to open the directory 22 | - '1.0': Initial upload 23 | # vim: filetype=yaml 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vimshell-ssh 2 | 3 | ## usage 4 | 5 | 1. `iexe ssh` on your vimshell 6 | 2. use `vim` command remotely 7 | 3. wow! 8 | 9 | ## dependencies 10 | 11 | * vimshell 12 | * netrw (should be built-in in your Vim) 13 | 14 | Optional 15 | 16 | * unite-ssh (this replaces netrw) 17 | * unite.vim (unite-ssh's dependency) 18 | * vimfiler (unite-ssh's dependency) 19 | 20 | ## known issues 21 | 22 | * netrw uses `:!` 23 | * solution: 24 | * use [my forked version of netrw](https://github.com/ujihisa/netrw.vim) 25 | * or use unite-ssh 26 | * netrw changes options like cursorline 27 | * solution: 28 | * write `let g:netrw_cursorline = 0` in your vimrc 29 | * or use [my forked version of netrw](https://github.com/ujihisa/netrw.vim) 30 | * or use unite-ssh 31 | * after vim command the ssh iexe buffer cursor location will be still in the vim command's line 32 | * for some reasin vim command failed on my remote zsh 33 | * run bash on the server just in case 34 | * `export` PS1, PS2 and RPS to simpify them 35 | 36 | ## articules 37 | 38 | * (written in Japanese) 39 | 40 | ## Author 41 | 42 | Tatsuhiro Ujihisa 43 | 44 | ## License 45 | 46 | MIT 47 | -------------------------------------------------------------------------------- /autoload/neocomplcache/sources/int_ssh.vim: -------------------------------------------------------------------------------- 1 | let s:source = { 2 | \ 'name' : 'int-ssh', 3 | \ 'kind' : 'ftplugin', 4 | \ 'filetypes': { 'int-ssh': 1 }, 5 | \ } 6 | function! s:source.initialize() "{{{ 7 | call neocomplcache#set_completion_length(self.name, 8 | \ g:neocomplcache_auto_completion_start_length) 9 | endfunction "}}} 10 | 11 | function! s:source.finalize() "{{{ 12 | endfunction "}}} 13 | 14 | function! s:source.get_keyword_pos(cur_text) "{{{ 15 | let pattern = neocomplcache#get_keyword_pattern_end('filename') 16 | let [cur_keyword_pos, _] = 17 | \ neocomplcache#match_word(a:cur_text, pattern) 18 | return cur_keyword_pos 19 | endfunction "}}} 20 | 21 | function! s:ls(x) 22 | let chunk = vimshell_ssh#remoterun( 23 | \ printf("/bin/ls -1F %s 2>/dev/null", string(a:x))) 24 | "return chunk 25 | return split(chunk, "\n") 26 | endfunction 27 | 28 | function! s:source.get_complete_words(cur_keyword_pos, cur_keyword_str) "{{{ 29 | if !s:is_on_prompt_line() 30 | return [] 31 | endif 32 | 33 | let dir = a:cur_keyword_str =~ '/' ? 34 | \ fnamemodify(a:cur_keyword_str, ':h') . '/' : '' 35 | let list = [] 36 | for f in s:ls(fnamemodify(a:cur_keyword_str, ':h')) 37 | let name = dir . f 38 | 39 | call add(list, { 'word': substitute(name, '[*|@]$', '', ''), 40 | \ 'menu': '[ssh] ' . name }) 41 | endfor 42 | 43 | return neocomplcache#keyword_filter(list, a:cur_keyword_str) 44 | endfunction "}}} 45 | 46 | function! s:is_on_prompt_line() 47 | return s:get_line() =~ '^.*[$%] ' 48 | endfunction 49 | 50 | function! s:get_line() 51 | return substitute(getline('.'), '\e\[[0-9;]*m', '', 'g') 52 | endfunction 53 | 54 | function! neocomplcache#sources#int_ssh#define() "{{{ 55 | return has('reltime') ? s:source : {} 56 | endfunction "}}} 57 | 58 | " vim: ts=2 sw=2 sts=2 foldmethod=marker 59 | -------------------------------------------------------------------------------- /doc/vimshell-ssh.txt: -------------------------------------------------------------------------------- 1 | *vimshell-ssh.txt* You can run Vim over ssh on Vim! 2 | 3 | Version: 2.1 4 | Author: ujihisa 5 | Maintainer: Shougo 6 | License: MIT license {{{ 7 | Permission is hereby granted, free of charge, to any person obtaining 8 | a copy of this software and associated documentation files (the 9 | "Software"), to deal in the Software without restriction, including 10 | without limitation the rights to use, copy, modify, merge, publish, 11 | distribute, sublicense, and/or sell copies of the Software, and to 12 | permit persons to whom the Software is furnished to do so, subject to 13 | the following conditions: 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | }}} 25 | 26 | CONTENTS *vimshell-ssh-contents* 27 | 28 | Introduction |vimshell-ssh-introduction| 29 | 30 | ============================================================================== 31 | INTRODUCTION *vimshell-ssh-introduction* 32 | 33 | vimshell-ssh is the world first vimshell plugin that you can run "vim" command 34 | on ssh on vimshell. 35 | 36 | See the details in README.md file. 37 | 38 | TODO: move README.md contents here 39 | 40 | ============================================================================== 41 | vim:tw=78:ts=8:ft=help:norl:noet:fen:fdl=0:isk+=-: 42 | -------------------------------------------------------------------------------- /autoload/vimshell_ssh.vim: -------------------------------------------------------------------------------- 1 | let g:vimshell_ssh#enable_debug = get(g:, 'vimshell_ssh#enable_debug', 0) 2 | 3 | function! vimshell_ssh#pre(input, context) 4 | if b:interactive.command !=# 'ssh' 5 | \ || a:input !~# '^vim\>' 6 | \ || !has('reltime') 7 | \ || !has_key(b:interactive.prompt_history, line('.')) 8 | return a:input 9 | endif 10 | 11 | let prompt = b:interactive.prompt_history[line('.')] 12 | 13 | let dir = vimshell_ssh#remoterun('pwd') 14 | let dir = substitute(dir, '\r\|\n', '', 'g') 15 | let file = substitute(a:input, '^vim\s*', '', '') 16 | let file = substitute(file, '\r\|\n', '', 'g') 17 | 18 | if g:vimshell_ssh#enable_debug 19 | echomsg string(file) 20 | endif 21 | 22 | let [new_pos, old_pos] = vimshell#split(g:vimshell_split_command) 23 | " NOTE: passive check. Should we check aggressively? 24 | 25 | if !empty(unite#get_all_sources('ssh')) && exists(':VimFiler') 26 | let command = printf('%s://%s/%s/%s', 27 | \ 'VimFiler ssh', 28 | \ s:args2hostname(b:interactive.args), 29 | \ dir, 30 | \ file) 31 | else 32 | let command = printf('%s://%s//%s/%s', 33 | \ 'edit scp', 34 | \ s:args2hostname(b:interactive.args), 35 | \ dir, 36 | \ file) 37 | endif 38 | if g:vimshell_ssh#enable_debug 39 | echomsg command 40 | endif 41 | execute command 42 | 43 | sleep 100ms 44 | 45 | call vimshell#restore_pos(old_pos) 46 | 47 | call append('.', prompt) 48 | call cursor(line('.')+1, 0) 49 | let b:interactive.output_pos = getpos('.') 50 | let b:interactive.prompt_history[line('.')] = prompt 51 | 52 | let b:vim_ran = 1 53 | return '' 54 | endfunction 55 | 56 | function! vimshell_ssh#post(input, context) 57 | if !(a:input == '' && s:get('b:vim_ran')) 58 | return 59 | endif 60 | 61 | let b:vim_ran = 0 62 | wincmd w 63 | stopinsert 64 | endfunction 65 | 66 | " s:args2hostname(['ssh', 'example.com']) 67 | " => 'example.com' 68 | " s:args2hostname(['ssh', '-p', '2222', 'example.com']) 69 | " => 'example.com:2222' 70 | " s:args2hostname(['ssh', '-u', 'ujihisa', 'example.com']) 71 | " => 'ujihisa@example.com' 72 | function! s:args2hostname(args) 73 | let xs = copy(a:args) 74 | call remove(xs, 0) " 1st item is always 'ssh' 75 | 76 | let port = '' 77 | let user = '' 78 | let machine = '' 79 | while xs != [] 80 | let e = remove(xs, 0) 81 | if e ==# '-p' 82 | let port = ':' . remove(xs, 0) 83 | elseif e ==# '-u' 84 | let user = remove(xs, 0) . '@' 85 | else 86 | let machine = e 87 | endif 88 | endwhile 89 | return join([user, machine, port], '') 90 | endfunction 91 | 92 | function! vimshell_ssh#remoterun(cmd) 93 | call b:interactive.process.stdout.write(a:cmd . "\") 94 | 95 | let chunk = '' 96 | let start = reltime() 97 | while 1 98 | let chunk .= b:interactive.process.stdout.read(1000, 100) 99 | 100 | if g:vimshell_ssh#enable_debug 101 | echomsg string(chunk) 102 | endif 103 | 104 | " Timeout 105 | let end = split(reltimestr(reltime(start)))[0] * 700 106 | if end > 700 107 | break 108 | endif 109 | 110 | let chunk = substitute(chunk, '\e\[[0-9;]*m', '', 'g') 111 | 112 | let chunks = split(chunk, "\n") 113 | if len(chunks) >= 3 && chunk =~ '[$%] ' 114 | break 115 | endif 116 | endwhile 117 | 118 | " Delete colors. 119 | let chunk = substitute(chunk, '\e\[[0-9;]*m', '', 'g') 120 | 121 | let chunk = join(split(substitute( 122 | \ chunk, "\r", '', 'g'), '\n')[1 : -2], "\n") 123 | 124 | if g:vimshell_ssh#enable_debug 125 | echomsg string(chunk) 126 | endif 127 | 128 | return chunk 129 | endfunction 130 | 131 | function! s:get(varname) 132 | return exists(a:varname) ? eval(a:varname) : 0 133 | endfunction 134 | --------------------------------------------------------------------------------