aboutsummaryrefslogtreecommitdiff
path: root/dot_vim/plugin/remoteOpen.vim
blob: cb550ffad5fc9e69467c222e8b6ee9676e1a26e5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
" File: remoteOpen.vim
" Author: Srinath Avadhanula <srinath AT fastmail DOT fm>
" $Id: remoteOpen.vim 997 2006-03-20 09:45:45Z srinathava $
" 
" Description:
" Often times, an external program needs to open a file in gvim from the
" command line. However, it will not know if the file is already opened in a
" previous vim session. It is not sufficient to simply specify 
"
" gvim --remote-silent <filename> 
"
" because this simply opens up <filename> in the first remote gvim session it
" sees. This script provides a command RemoteOpen which is meant to be used
" from the command line as follows:
"
" gvim -c ":RemoteOpen +<lnum> <filename>"
"
" where <lnum> is the line-number you wish <filename> to open to.  What will
" happen is that a new gvim will start up and enquire from all previous
" sessions if <filename> is already open in any of them. If it is, then it
" will edit the file in that session and bring it to the foreground and itself
" quit. Otherwise, it will not quit and instead open up the file for editing
" at <lnum>.
"
" This was mainly created to be used with Yap (the dvi previewer in miktex),
" so you can specify the program for "inverse search" as specified above.
" This ensures that the inverse search uses the correct gvim each time.
"
" Ofcourse, this requires vim with +clientserver. If not, then RemoteOpen just
" opens in the present session.

" Enclose <args> in single quotes so it can be passed as a function argument.
com -nargs=1 RemoteOpen :call RemoteOpen('<args>')
com -nargs=? RemoteInsert :call RemoteInsert('<args>')

" RemoteOpen: open a file remotely (if possible) {{{
" Description: checks all open vim windows to see if this file has been opened
"              anywhere and if so, opens it there instead of in this session.
function! RemoteOpen(arglist)

	" First construct line number and filename from argument. a:arglist is of
	" the form:
	"    +10 c:\path\to\file
	" or just
	" 	 c:\path\to\file
	if a:arglist =~ '^\s*+\d\+'
		let linenum = matchstr(a:arglist, '^\s*+\zs\d\+\ze')
		let filename = matchstr(a:arglist, '^\s*+\d\+\s*\zs.*\ze')
	else
		let linenum = 1
		let filename = matchstr(a:arglist, '^\s*\zs.*\ze')
	endif
	let filename = escape(filename, ' ')
	call Tex_Debug("linenum = ".linenum.', filename = '.filename, "ropen")

	" If there is no clientserver functionality, then just open in the present
	" session and return
	if !has('clientserver')
		call Tex_Debug("-clientserver, opening locally and returning", "ropen")
		exec "e ".filename
		exec linenum
		normal! zv
		return
	endif

	" Otherwise, loop through all available servers
	let servers = serverlist()
	" If there are no servers, open file locally.
	if servers == ''
		call Tex_Debug("no open servers, opening locally", "ropen")
		exec "e ".filename
		exec linenum
		let g:Remote_Server = 1
		normal! zv
		return
	endif

	let i = 1
	let server = s:Strntok(servers, "\n", i) 
	let targetServer = v:servername

	while server != ''
		" Find out if there was any server which was used by remoteOpen before
		" this. If a new gvim session was ever started via remoteOpen, then
		" g:Remote_Server will be set.
		if remote_expr(server, 'exists("g:Remote_Server")')
			let targetServer = server
		endif

		" Ask each server if that file is being edited by them.
		let bufnum = remote_expr(server, "bufnr('".filename."')")
		" If it is...
		if bufnum != -1
			" ask the server to edit that file and come to the foreground.
			" set a variable g:Remote_Server to indicate that this server
			" session has at least one file opened via RemoteOpen
			let targetServer = server
			break
		end
		
		let i = i + 1
		let server = s:Strntok(servers, "\n", i) 
	endwhile

	" If none of the servers have the file open, then open this file in the
	" first server. This has the advantage if yap tries to make vim open
	" multiple vims, then at least they will all be opened by the same gvim
	" server.
	call remote_send(targetServer, 
		\ "\<C-\>\<C-n>".
		\ ":let g:Remote_Server = 1\<CR>".
		\ ":drop ".filename."\<CR>".
		\ ":".linenum."\<CR>zv"
		\ )
	call remote_foreground(targetServer)
	" quit this vim session
	if v:servername != targetServer
		q
	endif
endfunction " }}}
" RemoteInsert: inserts a \cite'ation remotely (if possible) {{{
" Description:
function! RemoteInsert(...)

	let citation =  matchstr(argv(0), "\\[InsText('.cite{\\zs.\\{-}\\ze}');\\]")
	if citation == ""
		q
	endif

	" Otherwise, loop through all available servers
	let servers = serverlist()

	let i = 1
	let server = s:Strntok(servers, "\n", i) 
	let targetServer = v:servername

	while server != ''
		if remote_expr(server, 'exists("g:Remote_WaitingForCite")')
			call remote_send(server, citation . "\<CR>")
			call remote_foreground(server)
			if v:servername != server
				q
			else
				return
			endif
		endif

		let i = i + 1
		let server = s:Strntok(servers, "\n", i) 
	endwhile

	q

endfunction " }}}
" Strntok: extract the n^th token from a list {{{
" example: Strntok('1,23,3', ',', 2) = 23
fun! <SID>Strntok(s, tok, n)
	return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}')
endfun

" }}}

" vim:ft=vim:ts=4:sw=4:noet:fdm=marker:commentstring=\"\ %s:nowrap