├── 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 |
--------------------------------------------------------------------------------