xref: /vim-8.2.3635/src/ex_cmds2.c (revision 58ef8a31)
1edf3f97aSBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
2071d4279SBram Moolenaar  *
3071d4279SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
4071d4279SBram Moolenaar  *
5071d4279SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
6071d4279SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
7071d4279SBram Moolenaar  * See README.txt for an overview of the Vim source code.
8071d4279SBram Moolenaar  */
9071d4279SBram Moolenaar 
10071d4279SBram Moolenaar /*
11071d4279SBram Moolenaar  * ex_cmds2.c: some more functions for command line commands
12071d4279SBram Moolenaar  */
13071d4279SBram Moolenaar 
14071d4279SBram Moolenaar #include "vim.h"
15071d4279SBram Moolenaar #include "version.h"
16071d4279SBram Moolenaar 
17071d4279SBram Moolenaar /*
18071d4279SBram Moolenaar  * If 'autowrite' option set, try to write the file.
19071d4279SBram Moolenaar  * Careful: autocommands may make "buf" invalid!
20071d4279SBram Moolenaar  *
21071d4279SBram Moolenaar  * return FAIL for failure, OK otherwise
22071d4279SBram Moolenaar  */
23071d4279SBram Moolenaar     int
autowrite(buf_T * buf,int forceit)2478c0b7d4SBram Moolenaar autowrite(buf_T *buf, int forceit)
25071d4279SBram Moolenaar {
26373154b0SBram Moolenaar     int		r;
277c0a2f36SBram Moolenaar     bufref_T	bufref;
28373154b0SBram Moolenaar 
29071d4279SBram Moolenaar     if (!(p_aw || p_awa) || !p_write
30071d4279SBram Moolenaar #ifdef FEAT_QUICKFIX
31217e1b83SBram Moolenaar 	    // never autowrite a "nofile" or "nowrite" buffer
32071d4279SBram Moolenaar 	    || bt_dontwrite(buf)
33071d4279SBram Moolenaar #endif
34071d4279SBram Moolenaar 	    || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
35071d4279SBram Moolenaar 	return FAIL;
367c0a2f36SBram Moolenaar     set_bufref(&bufref, buf);
37373154b0SBram Moolenaar     r = buf_write_all(buf, forceit);
38373154b0SBram Moolenaar 
39217e1b83SBram Moolenaar     // Writing may succeed but the buffer still changed, e.g., when there is a
40217e1b83SBram Moolenaar     // conversion error.  We do want to return FAIL then.
417c0a2f36SBram Moolenaar     if (bufref_valid(&bufref) && bufIsChanged(buf))
42373154b0SBram Moolenaar 	r = FAIL;
43373154b0SBram Moolenaar     return r;
44071d4279SBram Moolenaar }
45071d4279SBram Moolenaar 
46071d4279SBram Moolenaar /*
478c9e7b00SBram Moolenaar  * Flush all buffers, except the ones that are readonly or are never written.
48071d4279SBram Moolenaar  */
49071d4279SBram Moolenaar     void
autowrite_all(void)5078c0b7d4SBram Moolenaar autowrite_all(void)
51071d4279SBram Moolenaar {
52071d4279SBram Moolenaar     buf_T	*buf;
53071d4279SBram Moolenaar 
54071d4279SBram Moolenaar     if (!(p_aw || p_awa) || !p_write)
55071d4279SBram Moolenaar 	return;
5629323590SBram Moolenaar     FOR_ALL_BUFFERS(buf)
578c9e7b00SBram Moolenaar 	if (bufIsChanged(buf) && !buf->b_p_ro && !bt_dontwrite(buf))
58071d4279SBram Moolenaar 	{
597c0a2f36SBram Moolenaar 	    bufref_T	bufref;
607c0a2f36SBram Moolenaar 
617c0a2f36SBram Moolenaar 	    set_bufref(&bufref, buf);
62f2bd8ef2SBram Moolenaar 
63071d4279SBram Moolenaar 	    (void)buf_write_all(buf, FALSE);
64f2bd8ef2SBram Moolenaar 
65217e1b83SBram Moolenaar 	    // an autocommand may have deleted the buffer
667c0a2f36SBram Moolenaar 	    if (!bufref_valid(&bufref))
67071d4279SBram Moolenaar 		buf = firstbuf;
68071d4279SBram Moolenaar 	}
69071d4279SBram Moolenaar }
70071d4279SBram Moolenaar 
71071d4279SBram Moolenaar /*
7245d3b145SBram Moolenaar  * Return TRUE if buffer was changed and cannot be abandoned.
7345d3b145SBram Moolenaar  * For flags use the CCGD_ values.
74071d4279SBram Moolenaar  */
75071d4279SBram Moolenaar     int
check_changed(buf_T * buf,int flags)7678c0b7d4SBram Moolenaar check_changed(buf_T *buf, int flags)
77071d4279SBram Moolenaar {
7845d3b145SBram Moolenaar     int		forceit = (flags & CCGD_FORCEIT);
797c0a2f36SBram Moolenaar     bufref_T	bufref;
807c0a2f36SBram Moolenaar 
817c0a2f36SBram Moolenaar     set_bufref(&bufref, buf);
8245d3b145SBram Moolenaar 
83071d4279SBram Moolenaar     if (       !forceit
84071d4279SBram Moolenaar 	    && bufIsChanged(buf)
8545d3b145SBram Moolenaar 	    && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1)
8645d3b145SBram Moolenaar 	    && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL))
87071d4279SBram Moolenaar     {
88071d4279SBram Moolenaar #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
89e1004401SBram Moolenaar 	if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
90071d4279SBram Moolenaar 	{
91071d4279SBram Moolenaar 	    buf_T	*buf2;
92071d4279SBram Moolenaar 	    int		count = 0;
93071d4279SBram Moolenaar 
9445d3b145SBram Moolenaar 	    if (flags & CCGD_ALLBUF)
9529323590SBram Moolenaar 		FOR_ALL_BUFFERS(buf2)
96071d4279SBram Moolenaar 		    if (bufIsChanged(buf2)
97071d4279SBram Moolenaar 				     && (buf2->b_ffname != NULL
98071d4279SBram Moolenaar # ifdef FEAT_BROWSE
99e1004401SBram Moolenaar 					 || (cmdmod.cmod_flags & CMOD_BROWSE)
100071d4279SBram Moolenaar # endif
101071d4279SBram Moolenaar 					))
102071d4279SBram Moolenaar 			++count;
1037c0a2f36SBram Moolenaar 	    if (!bufref_valid(&bufref))
104217e1b83SBram Moolenaar 		// Autocommand deleted buffer, oops!  It's not changed now.
105071d4279SBram Moolenaar 		return FALSE;
106f2bd8ef2SBram Moolenaar 
107071d4279SBram Moolenaar 	    dialog_changed(buf, count > 1);
108f2bd8ef2SBram Moolenaar 
1097c0a2f36SBram Moolenaar 	    if (!bufref_valid(&bufref))
110217e1b83SBram Moolenaar 		// Autocommand deleted buffer, oops!  It's not changed now.
111071d4279SBram Moolenaar 		return FALSE;
112071d4279SBram Moolenaar 	    return bufIsChanged(buf);
113071d4279SBram Moolenaar 	}
114071d4279SBram Moolenaar #endif
11545d3b145SBram Moolenaar 	if (flags & CCGD_EXCMD)
116f5be7cd0SBram Moolenaar 	    no_write_message();
11745d3b145SBram Moolenaar 	else
1187a76092aSBram Moolenaar 	    no_write_message_nobang(curbuf);
119071d4279SBram Moolenaar 	return TRUE;
120071d4279SBram Moolenaar     }
121071d4279SBram Moolenaar     return FALSE;
122071d4279SBram Moolenaar }
123071d4279SBram Moolenaar 
124071d4279SBram Moolenaar #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
125071d4279SBram Moolenaar 
126071d4279SBram Moolenaar #if defined(FEAT_BROWSE) || defined(PROTO)
127071d4279SBram Moolenaar /*
128071d4279SBram Moolenaar  * When wanting to write a file without a file name, ask the user for a name.
129071d4279SBram Moolenaar  */
130071d4279SBram Moolenaar     void
browse_save_fname(buf_T * buf)13178c0b7d4SBram Moolenaar browse_save_fname(buf_T *buf)
132071d4279SBram Moolenaar {
133071d4279SBram Moolenaar     if (buf->b_fname == NULL)
134071d4279SBram Moolenaar     {
135071d4279SBram Moolenaar 	char_u *fname;
136071d4279SBram Moolenaar 
1377b0294cbSBram Moolenaar 	fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1387b0294cbSBram Moolenaar 						 NULL, NULL, NULL, NULL, buf);
139071d4279SBram Moolenaar 	if (fname != NULL)
140071d4279SBram Moolenaar 	{
141071d4279SBram Moolenaar 	    if (setfname(buf, fname, NULL, TRUE) == OK)
142071d4279SBram Moolenaar 		buf->b_flags |= BF_NOTEDITED;
143071d4279SBram Moolenaar 	    vim_free(fname);
144071d4279SBram Moolenaar 	}
145071d4279SBram Moolenaar     }
146071d4279SBram Moolenaar }
147071d4279SBram Moolenaar #endif
148071d4279SBram Moolenaar 
149071d4279SBram Moolenaar /*
1509b486ca3SBram Moolenaar  * Ask the user what to do when abandoning a changed buffer.
151071d4279SBram Moolenaar  * Must check 'write' option first!
152071d4279SBram Moolenaar  */
153071d4279SBram Moolenaar     void
dialog_changed(buf_T * buf,int checkall)15478c0b7d4SBram Moolenaar dialog_changed(
15578c0b7d4SBram Moolenaar     buf_T	*buf,
156217e1b83SBram Moolenaar     int		checkall)	// may abandon all changed buffers
157071d4279SBram Moolenaar {
158d9462e39SBram Moolenaar     char_u	buff[DIALOG_MSG_SIZE];
159071d4279SBram Moolenaar     int		ret;
160071d4279SBram Moolenaar     buf_T	*buf2;
1618218f60bSBram Moolenaar     exarg_T     ea;
162071d4279SBram Moolenaar 
1633f9a1ff1SBram Moolenaar     dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname);
164071d4279SBram Moolenaar     if (checkall)
165071d4279SBram Moolenaar 	ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
166071d4279SBram Moolenaar     else
167071d4279SBram Moolenaar 	ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
168071d4279SBram Moolenaar 
1694ca41534SBram Moolenaar     // Init ea pseudo-structure, this is needed for the check_overwrite()
1704ca41534SBram Moolenaar     // function.
171a80faa89SBram Moolenaar     CLEAR_FIELD(ea);
1728218f60bSBram Moolenaar 
173071d4279SBram Moolenaar     if (ret == VIM_YES)
174071d4279SBram Moolenaar     {
175071d4279SBram Moolenaar #ifdef FEAT_BROWSE
176217e1b83SBram Moolenaar 	// May get file name, when there is none
177071d4279SBram Moolenaar 	browse_save_fname(buf);
178071d4279SBram Moolenaar #endif
1798218f60bSBram Moolenaar 	if (buf->b_fname != NULL && check_overwrite(&ea, buf,
1808218f60bSBram Moolenaar 				    buf->b_fname, buf->b_ffname, FALSE) == OK)
181217e1b83SBram Moolenaar 	    // didn't hit Cancel
182071d4279SBram Moolenaar 	    (void)buf_write_all(buf, FALSE);
183071d4279SBram Moolenaar     }
184071d4279SBram Moolenaar     else if (ret == VIM_NO)
185071d4279SBram Moolenaar     {
186c024b466SBram Moolenaar 	unchanged(buf, TRUE, FALSE);
187071d4279SBram Moolenaar     }
188071d4279SBram Moolenaar     else if (ret == VIM_ALL)
189071d4279SBram Moolenaar     {
190071d4279SBram Moolenaar 	/*
191071d4279SBram Moolenaar 	 * Write all modified files that can be written.
192071d4279SBram Moolenaar 	 * Skip readonly buffers, these need to be confirmed
193071d4279SBram Moolenaar 	 * individually.
194071d4279SBram Moolenaar 	 */
19529323590SBram Moolenaar 	FOR_ALL_BUFFERS(buf2)
196071d4279SBram Moolenaar 	{
197071d4279SBram Moolenaar 	    if (bufIsChanged(buf2)
198071d4279SBram Moolenaar 		    && (buf2->b_ffname != NULL
199071d4279SBram Moolenaar #ifdef FEAT_BROWSE
200e1004401SBram Moolenaar 			|| (cmdmod.cmod_flags & CMOD_BROWSE)
201071d4279SBram Moolenaar #endif
202071d4279SBram Moolenaar 			)
203071d4279SBram Moolenaar 		    && !buf2->b_p_ro)
204071d4279SBram Moolenaar 	    {
2057c0a2f36SBram Moolenaar 		bufref_T bufref;
2067c0a2f36SBram Moolenaar 
2077c0a2f36SBram Moolenaar 		set_bufref(&bufref, buf2);
208071d4279SBram Moolenaar #ifdef FEAT_BROWSE
209217e1b83SBram Moolenaar 		// May get file name, when there is none
210071d4279SBram Moolenaar 		browse_save_fname(buf2);
211071d4279SBram Moolenaar #endif
2128218f60bSBram Moolenaar 		if (buf2->b_fname != NULL && check_overwrite(&ea, buf2,
2138218f60bSBram Moolenaar 				  buf2->b_fname, buf2->b_ffname, FALSE) == OK)
214217e1b83SBram Moolenaar 		    // didn't hit Cancel
215071d4279SBram Moolenaar 		    (void)buf_write_all(buf2, FALSE);
216f2bd8ef2SBram Moolenaar 
217217e1b83SBram Moolenaar 		// an autocommand may have deleted the buffer
2187c0a2f36SBram Moolenaar 		if (!bufref_valid(&bufref))
219071d4279SBram Moolenaar 		    buf2 = firstbuf;
220071d4279SBram Moolenaar 	    }
221071d4279SBram Moolenaar 	}
222071d4279SBram Moolenaar     }
223071d4279SBram Moolenaar     else if (ret == VIM_DISCARDALL)
224071d4279SBram Moolenaar     {
225071d4279SBram Moolenaar 	/*
226071d4279SBram Moolenaar 	 * mark all buffers as unchanged
227071d4279SBram Moolenaar 	 */
22829323590SBram Moolenaar 	FOR_ALL_BUFFERS(buf2)
229c024b466SBram Moolenaar 	    unchanged(buf2, TRUE, FALSE);
230071d4279SBram Moolenaar     }
231071d4279SBram Moolenaar }
232071d4279SBram Moolenaar #endif
233071d4279SBram Moolenaar 
234071d4279SBram Moolenaar /*
235071d4279SBram Moolenaar  * Return TRUE if the buffer "buf" can be abandoned, either by making it
236071d4279SBram Moolenaar  * hidden, autowriting it or unloading it.
237071d4279SBram Moolenaar  */
238071d4279SBram Moolenaar     int
can_abandon(buf_T * buf,int forceit)23978c0b7d4SBram Moolenaar can_abandon(buf_T *buf, int forceit)
240071d4279SBram Moolenaar {
241eb44a68bSBram Moolenaar     return (	   buf_hide(buf)
242071d4279SBram Moolenaar 		|| !bufIsChanged(buf)
243071d4279SBram Moolenaar 		|| buf->b_nwindows > 1
244071d4279SBram Moolenaar 		|| autowrite(buf, forceit) == OK
245071d4279SBram Moolenaar 		|| forceit);
246071d4279SBram Moolenaar }
247071d4279SBram Moolenaar 
248970a1b82SBram Moolenaar /*
249970a1b82SBram Moolenaar  * Add a buffer number to "bufnrs", unless it's already there.
250970a1b82SBram Moolenaar  */
251970a1b82SBram Moolenaar     static void
add_bufnum(int * bufnrs,int * bufnump,int nr)25278c0b7d4SBram Moolenaar add_bufnum(int *bufnrs, int *bufnump, int nr)
253970a1b82SBram Moolenaar {
254970a1b82SBram Moolenaar     int i;
255970a1b82SBram Moolenaar 
256970a1b82SBram Moolenaar     for (i = 0; i < *bufnump; ++i)
257970a1b82SBram Moolenaar 	if (bufnrs[i] == nr)
258970a1b82SBram Moolenaar 	    return;
259970a1b82SBram Moolenaar     bufnrs[*bufnump] = nr;
260970a1b82SBram Moolenaar     *bufnump = *bufnump + 1;
261970a1b82SBram Moolenaar }
262970a1b82SBram Moolenaar 
263071d4279SBram Moolenaar /*
264071d4279SBram Moolenaar  * Return TRUE if any buffer was changed and cannot be abandoned.
265071d4279SBram Moolenaar  * That changed buffer becomes the current buffer.
26625cdd9c3SBram Moolenaar  * When "unload" is TRUE the current buffer is unloaded instead of making it
267027387f7SBram Moolenaar  * hidden.  This is used for ":q!".
268071d4279SBram Moolenaar  */
269071d4279SBram Moolenaar     int
check_changed_any(int hidden,int unload)27078c0b7d4SBram Moolenaar check_changed_any(
271217e1b83SBram Moolenaar     int		hidden,		// Only check hidden buffers
27278c0b7d4SBram Moolenaar     int		unload)
273071d4279SBram Moolenaar {
274970a1b82SBram Moolenaar     int		ret = FALSE;
275071d4279SBram Moolenaar     buf_T	*buf;
276071d4279SBram Moolenaar     int		save;
277970a1b82SBram Moolenaar     int		i;
278970a1b82SBram Moolenaar     int		bufnum = 0;
279970a1b82SBram Moolenaar     int		bufcount = 0;
280970a1b82SBram Moolenaar     int		*bufnrs;
281970a1b82SBram Moolenaar     tabpage_T   *tp;
282071d4279SBram Moolenaar     win_T	*wp;
283071d4279SBram Moolenaar 
284217e1b83SBram Moolenaar     // Make a list of all buffers, with the most important ones first.
28529323590SBram Moolenaar     FOR_ALL_BUFFERS(buf)
286970a1b82SBram Moolenaar 	++bufcount;
287970a1b82SBram Moolenaar 
288970a1b82SBram Moolenaar     if (bufcount == 0)
289071d4279SBram Moolenaar 	return FALSE;
290071d4279SBram Moolenaar 
291c799fe20SBram Moolenaar     bufnrs = ALLOC_MULT(int, bufcount);
292970a1b82SBram Moolenaar     if (bufnrs == NULL)
293970a1b82SBram Moolenaar 	return FALSE;
294970a1b82SBram Moolenaar 
295217e1b83SBram Moolenaar     // curbuf
296970a1b82SBram Moolenaar     bufnrs[bufnum++] = curbuf->b_fnum;
29725cdd9c3SBram Moolenaar 
298217e1b83SBram Moolenaar     // buffers in current tab
299970a1b82SBram Moolenaar     FOR_ALL_WINDOWS(wp)
300970a1b82SBram Moolenaar 	if (wp->w_buffer != curbuf)
301970a1b82SBram Moolenaar 	    add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
302970a1b82SBram Moolenaar 
303217e1b83SBram Moolenaar     // buffers in other tabs
30429323590SBram Moolenaar     FOR_ALL_TABPAGES(tp)
305970a1b82SBram Moolenaar 	if (tp != curtab)
306aeea7215SBram Moolenaar 	    FOR_ALL_WINDOWS_IN_TAB(tp, wp)
307970a1b82SBram Moolenaar 		add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
30825cdd9c3SBram Moolenaar 
309217e1b83SBram Moolenaar     // any other buffer
31029323590SBram Moolenaar     FOR_ALL_BUFFERS(buf)
311970a1b82SBram Moolenaar 	add_bufnum(bufnrs, &bufnum, buf->b_fnum);
312970a1b82SBram Moolenaar 
313970a1b82SBram Moolenaar     for (i = 0; i < bufnum; ++i)
314970a1b82SBram Moolenaar     {
315970a1b82SBram Moolenaar 	buf = buflist_findnr(bufnrs[i]);
316970a1b82SBram Moolenaar 	if (buf == NULL)
317970a1b82SBram Moolenaar 	    continue;
318970a1b82SBram Moolenaar 	if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
319970a1b82SBram Moolenaar 	{
3207c0a2f36SBram Moolenaar 	    bufref_T bufref;
3217c0a2f36SBram Moolenaar 
3227c0a2f36SBram Moolenaar 	    set_bufref(&bufref, buf);
32325cdd9c3SBram Moolenaar #ifdef FEAT_TERMINAL
32425cdd9c3SBram Moolenaar 	    if (term_job_running(buf->b_term))
32525cdd9c3SBram Moolenaar 	    {
32625cdd9c3SBram Moolenaar 		if (term_try_stop_job(buf) == FAIL)
32725cdd9c3SBram Moolenaar 		    break;
32825cdd9c3SBram Moolenaar 	    }
32925cdd9c3SBram Moolenaar 	    else
33025cdd9c3SBram Moolenaar #endif
331217e1b83SBram Moolenaar 	    // Try auto-writing the buffer.  If this fails but the buffer no
332217e1b83SBram Moolenaar 	    // longer exists it's not changed, that's OK.
33345d3b145SBram Moolenaar 	    if (check_changed(buf, (p_awa ? CCGD_AW : 0)
33445d3b145SBram Moolenaar 				 | CCGD_MULTWIN
3357c0a2f36SBram Moolenaar 				 | CCGD_ALLBUF) && bufref_valid(&bufref))
336217e1b83SBram Moolenaar 		break;	    // didn't save - still changes
337071d4279SBram Moolenaar 	}
338970a1b82SBram Moolenaar     }
339071d4279SBram Moolenaar 
340970a1b82SBram Moolenaar     if (i >= bufnum)
341970a1b82SBram Moolenaar 	goto theend;
342970a1b82SBram Moolenaar 
343217e1b83SBram Moolenaar     // Get here if "buf" cannot be abandoned.
344970a1b82SBram Moolenaar     ret = TRUE;
345071d4279SBram Moolenaar     exiting = FALSE;
346071d4279SBram Moolenaar #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
347071d4279SBram Moolenaar     /*
348071d4279SBram Moolenaar      * When ":confirm" used, don't give an error message.
349071d4279SBram Moolenaar      */
350e1004401SBram Moolenaar     if (!(p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)))
351071d4279SBram Moolenaar #endif
352071d4279SBram Moolenaar     {
353217e1b83SBram Moolenaar 	// There must be a wait_return for this message, do_buffer()
354217e1b83SBram Moolenaar 	// may cause a redraw.  But wait_return() is a no-op when vgetc()
355217e1b83SBram Moolenaar 	// is busy (Quit used from window menu), then make sure we don't
356217e1b83SBram Moolenaar 	// cause a scroll up.
35761660eadSBram Moolenaar 	if (vgetc_busy > 0)
358071d4279SBram Moolenaar 	{
359071d4279SBram Moolenaar 	    msg_row = cmdline_row;
360071d4279SBram Moolenaar 	    msg_col = 0;
361071d4279SBram Moolenaar 	    msg_didout = FALSE;
362071d4279SBram Moolenaar 	}
363eb44a68bSBram Moolenaar 	if (
364eb44a68bSBram Moolenaar #ifdef FEAT_TERMINAL
365eb44a68bSBram Moolenaar 		term_job_running(buf->b_term)
366f9e3e09fSBram Moolenaar 		    ? semsg(_("E947: Job still running in buffer \"%s\""),
367eb44a68bSBram Moolenaar 								  buf->b_fname)
368eb44a68bSBram Moolenaar 		    :
369eb44a68bSBram Moolenaar #endif
370f9e3e09fSBram Moolenaar 		semsg(_("E162: No write since last change for buffer \"%s\""),
371e1704badSBram Moolenaar 		    buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
372071d4279SBram Moolenaar 	{
373071d4279SBram Moolenaar 	    save = no_wait_return;
374071d4279SBram Moolenaar 	    no_wait_return = FALSE;
375071d4279SBram Moolenaar 	    wait_return(FALSE);
376071d4279SBram Moolenaar 	    no_wait_return = save;
377071d4279SBram Moolenaar 	}
378071d4279SBram Moolenaar     }
379071d4279SBram Moolenaar 
380217e1b83SBram Moolenaar     // Try to find a window that contains the buffer.
381071d4279SBram Moolenaar     if (buf != curbuf)
382970a1b82SBram Moolenaar 	FOR_ALL_TAB_WINDOWS(tp, wp)
383071d4279SBram Moolenaar 	    if (wp->w_buffer == buf)
384071d4279SBram Moolenaar 	    {
3857c0a2f36SBram Moolenaar 		bufref_T bufref;
3867c0a2f36SBram Moolenaar 
3877c0a2f36SBram Moolenaar 		set_bufref(&bufref, buf);
388f2bd8ef2SBram Moolenaar 
389970a1b82SBram Moolenaar 		goto_tabpage_win(tp, wp);
390f2bd8ef2SBram Moolenaar 
391bdace838SBram Moolenaar 		// Paranoia: did autocmd wipe out the buffer with changes?
3927c0a2f36SBram Moolenaar 		if (!bufref_valid(&bufref))
393970a1b82SBram Moolenaar 		    goto theend;
394970a1b82SBram Moolenaar 		goto buf_found;
395970a1b82SBram Moolenaar 	    }
396970a1b82SBram Moolenaar buf_found:
397071d4279SBram Moolenaar 
398217e1b83SBram Moolenaar     // Open the changed buffer in the current window.
399071d4279SBram Moolenaar     if (buf != curbuf)
400027387f7SBram Moolenaar 	set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
401071d4279SBram Moolenaar 
402970a1b82SBram Moolenaar theend:
403970a1b82SBram Moolenaar     vim_free(bufnrs);
404970a1b82SBram Moolenaar     return ret;
405071d4279SBram Moolenaar }
406071d4279SBram Moolenaar 
407071d4279SBram Moolenaar /*
408071d4279SBram Moolenaar  * return FAIL if there is no file name, OK if there is one
409071d4279SBram Moolenaar  * give error message for FAIL
410071d4279SBram Moolenaar  */
411071d4279SBram Moolenaar     int
check_fname(void)41278c0b7d4SBram Moolenaar check_fname(void)
413071d4279SBram Moolenaar {
414071d4279SBram Moolenaar     if (curbuf->b_ffname == NULL)
415071d4279SBram Moolenaar     {
416e29a27f6SBram Moolenaar 	emsg(_(e_no_file_name));
417071d4279SBram Moolenaar 	return FAIL;
418071d4279SBram Moolenaar     }
419071d4279SBram Moolenaar     return OK;
420071d4279SBram Moolenaar }
421071d4279SBram Moolenaar 
422071d4279SBram Moolenaar /*
423071d4279SBram Moolenaar  * flush the contents of a buffer, unless it has no file name
424071d4279SBram Moolenaar  *
425071d4279SBram Moolenaar  * return FAIL for failure, OK otherwise
426071d4279SBram Moolenaar  */
427071d4279SBram Moolenaar     int
buf_write_all(buf_T * buf,int forceit)42878c0b7d4SBram Moolenaar buf_write_all(buf_T *buf, int forceit)
429071d4279SBram Moolenaar {
430071d4279SBram Moolenaar     int	    retval;
431071d4279SBram Moolenaar     buf_T	*old_curbuf = curbuf;
432071d4279SBram Moolenaar 
433071d4279SBram Moolenaar     retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
434071d4279SBram Moolenaar 				   (linenr_T)1, buf->b_ml.ml_line_count, NULL,
435071d4279SBram Moolenaar 						  FALSE, forceit, TRUE, FALSE));
436071d4279SBram Moolenaar     if (curbuf != old_curbuf)
4372df6dcc5SBram Moolenaar     {
4388820b486SBram Moolenaar 	msg_source(HL_ATTR(HLF_W));
43932526b3cSBram Moolenaar 	msg(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
4402df6dcc5SBram Moolenaar     }
441071d4279SBram Moolenaar     return retval;
442071d4279SBram Moolenaar }
443071d4279SBram Moolenaar 
444071d4279SBram Moolenaar /*
445aa23b379SBram Moolenaar  * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo"
446071d4279SBram Moolenaar  */
447071d4279SBram Moolenaar     void
ex_listdo(exarg_T * eap)44878c0b7d4SBram Moolenaar ex_listdo(exarg_T *eap)
449071d4279SBram Moolenaar {
450071d4279SBram Moolenaar     int		i;
45132466aa2SBram Moolenaar     win_T	*wp;
45232466aa2SBram Moolenaar     tabpage_T	*tp;
453e25bb90bSBram Moolenaar     buf_T	*buf = curbuf;
454071d4279SBram Moolenaar     int		next_fnum = 0;
455f2bd8ef2SBram Moolenaar #if defined(FEAT_SYN_HL)
456071d4279SBram Moolenaar     char_u	*save_ei = NULL;
457071d4279SBram Moolenaar #endif
4581cd871b5SBram Moolenaar     char_u	*p_shm_save;
459aa23b379SBram Moolenaar #ifdef FEAT_QUICKFIX
460ed84b760SBram Moolenaar     int		qf_size = 0;
461aa23b379SBram Moolenaar     int		qf_idx;
462aa23b379SBram Moolenaar #endif
463071d4279SBram Moolenaar 
4640106e3d0SBram Moolenaar #ifndef FEAT_QUICKFIX
4650106e3d0SBram Moolenaar     if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo ||
4660106e3d0SBram Moolenaar 	    eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
4670106e3d0SBram Moolenaar     {
4680106e3d0SBram Moolenaar 	ex_ni(eap);
4690106e3d0SBram Moolenaar 	return;
4700106e3d0SBram Moolenaar     }
4710106e3d0SBram Moolenaar #endif
4720106e3d0SBram Moolenaar 
473f2bd8ef2SBram Moolenaar #if defined(FEAT_SYN_HL)
474910f66f9SBram Moolenaar     if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
475c7f1e400SBram Moolenaar     {
476217e1b83SBram Moolenaar 	// Don't do syntax HL autocommands.  Skipping the syntax file is a
477217e1b83SBram Moolenaar 	// great speed improvement.
478dcaf10e1SBram Moolenaar 	save_ei = au_event_disable(",Syntax");
479c7f1e400SBram Moolenaar 
480aeea7215SBram Moolenaar 	FOR_ALL_BUFFERS(buf)
481c7f1e400SBram Moolenaar 	    buf->b_flags &= ~BF_SYN_SET;
482c7f1e400SBram Moolenaar 	buf = curbuf;
483c7f1e400SBram Moolenaar     }
484071d4279SBram Moolenaar #endif
4856b1ee34aSBram Moolenaar #ifdef FEAT_CLIPBOARD
4866b1ee34aSBram Moolenaar     start_global_changes();
4876b1ee34aSBram Moolenaar #endif
488071d4279SBram Moolenaar 
489071d4279SBram Moolenaar     if (eap->cmdidx == CMD_windo
49032466aa2SBram Moolenaar 	    || eap->cmdidx == CMD_tabdo
491eb44a68bSBram Moolenaar 	    || buf_hide(curbuf)
49245d3b145SBram Moolenaar 	    || !check_changed(curbuf, CCGD_AW
49345d3b145SBram Moolenaar 				    | (eap->forceit ? CCGD_FORCEIT : 0)
49445d3b145SBram Moolenaar 				    | CCGD_EXCMD))
495071d4279SBram Moolenaar     {
496071d4279SBram Moolenaar 	i = 0;
497217e1b83SBram Moolenaar 	// start at the eap->line1 argument/window/buffer
49832466aa2SBram Moolenaar 	wp = firstwin;
49932466aa2SBram Moolenaar 	tp = first_tabpage;
500a162bc55SBram Moolenaar 	switch (eap->cmdidx)
501a162bc55SBram Moolenaar 	{
502a162bc55SBram Moolenaar 	    case CMD_windo:
503a162bc55SBram Moolenaar 		for ( ; wp != NULL && i + 1 < eap->line1; wp = wp->w_next)
504a162bc55SBram Moolenaar 		    i++;
505a162bc55SBram Moolenaar 		break;
506a162bc55SBram Moolenaar 	    case CMD_tabdo:
507a162bc55SBram Moolenaar 		for( ; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next)
508a162bc55SBram Moolenaar 		    i++;
509a162bc55SBram Moolenaar 		break;
510a162bc55SBram Moolenaar 	    case CMD_argdo:
511a162bc55SBram Moolenaar 		i = eap->line1 - 1;
512a162bc55SBram Moolenaar 		break;
513a162bc55SBram Moolenaar 	    default:
514a162bc55SBram Moolenaar 		break;
515a162bc55SBram Moolenaar 	}
516217e1b83SBram Moolenaar 	// set pcmark now
517071d4279SBram Moolenaar 	if (eap->cmdidx == CMD_bufdo)
518e25bb90bSBram Moolenaar 	{
519217e1b83SBram Moolenaar 	    // Advance to the first listed buffer after "eap->line1".
520e25bb90bSBram Moolenaar 	    for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1
521e25bb90bSBram Moolenaar 					  || !buf->b_p_bl); buf = buf->b_next)
522e25bb90bSBram Moolenaar 		if (buf->b_fnum > eap->line2)
523e25bb90bSBram Moolenaar 		{
524e25bb90bSBram Moolenaar 		    buf = NULL;
525e25bb90bSBram Moolenaar 		    break;
526e25bb90bSBram Moolenaar 		}
527e25bb90bSBram Moolenaar 	    if (buf != NULL)
528e25bb90bSBram Moolenaar 		goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum);
529e25bb90bSBram Moolenaar 	}
530aa23b379SBram Moolenaar #ifdef FEAT_QUICKFIX
531aa23b379SBram Moolenaar 	else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
532aa23b379SBram Moolenaar 		|| eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
533aa23b379SBram Moolenaar 	{
53425190db2SBram Moolenaar 	    qf_size = qf_get_valid_size(eap);
535aa23b379SBram Moolenaar 	    if (qf_size <= 0 || eap->line1 > qf_size)
536aa23b379SBram Moolenaar 		buf = NULL;
537aa23b379SBram Moolenaar 	    else
538aa23b379SBram Moolenaar 	    {
539aa23b379SBram Moolenaar 		ex_cc(eap);
540aa23b379SBram Moolenaar 
541aa23b379SBram Moolenaar 		buf = curbuf;
542aa23b379SBram Moolenaar 		i = eap->line1 - 1;
543aa23b379SBram Moolenaar 		if (eap->addr_count <= 0)
544217e1b83SBram Moolenaar 		    // default is all the quickfix/location list entries
545aa23b379SBram Moolenaar 		    eap->line2 = qf_size;
546aa23b379SBram Moolenaar 	    }
547aa23b379SBram Moolenaar 	}
548aa23b379SBram Moolenaar #endif
549071d4279SBram Moolenaar 	else
550071d4279SBram Moolenaar 	    setpcmark();
551217e1b83SBram Moolenaar 	listcmd_busy = TRUE;	    // avoids setting pcmark below
552071d4279SBram Moolenaar 
553e25bb90bSBram Moolenaar 	while (!got_int && buf != NULL)
554071d4279SBram Moolenaar 	{
555071d4279SBram Moolenaar 	    if (eap->cmdidx == CMD_argdo)
556071d4279SBram Moolenaar 	    {
557217e1b83SBram Moolenaar 		// go to argument "i"
558071d4279SBram Moolenaar 		if (i == ARGCOUNT)
559071d4279SBram Moolenaar 		    break;
560217e1b83SBram Moolenaar 		// Don't call do_argfile() when already there, it will try
561217e1b83SBram Moolenaar 		// reloading the file.
562d4755bb0SBram Moolenaar 		if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
5631cd871b5SBram Moolenaar 		{
564217e1b83SBram Moolenaar 		    // Clear 'shm' to avoid that the file message overwrites
565217e1b83SBram Moolenaar 		    // any output from the command.
5661cd871b5SBram Moolenaar 		    p_shm_save = vim_strsave(p_shm);
5671cd871b5SBram Moolenaar 		    set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
568071d4279SBram Moolenaar 		    do_argfile(eap, i);
5691cd871b5SBram Moolenaar 		    set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
5701cd871b5SBram Moolenaar 		    vim_free(p_shm_save);
5711cd871b5SBram Moolenaar 		}
572071d4279SBram Moolenaar 		if (curwin->w_arg_idx != i)
573071d4279SBram Moolenaar 		    break;
574071d4279SBram Moolenaar 	    }
575071d4279SBram Moolenaar 	    else if (eap->cmdidx == CMD_windo)
576071d4279SBram Moolenaar 	    {
577217e1b83SBram Moolenaar 		// go to window "wp"
57832466aa2SBram Moolenaar 		if (!win_valid(wp))
579071d4279SBram Moolenaar 		    break;
58032466aa2SBram Moolenaar 		win_goto(wp);
5814142324dSBram Moolenaar 		if (curwin != wp)
582217e1b83SBram Moolenaar 		    break;  // something must be wrong
58332466aa2SBram Moolenaar 		wp = curwin->w_next;
58432466aa2SBram Moolenaar 	    }
58532466aa2SBram Moolenaar 	    else if (eap->cmdidx == CMD_tabdo)
58632466aa2SBram Moolenaar 	    {
587217e1b83SBram Moolenaar 		// go to window "tp"
58832466aa2SBram Moolenaar 		if (!valid_tabpage(tp))
58932466aa2SBram Moolenaar 		    break;
59049e649fcSBram Moolenaar 		goto_tabpage_tp(tp, TRUE, TRUE);
59132466aa2SBram Moolenaar 		tp = tp->tp_next;
592071d4279SBram Moolenaar 	    }
593071d4279SBram Moolenaar 	    else if (eap->cmdidx == CMD_bufdo)
594071d4279SBram Moolenaar 	    {
595217e1b83SBram Moolenaar 		// Remember the number of the next listed buffer, in case
596217e1b83SBram Moolenaar 		// ":bwipe" is used or autocommands do something strange.
597071d4279SBram Moolenaar 		next_fnum = -1;
598071d4279SBram Moolenaar 		for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
599071d4279SBram Moolenaar 		    if (buf->b_p_bl)
600071d4279SBram Moolenaar 		    {
601071d4279SBram Moolenaar 			next_fnum = buf->b_fnum;
602071d4279SBram Moolenaar 			break;
603071d4279SBram Moolenaar 		    }
604071d4279SBram Moolenaar 	    }
605071d4279SBram Moolenaar 
606a162bc55SBram Moolenaar 	    ++i;
607a162bc55SBram Moolenaar 
608217e1b83SBram Moolenaar 	    // execute the command
609071d4279SBram Moolenaar 	    do_cmdline(eap->arg, eap->getline, eap->cookie,
610071d4279SBram Moolenaar 						DOCMD_VERBOSE + DOCMD_NOWAIT);
611071d4279SBram Moolenaar 
612071d4279SBram Moolenaar 	    if (eap->cmdidx == CMD_bufdo)
613071d4279SBram Moolenaar 	    {
614217e1b83SBram Moolenaar 		// Done?
615a162bc55SBram Moolenaar 		if (next_fnum < 0 || next_fnum > eap->line2)
616071d4279SBram Moolenaar 		    break;
617217e1b83SBram Moolenaar 		// Check if the buffer still exists.
61829323590SBram Moolenaar 		FOR_ALL_BUFFERS(buf)
619071d4279SBram Moolenaar 		    if (buf->b_fnum == next_fnum)
620071d4279SBram Moolenaar 			break;
621071d4279SBram Moolenaar 		if (buf == NULL)
622071d4279SBram Moolenaar 		    break;
6231cd871b5SBram Moolenaar 
624217e1b83SBram Moolenaar 		// Go to the next buffer.  Clear 'shm' to avoid that the file
625217e1b83SBram Moolenaar 		// message overwrites any output from the command.
6261cd871b5SBram Moolenaar 		p_shm_save = vim_strsave(p_shm);
6271cd871b5SBram Moolenaar 		set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
628071d4279SBram Moolenaar 		goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
6291cd871b5SBram Moolenaar 		set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
6301cd871b5SBram Moolenaar 		vim_free(p_shm_save);
6311cd871b5SBram Moolenaar 
632217e1b83SBram Moolenaar 		// If autocommands took us elsewhere, quit here.
633071d4279SBram Moolenaar 		if (curbuf->b_fnum != next_fnum)
634071d4279SBram Moolenaar 		    break;
635071d4279SBram Moolenaar 	    }
636071d4279SBram Moolenaar 
637aa23b379SBram Moolenaar #ifdef FEAT_QUICKFIX
638aa23b379SBram Moolenaar 	    if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
639aa23b379SBram Moolenaar 		    || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
640aa23b379SBram Moolenaar 	    {
641aa23b379SBram Moolenaar 		if (i >= qf_size || i >= eap->line2)
642aa23b379SBram Moolenaar 		    break;
643aa23b379SBram Moolenaar 
644aa23b379SBram Moolenaar 		qf_idx = qf_get_cur_idx(eap);
645aa23b379SBram Moolenaar 
64614798ab9SBram Moolenaar 		// Clear 'shm' to avoid that the file message overwrites
64714798ab9SBram Moolenaar 		// any output from the command.
64814798ab9SBram Moolenaar 		p_shm_save = vim_strsave(p_shm);
64914798ab9SBram Moolenaar 		set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
650aa23b379SBram Moolenaar 		ex_cnext(eap);
65114798ab9SBram Moolenaar 		set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
65214798ab9SBram Moolenaar 		vim_free(p_shm_save);
653aa23b379SBram Moolenaar 
654217e1b83SBram Moolenaar 		// If jumping to the next quickfix entry fails, quit here
655aa23b379SBram Moolenaar 		if (qf_get_cur_idx(eap) == qf_idx)
656aa23b379SBram Moolenaar 		    break;
657aa23b379SBram Moolenaar 	    }
658aa23b379SBram Moolenaar #endif
659aa23b379SBram Moolenaar 
660071d4279SBram Moolenaar 	    if (eap->cmdidx == CMD_windo)
661071d4279SBram Moolenaar 	    {
662217e1b83SBram Moolenaar 		validate_cursor();	// cursor may have moved
6638a3bb562SBram Moolenaar 
664217e1b83SBram Moolenaar 		// required when 'scrollbind' has been set
665071d4279SBram Moolenaar 		if (curwin->w_p_scb)
666071d4279SBram Moolenaar 		    do_check_scrollbind(TRUE);
667071d4279SBram Moolenaar 	    }
668a162bc55SBram Moolenaar 
669a162bc55SBram Moolenaar 	    if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo)
670a162bc55SBram Moolenaar 		if (i+1 > eap->line2)
671a162bc55SBram Moolenaar 		    break;
672a162bc55SBram Moolenaar 	    if (eap->cmdidx == CMD_argdo && i >= eap->line2)
673a162bc55SBram Moolenaar 		break;
674071d4279SBram Moolenaar 	}
675071d4279SBram Moolenaar 	listcmd_busy = FALSE;
676071d4279SBram Moolenaar     }
677071d4279SBram Moolenaar 
678f2bd8ef2SBram Moolenaar #if defined(FEAT_SYN_HL)
6796ac5429dSBram Moolenaar     if (save_ei != NULL)
6806ac5429dSBram Moolenaar     {
681c7f1e400SBram Moolenaar 	buf_T		*bnext;
682c7f1e400SBram Moolenaar 	aco_save_T	aco;
683c7f1e400SBram Moolenaar 
684dcaf10e1SBram Moolenaar 	au_event_restore(save_ei);
685c7f1e400SBram Moolenaar 
686c7f1e400SBram Moolenaar 	for (buf = firstbuf; buf != NULL; buf = bnext)
687c7f1e400SBram Moolenaar 	{
688c7f1e400SBram Moolenaar 	    bnext = buf->b_next;
689c7f1e400SBram Moolenaar 	    if (buf->b_nwindows > 0 && (buf->b_flags & BF_SYN_SET))
690c7f1e400SBram Moolenaar 	    {
691c7f1e400SBram Moolenaar 		buf->b_flags &= ~BF_SYN_SET;
692c7f1e400SBram Moolenaar 
693c7f1e400SBram Moolenaar 		// buffer was opened while Syntax autocommands were disabled,
694c7f1e400SBram Moolenaar 		// need to trigger them now.
695c7f1e400SBram Moolenaar 		if (buf == curbuf)
6966ac5429dSBram Moolenaar 		    apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
6976ac5429dSBram Moolenaar 					       curbuf->b_fname, TRUE, curbuf);
698c7f1e400SBram Moolenaar 		else
699c7f1e400SBram Moolenaar 		{
700c7f1e400SBram Moolenaar 		    aucmd_prepbuf(&aco, buf);
701c7f1e400SBram Moolenaar 		    apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
702c7f1e400SBram Moolenaar 						      buf->b_fname, TRUE, buf);
703c7f1e400SBram Moolenaar 		    aucmd_restbuf(&aco);
704c7f1e400SBram Moolenaar 		}
705c7f1e400SBram Moolenaar 
706c7f1e400SBram Moolenaar 		// start over, in case autocommands messed things up.
707c7f1e400SBram Moolenaar 		bnext = firstbuf;
708c7f1e400SBram Moolenaar 	    }
709c7f1e400SBram Moolenaar 	}
7106ac5429dSBram Moolenaar     }
711071d4279SBram Moolenaar #endif
7126b1ee34aSBram Moolenaar #ifdef FEAT_CLIPBOARD
7136b1ee34aSBram Moolenaar     end_global_changes();
7146b1ee34aSBram Moolenaar #endif
715071d4279SBram Moolenaar }
716071d4279SBram Moolenaar 
717071d4279SBram Moolenaar #ifdef FEAT_EVAL
718071d4279SBram Moolenaar /*
719071d4279SBram Moolenaar  * ":compiler[!] {name}"
720071d4279SBram Moolenaar  */
721071d4279SBram Moolenaar     void
ex_compiler(exarg_T * eap)72278c0b7d4SBram Moolenaar ex_compiler(exarg_T *eap)
723071d4279SBram Moolenaar {
724071d4279SBram Moolenaar     char_u	*buf;
725071d4279SBram Moolenaar     char_u	*old_cur_comp = NULL;
726071d4279SBram Moolenaar     char_u	*p;
727071d4279SBram Moolenaar 
728071d4279SBram Moolenaar     if (*eap->arg == NUL)
729071d4279SBram Moolenaar     {
730217e1b83SBram Moolenaar 	// List all compiler scripts.
731071d4279SBram Moolenaar 	do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
732217e1b83SBram Moolenaar 					// ) keep the indenter happy...
733071d4279SBram Moolenaar     }
734071d4279SBram Moolenaar     else
735071d4279SBram Moolenaar     {
736964b3746SBram Moolenaar 	buf = alloc(STRLEN(eap->arg) + 14);
737071d4279SBram Moolenaar 	if (buf != NULL)
738071d4279SBram Moolenaar 	{
739071d4279SBram Moolenaar 	    if (eap->forceit)
740071d4279SBram Moolenaar 	    {
741217e1b83SBram Moolenaar 		// ":compiler! {name}" sets global options
742071d4279SBram Moolenaar 		do_cmdline_cmd((char_u *)
743071d4279SBram Moolenaar 				   "command -nargs=* CompilerSet set <args>");
744071d4279SBram Moolenaar 	    }
745071d4279SBram Moolenaar 	    else
746071d4279SBram Moolenaar 	    {
747217e1b83SBram Moolenaar 		// ":compiler! {name}" sets local options.
748217e1b83SBram Moolenaar 		// To remain backwards compatible "current_compiler" is always
749217e1b83SBram Moolenaar 		// used.  A user's compiler plugin may set it, the distributed
750217e1b83SBram Moolenaar 		// plugin will then skip the settings.  Afterwards set
751217e1b83SBram Moolenaar 		// "b:current_compiler" and restore "current_compiler".
752217e1b83SBram Moolenaar 		// Explicitly prepend "g:" to make it work in a function.
7533d63e3f1SBram Moolenaar 		old_cur_comp = get_var_value((char_u *)"g:current_compiler");
754071d4279SBram Moolenaar 		if (old_cur_comp != NULL)
755071d4279SBram Moolenaar 		    old_cur_comp = vim_strsave(old_cur_comp);
756071d4279SBram Moolenaar 		do_cmdline_cmd((char_u *)
757*58ef8a31SBram Moolenaar 		   "command -nargs=* -keepscript CompilerSet setlocal <args>");
758071d4279SBram Moolenaar 	    }
7593d63e3f1SBram Moolenaar 	    do_unlet((char_u *)"g:current_compiler", TRUE);
7602ce06f6eSBram Moolenaar 	    do_unlet((char_u *)"b:current_compiler", TRUE);
761071d4279SBram Moolenaar 
762071d4279SBram Moolenaar 	    sprintf((char *)buf, "compiler/%s.vim", eap->arg);
7637f8989ddSBram Moolenaar 	    if (source_runtime(buf, DIP_ALL) == FAIL)
764f9e3e09fSBram Moolenaar 		semsg(_("E666: compiler not supported: %s"), eap->arg);
765071d4279SBram Moolenaar 	    vim_free(buf);
766071d4279SBram Moolenaar 
767071d4279SBram Moolenaar 	    do_cmdline_cmd((char_u *)":delcommand CompilerSet");
768071d4279SBram Moolenaar 
769217e1b83SBram Moolenaar 	    // Set "b:current_compiler" from "current_compiler".
7703d63e3f1SBram Moolenaar 	    p = get_var_value((char_u *)"g:current_compiler");
771071d4279SBram Moolenaar 	    if (p != NULL)
772071d4279SBram Moolenaar 		set_internal_string_var((char_u *)"b:current_compiler", p);
773071d4279SBram Moolenaar 
774217e1b83SBram Moolenaar 	    // Restore "current_compiler" for ":compiler {name}".
775071d4279SBram Moolenaar 	    if (!eap->forceit)
776071d4279SBram Moolenaar 	    {
777071d4279SBram Moolenaar 		if (old_cur_comp != NULL)
778071d4279SBram Moolenaar 		{
7793d63e3f1SBram Moolenaar 		    set_internal_string_var((char_u *)"g:current_compiler",
780071d4279SBram Moolenaar 								old_cur_comp);
781071d4279SBram Moolenaar 		    vim_free(old_cur_comp);
782071d4279SBram Moolenaar 		}
783071d4279SBram Moolenaar 		else
7843d63e3f1SBram Moolenaar 		    do_unlet((char_u *)"g:current_compiler", TRUE);
785071d4279SBram Moolenaar 	    }
786071d4279SBram Moolenaar 	}
787071d4279SBram Moolenaar     }
788071d4279SBram Moolenaar }
789071d4279SBram Moolenaar #endif
790071d4279SBram Moolenaar 
791f42dd3c3SBram Moolenaar #if defined(FEAT_PYTHON3) || defined(FEAT_PYTHON) || defined(PROTO)
792f42dd3c3SBram Moolenaar 
793f42dd3c3SBram Moolenaar # if (defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO)
794f42dd3c3SBram Moolenaar /*
795f42dd3c3SBram Moolenaar  * Detect Python 3 or 2, and initialize 'pyxversion'.
796f42dd3c3SBram Moolenaar  */
797f42dd3c3SBram Moolenaar     void
init_pyxversion(void)798f42dd3c3SBram Moolenaar init_pyxversion(void)
799f42dd3c3SBram Moolenaar {
800f42dd3c3SBram Moolenaar     if (p_pyx == 0)
801f42dd3c3SBram Moolenaar     {
802f42dd3c3SBram Moolenaar 	if (python3_enabled(FALSE))
803f42dd3c3SBram Moolenaar 	    p_pyx = 3;
804f42dd3c3SBram Moolenaar 	else if (python_enabled(FALSE))
805f42dd3c3SBram Moolenaar 	    p_pyx = 2;
806f42dd3c3SBram Moolenaar     }
807f42dd3c3SBram Moolenaar }
808f42dd3c3SBram Moolenaar # endif
809f42dd3c3SBram Moolenaar 
810f42dd3c3SBram Moolenaar /*
811f42dd3c3SBram Moolenaar  * Does a file contain one of the following strings at the beginning of any
812f42dd3c3SBram Moolenaar  * line?
813f42dd3c3SBram Moolenaar  * "#!(any string)python2"  => returns 2
814f42dd3c3SBram Moolenaar  * "#!(any string)python3"  => returns 3
815f42dd3c3SBram Moolenaar  * "# requires python 2.x"  => returns 2
816f42dd3c3SBram Moolenaar  * "# requires python 3.x"  => returns 3
817f42dd3c3SBram Moolenaar  * otherwise return 0.
818f42dd3c3SBram Moolenaar  */
819f42dd3c3SBram Moolenaar     static int
requires_py_version(char_u * filename)820f42dd3c3SBram Moolenaar requires_py_version(char_u *filename)
821f42dd3c3SBram Moolenaar {
822f42dd3c3SBram Moolenaar     FILE    *file;
823f42dd3c3SBram Moolenaar     int	    requires_py_version = 0;
824f42dd3c3SBram Moolenaar     int	    i, lines;
825f42dd3c3SBram Moolenaar 
826f42dd3c3SBram Moolenaar     lines = (int)p_mls;
827f42dd3c3SBram Moolenaar     if (lines < 0)
828f42dd3c3SBram Moolenaar 	lines = 5;
829f42dd3c3SBram Moolenaar 
830f42dd3c3SBram Moolenaar     file = mch_fopen((char *)filename, "r");
831f42dd3c3SBram Moolenaar     if (file != NULL)
832f42dd3c3SBram Moolenaar     {
833f42dd3c3SBram Moolenaar 	for (i = 0; i < lines; i++)
834f42dd3c3SBram Moolenaar 	{
835f42dd3c3SBram Moolenaar 	    if (vim_fgets(IObuff, IOSIZE, file))
836f42dd3c3SBram Moolenaar 		break;
837f42dd3c3SBram Moolenaar 	    if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!')
838f42dd3c3SBram Moolenaar 	    {
839217e1b83SBram Moolenaar 		// Check shebang.
840f42dd3c3SBram Moolenaar 		if (strstr((char *)IObuff + 2, "python2") != NULL)
841f42dd3c3SBram Moolenaar 		{
842f42dd3c3SBram Moolenaar 		    requires_py_version = 2;
843f42dd3c3SBram Moolenaar 		    break;
844f42dd3c3SBram Moolenaar 		}
845f42dd3c3SBram Moolenaar 		if (strstr((char *)IObuff + 2, "python3") != NULL)
846f42dd3c3SBram Moolenaar 		{
847f42dd3c3SBram Moolenaar 		    requires_py_version = 3;
848f42dd3c3SBram Moolenaar 		    break;
849f42dd3c3SBram Moolenaar 		}
850f42dd3c3SBram Moolenaar 	    }
851f42dd3c3SBram Moolenaar 	    IObuff[21] = '\0';
852f42dd3c3SBram Moolenaar 	    if (STRCMP("# requires python 2.x", IObuff) == 0)
853f42dd3c3SBram Moolenaar 	    {
854f42dd3c3SBram Moolenaar 		requires_py_version = 2;
855f42dd3c3SBram Moolenaar 		break;
856f42dd3c3SBram Moolenaar 	    }
857f42dd3c3SBram Moolenaar 	    if (STRCMP("# requires python 3.x", IObuff) == 0)
858f42dd3c3SBram Moolenaar 	    {
859f42dd3c3SBram Moolenaar 		requires_py_version = 3;
860f42dd3c3SBram Moolenaar 		break;
861f42dd3c3SBram Moolenaar 	    }
862f42dd3c3SBram Moolenaar 	}
863f42dd3c3SBram Moolenaar 	fclose(file);
864f42dd3c3SBram Moolenaar     }
865f42dd3c3SBram Moolenaar     return requires_py_version;
866f42dd3c3SBram Moolenaar }
867f42dd3c3SBram Moolenaar 
868f42dd3c3SBram Moolenaar 
869f42dd3c3SBram Moolenaar /*
870f42dd3c3SBram Moolenaar  * Source a python file using the requested python version.
871f42dd3c3SBram Moolenaar  */
872f42dd3c3SBram Moolenaar     static void
source_pyx_file(exarg_T * eap,char_u * fname)873f42dd3c3SBram Moolenaar source_pyx_file(exarg_T *eap, char_u *fname)
874f42dd3c3SBram Moolenaar {
875f42dd3c3SBram Moolenaar     exarg_T ex;
876f42dd3c3SBram Moolenaar     int	    v = requires_py_version(fname);
877f42dd3c3SBram Moolenaar 
878f42dd3c3SBram Moolenaar # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
879f42dd3c3SBram Moolenaar     init_pyxversion();
880f42dd3c3SBram Moolenaar # endif
881f42dd3c3SBram Moolenaar     if (v == 0)
882f42dd3c3SBram Moolenaar     {
883f42dd3c3SBram Moolenaar # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
884217e1b83SBram Moolenaar 	// user didn't choose a preference, 'pyx' is used
885f42dd3c3SBram Moolenaar 	v = p_pyx;
886f42dd3c3SBram Moolenaar # elif defined(FEAT_PYTHON)
887f42dd3c3SBram Moolenaar 	v = 2;
888f42dd3c3SBram Moolenaar # elif defined(FEAT_PYTHON3)
889f42dd3c3SBram Moolenaar 	v = 3;
890f42dd3c3SBram Moolenaar # endif
891f42dd3c3SBram Moolenaar     }
892f42dd3c3SBram Moolenaar 
893f42dd3c3SBram Moolenaar     /*
894f42dd3c3SBram Moolenaar      * now source, if required python version is not supported show
895f42dd3c3SBram Moolenaar      * unobtrusive message.
896f42dd3c3SBram Moolenaar      */
897f42dd3c3SBram Moolenaar     if (eap == NULL)
898a80faa89SBram Moolenaar 	CLEAR_FIELD(ex);
899f42dd3c3SBram Moolenaar     else
900f42dd3c3SBram Moolenaar 	ex = *eap;
901f42dd3c3SBram Moolenaar     ex.arg = fname;
902f42dd3c3SBram Moolenaar     ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3");
903f42dd3c3SBram Moolenaar 
904f42dd3c3SBram Moolenaar     if (v == 2)
905f42dd3c3SBram Moolenaar     {
906f42dd3c3SBram Moolenaar # ifdef FEAT_PYTHON
907f42dd3c3SBram Moolenaar 	ex_pyfile(&ex);
908f42dd3c3SBram Moolenaar # else
909f42dd3c3SBram Moolenaar 	vim_snprintf((char *)IObuff, IOSIZE,
910f42dd3c3SBram Moolenaar 		_("W20: Required python version 2.x not supported, ignoring file: %s"),
911f42dd3c3SBram Moolenaar 		fname);
91232526b3cSBram Moolenaar 	msg((char *)IObuff);
913f42dd3c3SBram Moolenaar # endif
914f42dd3c3SBram Moolenaar 	return;
915f42dd3c3SBram Moolenaar     }
916f42dd3c3SBram Moolenaar     else
917f42dd3c3SBram Moolenaar     {
918f42dd3c3SBram Moolenaar # ifdef FEAT_PYTHON3
919f42dd3c3SBram Moolenaar 	ex_py3file(&ex);
920f42dd3c3SBram Moolenaar # else
921f42dd3c3SBram Moolenaar 	vim_snprintf((char *)IObuff, IOSIZE,
922f42dd3c3SBram Moolenaar 		_("W21: Required python version 3.x not supported, ignoring file: %s"),
923f42dd3c3SBram Moolenaar 		fname);
92432526b3cSBram Moolenaar 	msg((char *)IObuff);
925f42dd3c3SBram Moolenaar # endif
926f42dd3c3SBram Moolenaar 	return;
927f42dd3c3SBram Moolenaar     }
928f42dd3c3SBram Moolenaar }
929f42dd3c3SBram Moolenaar 
930f42dd3c3SBram Moolenaar /*
931f42dd3c3SBram Moolenaar  * ":pyxfile {fname}"
932f42dd3c3SBram Moolenaar  */
933f42dd3c3SBram Moolenaar     void
ex_pyxfile(exarg_T * eap)934f42dd3c3SBram Moolenaar ex_pyxfile(exarg_T *eap)
935f42dd3c3SBram Moolenaar {
936f42dd3c3SBram Moolenaar     source_pyx_file(eap, eap->arg);
937f42dd3c3SBram Moolenaar }
938f42dd3c3SBram Moolenaar 
939f42dd3c3SBram Moolenaar /*
940f42dd3c3SBram Moolenaar  * ":pyx"
941f42dd3c3SBram Moolenaar  */
942f42dd3c3SBram Moolenaar     void
ex_pyx(exarg_T * eap)943f42dd3c3SBram Moolenaar ex_pyx(exarg_T *eap)
944f42dd3c3SBram Moolenaar {
945f42dd3c3SBram Moolenaar # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
946f42dd3c3SBram Moolenaar     init_pyxversion();
947f42dd3c3SBram Moolenaar     if (p_pyx == 2)
948f42dd3c3SBram Moolenaar 	ex_python(eap);
949f42dd3c3SBram Moolenaar     else
950f42dd3c3SBram Moolenaar 	ex_py3(eap);
951f42dd3c3SBram Moolenaar # elif defined(FEAT_PYTHON)
952f42dd3c3SBram Moolenaar     ex_python(eap);
953f42dd3c3SBram Moolenaar # elif defined(FEAT_PYTHON3)
954f42dd3c3SBram Moolenaar     ex_py3(eap);
955f42dd3c3SBram Moolenaar # endif
956f42dd3c3SBram Moolenaar }
957f42dd3c3SBram Moolenaar 
958f42dd3c3SBram Moolenaar /*
959f42dd3c3SBram Moolenaar  * ":pyxdo"
960f42dd3c3SBram Moolenaar  */
961f42dd3c3SBram Moolenaar     void
ex_pyxdo(exarg_T * eap)962f42dd3c3SBram Moolenaar ex_pyxdo(exarg_T *eap)
963f42dd3c3SBram Moolenaar {
964f42dd3c3SBram Moolenaar # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
965f42dd3c3SBram Moolenaar     init_pyxversion();
966f42dd3c3SBram Moolenaar     if (p_pyx == 2)
967f42dd3c3SBram Moolenaar 	ex_pydo(eap);
968f42dd3c3SBram Moolenaar     else
969f42dd3c3SBram Moolenaar 	ex_py3do(eap);
970f42dd3c3SBram Moolenaar # elif defined(FEAT_PYTHON)
971f42dd3c3SBram Moolenaar     ex_pydo(eap);
972f42dd3c3SBram Moolenaar # elif defined(FEAT_PYTHON3)
973f42dd3c3SBram Moolenaar     ex_py3do(eap);
974f42dd3c3SBram Moolenaar # endif
975f42dd3c3SBram Moolenaar }
976f42dd3c3SBram Moolenaar 
977f42dd3c3SBram Moolenaar #endif
978f42dd3c3SBram Moolenaar 
979071d4279SBram Moolenaar /*
980071d4279SBram Moolenaar  * ":checktime [buffer]"
981071d4279SBram Moolenaar  */
982071d4279SBram Moolenaar     void
ex_checktime(exarg_T * eap)98378c0b7d4SBram Moolenaar ex_checktime(exarg_T *eap)
984071d4279SBram Moolenaar {
985071d4279SBram Moolenaar     buf_T	*buf;
986071d4279SBram Moolenaar     int		save_no_check_timestamps = no_check_timestamps;
987071d4279SBram Moolenaar 
988071d4279SBram Moolenaar     no_check_timestamps = 0;
989217e1b83SBram Moolenaar     if (eap->addr_count == 0)	// default is all buffers
990071d4279SBram Moolenaar 	check_timestamps(FALSE);
991071d4279SBram Moolenaar     else
992071d4279SBram Moolenaar     {
993071d4279SBram Moolenaar 	buf = buflist_findnr((int)eap->line2);
994217e1b83SBram Moolenaar 	if (buf != NULL)	// cannot happen?
995071d4279SBram Moolenaar 	    (void)buf_check_timestamp(buf, FALSE);
996071d4279SBram Moolenaar     }
997071d4279SBram Moolenaar     no_check_timestamps = save_no_check_timestamps;
998071d4279SBram Moolenaar }
999