blob: b118c2d74bc07baceed646ffad4e62819a3e93d6 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * ex_cmds2.c: some more functions for command line commands
12 */
13
Bram Moolenaar071d4272004-06-13 20:20:40 +000014#include "vim.h"
Bram Moolenaar071d4272004-06-13 20:20:40 +000015#include "version.h"
16
Bram Moolenaar071d4272004-06-13 20:20:40 +000017/*
18 * If 'autowrite' option set, try to write the file.
19 * Careful: autocommands may make "buf" invalid!
20 *
21 * return FAIL for failure, OK otherwise
22 */
23 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010024autowrite(buf_T *buf, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025{
Bram Moolenaar373154b2007-02-13 05:19:30 +000026 int r;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020027 bufref_T bufref;
Bram Moolenaar373154b2007-02-13 05:19:30 +000028
Bram Moolenaar071d4272004-06-13 20:20:40 +000029 if (!(p_aw || p_awa) || !p_write
30#ifdef FEAT_QUICKFIX
Bram Moolenaar217e1b82019-12-01 21:41:28 +010031 // never autowrite a "nofile" or "nowrite" buffer
Bram Moolenaar373154b2007-02-13 05:19:30 +000032 || bt_dontwrite(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +000033#endif
Bram Moolenaar373154b2007-02-13 05:19:30 +000034 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000035 return FAIL;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020036 set_bufref(&bufref, buf);
Bram Moolenaar373154b2007-02-13 05:19:30 +000037 r = buf_write_all(buf, forceit);
38
Bram Moolenaar217e1b82019-12-01 21:41:28 +010039 // Writing may succeed but the buffer still changed, e.g., when there is a
40 // conversion error. We do want to return FAIL then.
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020041 if (bufref_valid(&bufref) && bufIsChanged(buf))
Bram Moolenaar373154b2007-02-13 05:19:30 +000042 r = FAIL;
43 return r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000044}
45
46/*
Bram Moolenaar8c9e7b02018-08-30 13:07:17 +020047 * Flush all buffers, except the ones that are readonly or are never written.
Bram Moolenaar071d4272004-06-13 20:20:40 +000048 */
49 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010050autowrite_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +000051{
52 buf_T *buf;
53
54 if (!(p_aw || p_awa) || !p_write)
55 return;
Bram Moolenaar29323592016-07-24 22:04:11 +020056 FOR_ALL_BUFFERS(buf)
Bram Moolenaar8c9e7b02018-08-30 13:07:17 +020057 if (bufIsChanged(buf) && !buf->b_p_ro && !bt_dontwrite(buf))
Bram Moolenaar071d4272004-06-13 20:20:40 +000058 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020059 bufref_T bufref;
60
61 set_bufref(&bufref, buf);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +010062
Bram Moolenaar071d4272004-06-13 20:20:40 +000063 (void)buf_write_all(buf, FALSE);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +010064
Bram Moolenaar217e1b82019-12-01 21:41:28 +010065 // an autocommand may have deleted the buffer
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020066 if (!bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +000067 buf = firstbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000068 }
69}
70
71/*
Bram Moolenaar45d3b142013-11-09 03:31:51 +010072 * Return TRUE if buffer was changed and cannot be abandoned.
73 * For flags use the CCGD_ values.
Bram Moolenaar071d4272004-06-13 20:20:40 +000074 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000075 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010076check_changed(buf_T *buf, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000077{
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020078 int forceit = (flags & CCGD_FORCEIT);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020079 bufref_T bufref;
80
81 set_bufref(&bufref, buf);
Bram Moolenaar45d3b142013-11-09 03:31:51 +010082
Bram Moolenaar071d4272004-06-13 20:20:40 +000083 if ( !forceit
84 && bufIsChanged(buf)
Bram Moolenaar45d3b142013-11-09 03:31:51 +010085 && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1)
86 && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL))
Bram Moolenaar071d4272004-06-13 20:20:40 +000087 {
88#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
Bram Moolenaare1004402020-10-24 20:49:43 +020089 if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
Bram Moolenaar071d4272004-06-13 20:20:40 +000090 {
91 buf_T *buf2;
92 int count = 0;
93
Bram Moolenaar45d3b142013-11-09 03:31:51 +010094 if (flags & CCGD_ALLBUF)
Bram Moolenaar29323592016-07-24 22:04:11 +020095 FOR_ALL_BUFFERS(buf2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000096 if (bufIsChanged(buf2)
97 && (buf2->b_ffname != NULL
98# ifdef FEAT_BROWSE
Bram Moolenaare1004402020-10-24 20:49:43 +020099 || (cmdmod.cmod_flags & CMOD_BROWSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100# endif
101 ))
102 ++count;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200103 if (!bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100104 // Autocommand deleted buffer, oops! It's not changed now.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105 return FALSE;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100106
Bram Moolenaar071d4272004-06-13 20:20:40 +0000107 dialog_changed(buf, count > 1);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100108
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200109 if (!bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100110 // Autocommand deleted buffer, oops! It's not changed now.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000111 return FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000112 return bufIsChanged(buf);
113 }
114#endif
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100115 if (flags & CCGD_EXCMD)
Bram Moolenaarf5be7cd2017-08-17 16:55:13 +0200116 no_write_message();
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100117 else
Bram Moolenaar7a760922018-02-19 23:10:02 +0100118 no_write_message_nobang(curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000119 return TRUE;
120 }
121 return FALSE;
122}
123
124#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
125
126#if defined(FEAT_BROWSE) || defined(PROTO)
127/*
128 * When wanting to write a file without a file name, ask the user for a name.
129 */
130 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100131browse_save_fname(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000132{
133 if (buf->b_fname == NULL)
134 {
135 char_u *fname;
136
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000137 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
138 NULL, NULL, NULL, NULL, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139 if (fname != NULL)
140 {
141 if (setfname(buf, fname, NULL, TRUE) == OK)
142 buf->b_flags |= BF_NOTEDITED;
143 vim_free(fname);
144 }
145 }
146}
147#endif
148
149/*
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200150 * Ask the user what to do when abandoning a changed buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151 * Must check 'write' option first!
152 */
153 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100154dialog_changed(
155 buf_T *buf,
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100156 int checkall) // may abandon all changed buffers
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157{
Bram Moolenaard9462e32011-04-11 21:35:11 +0200158 char_u buff[DIALOG_MSG_SIZE];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000159 int ret;
160 buf_T *buf2;
Bram Moolenaar8218f602012-04-25 17:32:18 +0200161 exarg_T ea;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162
Bram Moolenaar3f9a1ff2017-08-21 22:06:02 +0200163 dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000164 if (checkall)
165 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
166 else
167 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
168
Bram Moolenaar4ca41532019-05-09 21:48:37 +0200169 // Init ea pseudo-structure, this is needed for the check_overwrite()
170 // function.
Bram Moolenaara80faa82020-04-12 19:37:17 +0200171 CLEAR_FIELD(ea);
Bram Moolenaar8218f602012-04-25 17:32:18 +0200172
Bram Moolenaar071d4272004-06-13 20:20:40 +0000173 if (ret == VIM_YES)
174 {
175#ifdef FEAT_BROWSE
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100176 // May get file name, when there is none
Bram Moolenaar071d4272004-06-13 20:20:40 +0000177 browse_save_fname(buf);
178#endif
Bram Moolenaar8218f602012-04-25 17:32:18 +0200179 if (buf->b_fname != NULL && check_overwrite(&ea, buf,
180 buf->b_fname, buf->b_ffname, FALSE) == OK)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100181 // didn't hit Cancel
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182 (void)buf_write_all(buf, FALSE);
183 }
184 else if (ret == VIM_NO)
185 {
Bram Moolenaarc024b462019-06-08 18:07:21 +0200186 unchanged(buf, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000187 }
188 else if (ret == VIM_ALL)
189 {
190 /*
191 * Write all modified files that can be written.
192 * Skip readonly buffers, these need to be confirmed
193 * individually.
194 */
Bram Moolenaar29323592016-07-24 22:04:11 +0200195 FOR_ALL_BUFFERS(buf2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196 {
197 if (bufIsChanged(buf2)
198 && (buf2->b_ffname != NULL
199#ifdef FEAT_BROWSE
Bram Moolenaare1004402020-10-24 20:49:43 +0200200 || (cmdmod.cmod_flags & CMOD_BROWSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201#endif
202 )
203 && !buf2->b_p_ro)
204 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200205 bufref_T bufref;
206
207 set_bufref(&bufref, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208#ifdef FEAT_BROWSE
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100209 // May get file name, when there is none
Bram Moolenaar071d4272004-06-13 20:20:40 +0000210 browse_save_fname(buf2);
211#endif
Bram Moolenaar8218f602012-04-25 17:32:18 +0200212 if (buf2->b_fname != NULL && check_overwrite(&ea, buf2,
213 buf2->b_fname, buf2->b_ffname, FALSE) == OK)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100214 // didn't hit Cancel
Bram Moolenaar071d4272004-06-13 20:20:40 +0000215 (void)buf_write_all(buf2, FALSE);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100216
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100217 // an autocommand may have deleted the buffer
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200218 if (!bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000219 buf2 = firstbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000220 }
221 }
222 }
223 else if (ret == VIM_DISCARDALL)
224 {
225 /*
226 * mark all buffers as unchanged
227 */
Bram Moolenaar29323592016-07-24 22:04:11 +0200228 FOR_ALL_BUFFERS(buf2)
Bram Moolenaarc024b462019-06-08 18:07:21 +0200229 unchanged(buf2, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000230 }
231}
232#endif
233
234/*
235 * Return TRUE if the buffer "buf" can be abandoned, either by making it
236 * hidden, autowriting it or unloading it.
237 */
238 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100239can_abandon(buf_T *buf, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000240{
Bram Moolenaareb44a682017-08-03 22:44:55 +0200241 return ( buf_hide(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242 || !bufIsChanged(buf)
243 || buf->b_nwindows > 1
244 || autowrite(buf, forceit) == OK
245 || forceit);
246}
247
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100248/*
249 * Add a buffer number to "bufnrs", unless it's already there.
250 */
251 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100252add_bufnum(int *bufnrs, int *bufnump, int nr)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100253{
254 int i;
255
256 for (i = 0; i < *bufnump; ++i)
257 if (bufnrs[i] == nr)
258 return;
259 bufnrs[*bufnump] = nr;
260 *bufnump = *bufnump + 1;
261}
262
Bram Moolenaar071d4272004-06-13 20:20:40 +0000263/*
264 * Return TRUE if any buffer was changed and cannot be abandoned.
265 * That changed buffer becomes the current buffer.
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100266 * When "unload" is TRUE the current buffer is unloaded instead of making it
Bram Moolenaar027387f2016-01-02 22:25:52 +0100267 * hidden. This is used for ":q!".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000268 */
269 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100270check_changed_any(
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100271 int hidden, // Only check hidden buffers
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100272 int unload)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000273{
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100274 int ret = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000275 buf_T *buf;
276 int save;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100277 int i;
278 int bufnum = 0;
279 int bufcount = 0;
280 int *bufnrs;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100281 tabpage_T *tp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000282 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000283
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100284 // Make a list of all buffers, with the most important ones first.
Bram Moolenaar29323592016-07-24 22:04:11 +0200285 FOR_ALL_BUFFERS(buf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100286 ++bufcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000287
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100288 if (bufcount == 0)
289 return FALSE;
290
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200291 bufnrs = ALLOC_MULT(int, bufcount);
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100292 if (bufnrs == NULL)
293 return FALSE;
294
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100295 // curbuf
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100296 bufnrs[bufnum++] = curbuf->b_fnum;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100297
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100298 // buffers in current tab
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100299 FOR_ALL_WINDOWS(wp)
300 if (wp->w_buffer != curbuf)
301 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
302
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100303 // buffers in other tabs
Bram Moolenaar29323592016-07-24 22:04:11 +0200304 FOR_ALL_TABPAGES(tp)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100305 if (tp != curtab)
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200306 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100307 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100308
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100309 // any other buffer
Bram Moolenaar29323592016-07-24 22:04:11 +0200310 FOR_ALL_BUFFERS(buf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100311 add_bufnum(bufnrs, &bufnum, buf->b_fnum);
312
313 for (i = 0; i < bufnum; ++i)
314 {
315 buf = buflist_findnr(bufnrs[i]);
316 if (buf == NULL)
317 continue;
318 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
319 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200320 bufref_T bufref;
321
322 set_bufref(&bufref, buf);
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100323#ifdef FEAT_TERMINAL
324 if (term_job_running(buf->b_term))
325 {
326 if (term_try_stop_job(buf) == FAIL)
327 break;
328 }
329 else
330#endif
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100331 // Try auto-writing the buffer. If this fails but the buffer no
332 // longer exists it's not changed, that's OK.
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100333 if (check_changed(buf, (p_awa ? CCGD_AW : 0)
334 | CCGD_MULTWIN
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200335 | CCGD_ALLBUF) && bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100336 break; // didn't save - still changes
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100337 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000338 }
339
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100340 if (i >= bufnum)
341 goto theend;
342
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100343 // Get here if "buf" cannot be abandoned.
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100344 ret = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000345 exiting = FALSE;
346#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
347 /*
348 * When ":confirm" used, don't give an error message.
349 */
Bram Moolenaare1004402020-10-24 20:49:43 +0200350 if (!(p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000351#endif
352 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100353 // There must be a wait_return for this message, do_buffer()
354 // may cause a redraw. But wait_return() is a no-op when vgetc()
355 // is busy (Quit used from window menu), then make sure we don't
356 // cause a scroll up.
Bram Moolenaar61660ea2006-04-07 21:40:07 +0000357 if (vgetc_busy > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000358 {
359 msg_row = cmdline_row;
360 msg_col = 0;
361 msg_didout = FALSE;
362 }
Bram Moolenaareb44a682017-08-03 22:44:55 +0200363 if (
364#ifdef FEAT_TERMINAL
365 term_job_running(buf->b_term)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100366 ? semsg(_("E947: Job still running in buffer \"%s\""),
Bram Moolenaareb44a682017-08-03 22:44:55 +0200367 buf->b_fname)
368 :
369#endif
Bram Moolenaar1a992222021-12-31 17:25:48 +0000370 semsg(_(e_no_write_since_last_change_for_buffer_str),
Bram Moolenaare1704ba2012-10-03 18:25:00 +0200371 buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000372 {
373 save = no_wait_return;
374 no_wait_return = FALSE;
375 wait_return(FALSE);
376 no_wait_return = save;
377 }
378 }
379
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100380 // Try to find a window that contains the buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000381 if (buf != curbuf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100382 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383 if (wp->w_buffer == buf)
384 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200385 bufref_T bufref;
386
387 set_bufref(&bufref, buf);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100388
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100389 goto_tabpage_win(tp, wp);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100390
Bram Moolenaarbdace832019-03-02 10:13:42 +0100391 // Paranoia: did autocmd wipe out the buffer with changes?
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200392 if (!bufref_valid(&bufref))
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100393 goto theend;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100394 goto buf_found;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395 }
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100396buf_found:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000397
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100398 // Open the changed buffer in the current window.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000399 if (buf != curbuf)
Bram Moolenaar027387f2016-01-02 22:25:52 +0100400 set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000401
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100402theend:
403 vim_free(bufnrs);
404 return ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000405}
406
407/*
408 * return FAIL if there is no file name, OK if there is one
409 * give error message for FAIL
410 */
411 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100412check_fname(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000413{
414 if (curbuf->b_ffname == NULL)
415 {
Bram Moolenaare29a27f2021-07-20 21:07:36 +0200416 emsg(_(e_no_file_name));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000417 return FAIL;
418 }
419 return OK;
420}
421
422/*
423 * flush the contents of a buffer, unless it has no file name
424 *
425 * return FAIL for failure, OK otherwise
426 */
427 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100428buf_write_all(buf_T *buf, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000429{
430 int retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000431 buf_T *old_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000432
433 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
434 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
435 FALSE, forceit, TRUE, FALSE));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000436 if (curbuf != old_curbuf)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +0000437 {
Bram Moolenaar8820b482017-03-16 17:23:31 +0100438 msg_source(HL_ATTR(HLF_W));
Bram Moolenaar32526b32019-01-19 17:43:09 +0100439 msg(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +0000440 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000441 return retval;
442}
443
444/*
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200445 * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446 */
447 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100448ex_listdo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000449{
450 int i;
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000451 win_T *wp;
452 tabpage_T *tp;
Bram Moolenaare25bb902015-02-27 20:33:37 +0100453 buf_T *buf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000454 int next_fnum = 0;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100455#if defined(FEAT_SYN_HL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000456 char_u *save_ei = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000457#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000458 char_u *p_shm_save;
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200459#ifdef FEAT_QUICKFIX
Bram Moolenaared84b762015-09-09 22:35:29 +0200460 int qf_size = 0;
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200461 int qf_idx;
462#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000463
Bram Moolenaar0106e3d2016-02-23 18:55:43 +0100464#ifndef FEAT_QUICKFIX
465 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo ||
466 eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
467 {
468 ex_ni(eap);
469 return;
470 }
471#endif
472
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100473#if defined(FEAT_SYN_HL)
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000474 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200475 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100476 // Don't do syntax HL autocommands. Skipping the syntax file is a
477 // great speed improvement.
Bram Moolenaardcaf10e2005-01-21 11:55:25 +0000478 save_ei = au_event_disable(",Syntax");
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200479
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200480 FOR_ALL_BUFFERS(buf)
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200481 buf->b_flags &= ~BF_SYN_SET;
482 buf = curbuf;
483 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000484#endif
Bram Moolenaar6b1ee342014-08-06 18:17:11 +0200485#ifdef FEAT_CLIPBOARD
486 start_global_changes();
487#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000488
489 if (eap->cmdidx == CMD_windo
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000490 || eap->cmdidx == CMD_tabdo
Bram Moolenaareb44a682017-08-03 22:44:55 +0200491 || buf_hide(curbuf)
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100492 || !check_changed(curbuf, CCGD_AW
493 | (eap->forceit ? CCGD_FORCEIT : 0)
494 | CCGD_EXCMD))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000495 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000496 i = 0;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100497 // start at the eap->line1 argument/window/buffer
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000498 wp = firstwin;
499 tp = first_tabpage;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100500 switch (eap->cmdidx)
501 {
Bram Moolenaara162bc52015-01-07 16:54:21 +0100502 case CMD_windo:
503 for ( ; wp != NULL && i + 1 < eap->line1; wp = wp->w_next)
504 i++;
505 break;
506 case CMD_tabdo:
507 for( ; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next)
508 i++;
509 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100510 case CMD_argdo:
511 i = eap->line1 - 1;
512 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100513 default:
514 break;
515 }
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100516 // set pcmark now
Bram Moolenaar071d4272004-06-13 20:20:40 +0000517 if (eap->cmdidx == CMD_bufdo)
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200518 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100519 // Advance to the first listed buffer after "eap->line1".
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200520 for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1
Bram Moolenaare25bb902015-02-27 20:33:37 +0100521 || !buf->b_p_bl); buf = buf->b_next)
522 if (buf->b_fnum > eap->line2)
523 {
524 buf = NULL;
525 break;
526 }
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200527 if (buf != NULL)
Bram Moolenaare25bb902015-02-27 20:33:37 +0100528 goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200529 }
530#ifdef FEAT_QUICKFIX
531 else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
532 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
533 {
Bram Moolenaar25190db2019-05-04 15:05:28 +0200534 qf_size = qf_get_valid_size(eap);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200535 if (qf_size <= 0 || eap->line1 > qf_size)
536 buf = NULL;
537 else
538 {
539 ex_cc(eap);
540
541 buf = curbuf;
542 i = eap->line1 - 1;
543 if (eap->addr_count <= 0)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100544 // default is all the quickfix/location list entries
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200545 eap->line2 = qf_size;
546 }
547 }
548#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549 else
550 setpcmark();
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100551 listcmd_busy = TRUE; // avoids setting pcmark below
Bram Moolenaar071d4272004-06-13 20:20:40 +0000552
Bram Moolenaare25bb902015-02-27 20:33:37 +0100553 while (!got_int && buf != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000554 {
555 if (eap->cmdidx == CMD_argdo)
556 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100557 // go to argument "i"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558 if (i == ARGCOUNT)
559 break;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100560 // Don't call do_argfile() when already there, it will try
561 // reloading the file.
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000562 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000563 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100564 // Clear 'shm' to avoid that the file message overwrites
565 // any output from the command.
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000566 p_shm_save = vim_strsave(p_shm);
567 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000568 do_argfile(eap, i);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000569 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
570 vim_free(p_shm_save);
571 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000572 if (curwin->w_arg_idx != i)
573 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000574 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000575 else if (eap->cmdidx == CMD_windo)
576 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100577 // go to window "wp"
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000578 if (!win_valid(wp))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000579 break;
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000580 win_goto(wp);
Bram Moolenaar41423242007-05-03 20:11:13 +0000581 if (curwin != wp)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100582 break; // something must be wrong
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000583 wp = curwin->w_next;
584 }
585 else if (eap->cmdidx == CMD_tabdo)
586 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100587 // go to window "tp"
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000588 if (!valid_tabpage(tp))
589 break;
Bram Moolenaar49e649f2013-05-06 04:50:35 +0200590 goto_tabpage_tp(tp, TRUE, TRUE);
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000591 tp = tp->tp_next;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000592 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000593 else if (eap->cmdidx == CMD_bufdo)
594 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100595 // Remember the number of the next listed buffer, in case
596 // ":bwipe" is used or autocommands do something strange.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000597 next_fnum = -1;
598 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
599 if (buf->b_p_bl)
600 {
601 next_fnum = buf->b_fnum;
602 break;
603 }
604 }
605
Bram Moolenaara162bc52015-01-07 16:54:21 +0100606 ++i;
607
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100608 // execute the command
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609 do_cmdline(eap->arg, eap->getline, eap->cookie,
610 DOCMD_VERBOSE + DOCMD_NOWAIT);
611
612 if (eap->cmdidx == CMD_bufdo)
613 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100614 // Done?
Bram Moolenaara162bc52015-01-07 16:54:21 +0100615 if (next_fnum < 0 || next_fnum > eap->line2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000616 break;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100617 // Check if the buffer still exists.
Bram Moolenaar29323592016-07-24 22:04:11 +0200618 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000619 if (buf->b_fnum == next_fnum)
620 break;
621 if (buf == NULL)
622 break;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000623
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100624 // Go to the next buffer. Clear 'shm' to avoid that the file
625 // message overwrites any output from the command.
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000626 p_shm_save = vim_strsave(p_shm);
627 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000628 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000629 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
630 vim_free(p_shm_save);
631
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100632 // If autocommands took us elsewhere, quit here.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000633 if (curbuf->b_fnum != next_fnum)
634 break;
635 }
636
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200637#ifdef FEAT_QUICKFIX
638 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
639 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
640 {
641 if (i >= qf_size || i >= eap->line2)
642 break;
643
644 qf_idx = qf_get_cur_idx(eap);
645
Bram Moolenaar14798ab2020-05-28 21:30:11 +0200646 // Clear 'shm' to avoid that the file message overwrites
647 // any output from the command.
648 p_shm_save = vim_strsave(p_shm);
649 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200650 ex_cnext(eap);
Bram Moolenaar14798ab2020-05-28 21:30:11 +0200651 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
652 vim_free(p_shm_save);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200653
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100654 // If jumping to the next quickfix entry fails, quit here
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200655 if (qf_get_cur_idx(eap) == qf_idx)
656 break;
657 }
658#endif
659
Bram Moolenaar071d4272004-06-13 20:20:40 +0000660 if (eap->cmdidx == CMD_windo)
661 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100662 validate_cursor(); // cursor may have moved
Bram Moolenaar8a3bb562018-03-04 20:14:14 +0100663
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100664 // required when 'scrollbind' has been set
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665 if (curwin->w_p_scb)
666 do_check_scrollbind(TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 }
Bram Moolenaara162bc52015-01-07 16:54:21 +0100668
Bram Moolenaara162bc52015-01-07 16:54:21 +0100669 if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo)
670 if (i+1 > eap->line2)
671 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100672 if (eap->cmdidx == CMD_argdo && i >= eap->line2)
673 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000674 }
675 listcmd_busy = FALSE;
676 }
677
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100678#if defined(FEAT_SYN_HL)
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000679 if (save_ei != NULL)
680 {
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200681 buf_T *bnext;
682 aco_save_T aco;
683
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000684 au_event_restore(save_ei);
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200685
686 for (buf = firstbuf; buf != NULL; buf = bnext)
687 {
688 bnext = buf->b_next;
689 if (buf->b_nwindows > 0 && (buf->b_flags & BF_SYN_SET))
690 {
691 buf->b_flags &= ~BF_SYN_SET;
692
693 // buffer was opened while Syntax autocommands were disabled,
694 // need to trigger them now.
695 if (buf == curbuf)
696 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000697 curbuf->b_fname, TRUE, curbuf);
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200698 else
699 {
700 aucmd_prepbuf(&aco, buf);
701 apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
702 buf->b_fname, TRUE, buf);
703 aucmd_restbuf(&aco);
704 }
705
706 // start over, in case autocommands messed things up.
707 bnext = firstbuf;
708 }
709 }
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000710 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000711#endif
Bram Moolenaar6b1ee342014-08-06 18:17:11 +0200712#ifdef FEAT_CLIPBOARD
713 end_global_changes();
714#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000715}
716
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717#ifdef FEAT_EVAL
718/*
719 * ":compiler[!] {name}"
720 */
721 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100722ex_compiler(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000723{
724 char_u *buf;
725 char_u *old_cur_comp = NULL;
726 char_u *p;
727
728 if (*eap->arg == NUL)
729 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100730 // List all compiler scripts.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000731 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100732 // ) keep the indenter happy...
Bram Moolenaar071d4272004-06-13 20:20:40 +0000733 }
734 else
735 {
Bram Moolenaar964b3742019-05-24 18:54:09 +0200736 buf = alloc(STRLEN(eap->arg) + 14);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000737 if (buf != NULL)
738 {
739 if (eap->forceit)
740 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100741 // ":compiler! {name}" sets global options
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742 do_cmdline_cmd((char_u *)
743 "command -nargs=* CompilerSet set <args>");
744 }
745 else
746 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100747 // ":compiler! {name}" sets local options.
748 // To remain backwards compatible "current_compiler" is always
749 // used. A user's compiler plugin may set it, the distributed
750 // plugin will then skip the settings. Afterwards set
751 // "b:current_compiler" and restore "current_compiler".
752 // Explicitly prepend "g:" to make it work in a function.
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100753 old_cur_comp = get_var_value((char_u *)"g:current_compiler");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754 if (old_cur_comp != NULL)
755 old_cur_comp = vim_strsave(old_cur_comp);
756 do_cmdline_cmd((char_u *)
Bram Moolenaar58ef8a32021-11-12 11:25:11 +0000757 "command -nargs=* -keepscript CompilerSet setlocal <args>");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000758 }
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100759 do_unlet((char_u *)"g:current_compiler", TRUE);
Bram Moolenaar2ce06f62005-01-31 19:19:04 +0000760 do_unlet((char_u *)"b:current_compiler", TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000761
762 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
Bram Moolenaar7f8989d2016-03-12 22:11:39 +0100763 if (source_runtime(buf, DIP_ALL) == FAIL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100764 semsg(_("E666: compiler not supported: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000765 vim_free(buf);
766
767 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
768
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100769 // Set "b:current_compiler" from "current_compiler".
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100770 p = get_var_value((char_u *)"g:current_compiler");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000771 if (p != NULL)
772 set_internal_string_var((char_u *)"b:current_compiler", p);
773
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100774 // Restore "current_compiler" for ":compiler {name}".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775 if (!eap->forceit)
776 {
777 if (old_cur_comp != NULL)
778 {
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100779 set_internal_string_var((char_u *)"g:current_compiler",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780 old_cur_comp);
781 vim_free(old_cur_comp);
782 }
783 else
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100784 do_unlet((char_u *)"g:current_compiler", TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000785 }
786 }
787 }
788}
789#endif
790
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100791#if defined(FEAT_PYTHON3) || defined(FEAT_PYTHON) || defined(PROTO)
792
793# if (defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO)
794/*
795 * Detect Python 3 or 2, and initialize 'pyxversion'.
796 */
797 void
798init_pyxversion(void)
799{
800 if (p_pyx == 0)
801 {
802 if (python3_enabled(FALSE))
803 p_pyx = 3;
804 else if (python_enabled(FALSE))
805 p_pyx = 2;
806 }
807}
808# endif
809
810/*
811 * Does a file contain one of the following strings at the beginning of any
812 * line?
813 * "#!(any string)python2" => returns 2
814 * "#!(any string)python3" => returns 3
815 * "# requires python 2.x" => returns 2
816 * "# requires python 3.x" => returns 3
817 * otherwise return 0.
818 */
819 static int
820requires_py_version(char_u *filename)
821{
822 FILE *file;
823 int requires_py_version = 0;
824 int i, lines;
825
826 lines = (int)p_mls;
827 if (lines < 0)
828 lines = 5;
829
830 file = mch_fopen((char *)filename, "r");
831 if (file != NULL)
832 {
833 for (i = 0; i < lines; i++)
834 {
835 if (vim_fgets(IObuff, IOSIZE, file))
836 break;
837 if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!')
838 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100839 // Check shebang.
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100840 if (strstr((char *)IObuff + 2, "python2") != NULL)
841 {
842 requires_py_version = 2;
843 break;
844 }
845 if (strstr((char *)IObuff + 2, "python3") != NULL)
846 {
847 requires_py_version = 3;
848 break;
849 }
850 }
851 IObuff[21] = '\0';
852 if (STRCMP("# requires python 2.x", IObuff) == 0)
853 {
854 requires_py_version = 2;
855 break;
856 }
857 if (STRCMP("# requires python 3.x", IObuff) == 0)
858 {
859 requires_py_version = 3;
860 break;
861 }
862 }
863 fclose(file);
864 }
865 return requires_py_version;
866}
867
868
869/*
870 * Source a python file using the requested python version.
871 */
872 static void
873source_pyx_file(exarg_T *eap, char_u *fname)
874{
875 exarg_T ex;
876 int v = requires_py_version(fname);
877
878# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
879 init_pyxversion();
880# endif
881 if (v == 0)
882 {
883# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100884 // user didn't choose a preference, 'pyx' is used
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100885 v = p_pyx;
886# elif defined(FEAT_PYTHON)
887 v = 2;
888# elif defined(FEAT_PYTHON3)
889 v = 3;
890# endif
891 }
892
893 /*
894 * now source, if required python version is not supported show
895 * unobtrusive message.
896 */
897 if (eap == NULL)
Bram Moolenaara80faa82020-04-12 19:37:17 +0200898 CLEAR_FIELD(ex);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100899 else
900 ex = *eap;
901 ex.arg = fname;
902 ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3");
903
904 if (v == 2)
905 {
906# ifdef FEAT_PYTHON
907 ex_pyfile(&ex);
908# else
909 vim_snprintf((char *)IObuff, IOSIZE,
910 _("W20: Required python version 2.x not supported, ignoring file: %s"),
911 fname);
Bram Moolenaar32526b32019-01-19 17:43:09 +0100912 msg((char *)IObuff);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100913# endif
914 return;
915 }
916 else
917 {
918# ifdef FEAT_PYTHON3
919 ex_py3file(&ex);
920# else
921 vim_snprintf((char *)IObuff, IOSIZE,
922 _("W21: Required python version 3.x not supported, ignoring file: %s"),
923 fname);
Bram Moolenaar32526b32019-01-19 17:43:09 +0100924 msg((char *)IObuff);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100925# endif
926 return;
927 }
928}
929
930/*
931 * ":pyxfile {fname}"
932 */
933 void
934ex_pyxfile(exarg_T *eap)
935{
936 source_pyx_file(eap, eap->arg);
937}
938
939/*
940 * ":pyx"
941 */
942 void
943ex_pyx(exarg_T *eap)
944{
945# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
946 init_pyxversion();
947 if (p_pyx == 2)
948 ex_python(eap);
949 else
950 ex_py3(eap);
951# elif defined(FEAT_PYTHON)
952 ex_python(eap);
953# elif defined(FEAT_PYTHON3)
954 ex_py3(eap);
955# endif
956}
957
958/*
959 * ":pyxdo"
960 */
961 void
962ex_pyxdo(exarg_T *eap)
963{
964# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
965 init_pyxversion();
966 if (p_pyx == 2)
967 ex_pydo(eap);
968 else
969 ex_py3do(eap);
970# elif defined(FEAT_PYTHON)
971 ex_pydo(eap);
972# elif defined(FEAT_PYTHON3)
973 ex_py3do(eap);
974# endif
975}
976
977#endif
978
Bram Moolenaar071d4272004-06-13 20:20:40 +0000979/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000980 * ":checktime [buffer]"
981 */
982 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100983ex_checktime(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000984{
985 buf_T *buf;
986 int save_no_check_timestamps = no_check_timestamps;
987
988 no_check_timestamps = 0;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100989 if (eap->addr_count == 0) // default is all buffers
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990 check_timestamps(FALSE);
991 else
992 {
993 buf = buflist_findnr((int)eap->line2);
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100994 if (buf != NULL) // cannot happen?
Bram Moolenaar071d4272004-06-13 20:20:40 +0000995 (void)buf_check_timestamp(buf, FALSE);
996 }
997 no_check_timestamps = save_no_check_timestamps;
998}