1" Vim Plugin:	Edit the file with an existing Vim if possible
2" Maintainer:	Bram Moolenaar
3" Last Change:	2008 May 29
4
5" This is a plugin, drop it in your (Unix) ~/.vim/plugin or (Win32)
6" $VIM/vimfiles/plugin directory.  Or make a symbolic link, so that you
7" automatically use the latest version.
8
9" This plugin serves two purposes:
10" 1. On startup, if we were invoked with one file name argument and the file
11"    is not modified then try to find another Vim instance that is editing
12"    this file.  If there is one then bring it to the foreground and exit.
13" 2. When a file is edited and a swap file exists for it, try finding that
14"    other Vim and bring it to the foreground.  Requires Vim 7, because it
15"    uses the SwapExists autocommand event.
16if v:version < 700
17  finish
18endif
19
20" Function that finds the Vim instance that is editing "filename" and brings
21" it to the foreground.
22func s:EditElsewhere(filename)
23  let fname_esc = substitute(a:filename, "'", "''", "g")
24
25  let servers = serverlist()
26  while servers != ''
27    " Get next server name in "servername"; remove it from "servers".
28    let i = match(servers, "\n")
29    if i == -1
30      let servername = servers
31      let servers = ''
32    else
33      let servername = strpart(servers, 0, i)
34      let servers = strpart(servers, i + 1)
35    endif
36
37    " Skip ourselves.
38    if servername ==? v:servername
39      continue
40    endif
41
42    " Check if this server is editing our file.
43    if remote_expr(servername, "bufloaded('" . fname_esc . "')")
44      " Yes, bring it to the foreground.
45      if has("win32")
46	call remote_foreground(servername)
47      endif
48      call remote_expr(servername, "foreground()")
49
50      if remote_expr(servername, "exists('*EditExisting')")
51	" Make sure the file is visible in a window (not hidden).
52	" If v:swapcommand exists and is set, send it to the server.
53	if exists("v:swapcommand")
54	  let c = substitute(v:swapcommand, "'", "''", "g")
55	  call remote_expr(servername, "EditExisting('" . fname_esc . "', '" . c . "')")
56	else
57	  call remote_expr(servername, "EditExisting('" . fname_esc . "', '')")
58	endif
59      endif
60
61      if !(has('vim_starting') && has('gui_running') && has('gui_win32'))
62	" Tell the user what is happening.  Not when the GUI is starting
63	" though, it would result in a message box.
64	echomsg "File is being edited by " . servername
65	sleep 2
66      endif
67      return 'q'
68    endif
69  endwhile
70  return ''
71endfunc
72
73" When the plugin is loaded and there is one file name argument: Find another
74" Vim server that is editing this file right now.
75if argc() == 1 && !&modified
76  if s:EditElsewhere(expand("%:p")) == 'q'
77    quit
78  endif
79endif
80
81" Setup for handling the situation that an existing swap file is found.
82try
83  au! SwapExists * let v:swapchoice = s:EditElsewhere(expand("<afile>:p"))
84catch
85  " Without SwapExists we don't do anything for ":edit" commands
86endtry
87
88" Function used on the server to make the file visible and possibly execute a
89" command.
90func! EditExisting(fname, command)
91  " Get the window number of the file in the current tab page.
92  let winnr = bufwinnr(a:fname)
93  if winnr <= 0
94    " Not found, look in other tab pages.
95    let bufnr = bufnr(a:fname)
96    for i in range(tabpagenr('$'))
97      if index(tabpagebuflist(i + 1), bufnr) >= 0
98	" Make this tab page the current one and find the window number.
99	exe 'tabnext ' . (i + 1)
100	let winnr = bufwinnr(a:fname)
101	break;
102      endif
103    endfor
104  endif
105
106  if winnr > 0
107    exe winnr . "wincmd w"
108  elseif exists('*fnameescape')
109    exe "split " . fnameescape(a:fname)
110  else
111    exe "split " . escape(a:fname, " \t\n*?[{`$\\%#'\"|!<")
112  endif
113
114  if a:command != ''
115    exe "normal " . a:command
116  endif
117
118  redraw
119endfunc
120