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