blob: c13d354bc1c32121d405921c7661e74226ad812b [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
Bram Moolenaar217e1b82019-12-01 21:41:28 +010030 // never autowrite a "nofile" or "nowrite" buffer
Bram Moolenaar373154b2007-02-13 05:19:30 +000031 || bt_dontwrite(buf)
Bram Moolenaar373154b2007-02-13 05:19:30 +000032 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000033 return FAIL;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020034 set_bufref(&bufref, buf);
Bram Moolenaar373154b2007-02-13 05:19:30 +000035 r = buf_write_all(buf, forceit);
36
Bram Moolenaar217e1b82019-12-01 21:41:28 +010037 // Writing may succeed but the buffer still changed, e.g., when there is a
38 // conversion error. We do want to return FAIL then.
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020039 if (bufref_valid(&bufref) && bufIsChanged(buf))
Bram Moolenaar373154b2007-02-13 05:19:30 +000040 r = FAIL;
41 return r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000042}
43
44/*
Bram Moolenaar8c9e7b02018-08-30 13:07:17 +020045 * Flush all buffers, except the ones that are readonly or are never written.
Bram Moolenaar071d4272004-06-13 20:20:40 +000046 */
47 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010048autowrite_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +000049{
50 buf_T *buf;
51
52 if (!(p_aw || p_awa) || !p_write)
53 return;
Bram Moolenaar29323592016-07-24 22:04:11 +020054 FOR_ALL_BUFFERS(buf)
Bram Moolenaar8c9e7b02018-08-30 13:07:17 +020055 if (bufIsChanged(buf) && !buf->b_p_ro && !bt_dontwrite(buf))
Bram Moolenaar071d4272004-06-13 20:20:40 +000056 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020057 bufref_T bufref;
58
59 set_bufref(&bufref, buf);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +010060
Bram Moolenaar071d4272004-06-13 20:20:40 +000061 (void)buf_write_all(buf, FALSE);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +010062
Bram Moolenaar217e1b82019-12-01 21:41:28 +010063 // an autocommand may have deleted the buffer
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020064 if (!bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +000065 buf = firstbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000066 }
67}
68
69/*
Bram Moolenaar45d3b142013-11-09 03:31:51 +010070 * Return TRUE if buffer was changed and cannot be abandoned.
71 * For flags use the CCGD_ values.
Bram Moolenaar071d4272004-06-13 20:20:40 +000072 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000073 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010074check_changed(buf_T *buf, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000075{
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020076 int forceit = (flags & CCGD_FORCEIT);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +020077 bufref_T bufref;
78
79 set_bufref(&bufref, buf);
Bram Moolenaar45d3b142013-11-09 03:31:51 +010080
Bram Moolenaar071d4272004-06-13 20:20:40 +000081 if ( !forceit
82 && bufIsChanged(buf)
Bram Moolenaar45d3b142013-11-09 03:31:51 +010083 && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1)
84 && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL))
Bram Moolenaar071d4272004-06-13 20:20:40 +000085 {
86#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
Bram Moolenaare1004402020-10-24 20:49:43 +020087 if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
Bram Moolenaar071d4272004-06-13 20:20:40 +000088 {
Yee Cheng Chin15b314f2022-10-09 18:53:32 +010089# ifdef FEAT_TERMINAL
90 if (term_job_running(buf->b_term))
91 {
92 return term_confirm_stop(buf) == FAIL;
93 }
94# endif
95
Bram Moolenaar071d4272004-06-13 20:20:40 +000096 buf_T *buf2;
97 int count = 0;
98
Bram Moolenaar45d3b142013-11-09 03:31:51 +010099 if (flags & CCGD_ALLBUF)
Bram Moolenaar29323592016-07-24 22:04:11 +0200100 FOR_ALL_BUFFERS(buf2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000101 if (bufIsChanged(buf2)
102 && (buf2->b_ffname != NULL
103# ifdef FEAT_BROWSE
Bram Moolenaare1004402020-10-24 20:49:43 +0200104 || (cmdmod.cmod_flags & CMOD_BROWSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105# endif
106 ))
107 ++count;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200108 if (!bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100109 // Autocommand deleted buffer, oops! It's not changed now.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000110 return FALSE;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100111
Bram Moolenaar071d4272004-06-13 20:20:40 +0000112 dialog_changed(buf, count > 1);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100113
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200114 if (!bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100115 // Autocommand deleted buffer, oops! It's not changed now.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000116 return FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000117 return bufIsChanged(buf);
118 }
119#endif
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100120 if (flags & CCGD_EXCMD)
Bram Moolenaarf5be7cd2017-08-17 16:55:13 +0200121 no_write_message();
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100122 else
Bram Moolenaar7a760922018-02-19 23:10:02 +0100123 no_write_message_nobang(curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000124 return TRUE;
125 }
126 return FALSE;
127}
128
129#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
130
131#if defined(FEAT_BROWSE) || defined(PROTO)
132/*
133 * When wanting to write a file without a file name, ask the user for a name.
134 */
135 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100136browse_save_fname(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000137{
138 if (buf->b_fname == NULL)
139 {
140 char_u *fname;
141
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000142 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
143 NULL, NULL, NULL, NULL, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144 if (fname != NULL)
145 {
146 if (setfname(buf, fname, NULL, TRUE) == OK)
147 buf->b_flags |= BF_NOTEDITED;
148 vim_free(fname);
149 }
150 }
151}
152#endif
153
154/*
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200155 * Ask the user what to do when abandoning a changed buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000156 * Must check 'write' option first!
157 */
158 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100159dialog_changed(
160 buf_T *buf,
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100161 int checkall) // may abandon all changed buffers
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162{
Bram Moolenaard9462e32011-04-11 21:35:11 +0200163 char_u buff[DIALOG_MSG_SIZE];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000164 int ret;
165 buf_T *buf2;
Bram Moolenaar8218f602012-04-25 17:32:18 +0200166 exarg_T ea;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000167
Bram Moolenaar3f9a1ff2017-08-21 22:06:02 +0200168 dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000169 if (checkall)
170 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
171 else
172 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
173
Bram Moolenaar4ca41532019-05-09 21:48:37 +0200174 // Init ea pseudo-structure, this is needed for the check_overwrite()
175 // function.
Bram Moolenaara80faa82020-04-12 19:37:17 +0200176 CLEAR_FIELD(ea);
Bram Moolenaar8218f602012-04-25 17:32:18 +0200177
Bram Moolenaar071d4272004-06-13 20:20:40 +0000178 if (ret == VIM_YES)
179 {
180#ifdef FEAT_BROWSE
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100181 // May get file name, when there is none
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182 browse_save_fname(buf);
183#endif
Bram Moolenaar8218f602012-04-25 17:32:18 +0200184 if (buf->b_fname != NULL && check_overwrite(&ea, buf,
185 buf->b_fname, buf->b_ffname, FALSE) == OK)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100186 // didn't hit Cancel
Bram Moolenaar071d4272004-06-13 20:20:40 +0000187 (void)buf_write_all(buf, FALSE);
188 }
189 else if (ret == VIM_NO)
190 {
Bram Moolenaarc024b462019-06-08 18:07:21 +0200191 unchanged(buf, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000192 }
193 else if (ret == VIM_ALL)
194 {
195 /*
196 * Write all modified files that can be written.
197 * Skip readonly buffers, these need to be confirmed
198 * individually.
199 */
Bram Moolenaar29323592016-07-24 22:04:11 +0200200 FOR_ALL_BUFFERS(buf2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201 {
202 if (bufIsChanged(buf2)
203 && (buf2->b_ffname != NULL
204#ifdef FEAT_BROWSE
Bram Moolenaare1004402020-10-24 20:49:43 +0200205 || (cmdmod.cmod_flags & CMOD_BROWSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000206#endif
207 )
Yee Cheng Chin15b314f2022-10-09 18:53:32 +0100208 && !bt_dontwrite(buf2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000209 && !buf2->b_p_ro)
210 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200211 bufref_T bufref;
212
213 set_bufref(&bufref, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000214#ifdef FEAT_BROWSE
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100215 // May get file name, when there is none
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216 browse_save_fname(buf2);
217#endif
Bram Moolenaar8218f602012-04-25 17:32:18 +0200218 if (buf2->b_fname != NULL && check_overwrite(&ea, buf2,
219 buf2->b_fname, buf2->b_ffname, FALSE) == OK)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100220 // didn't hit Cancel
Bram Moolenaar071d4272004-06-13 20:20:40 +0000221 (void)buf_write_all(buf2, FALSE);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100222
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100223 // an autocommand may have deleted the buffer
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200224 if (!bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225 buf2 = firstbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000226 }
227 }
228 }
229 else if (ret == VIM_DISCARDALL)
230 {
231 /*
232 * mark all buffers as unchanged
233 */
Bram Moolenaar29323592016-07-24 22:04:11 +0200234 FOR_ALL_BUFFERS(buf2)
Bram Moolenaarc024b462019-06-08 18:07:21 +0200235 unchanged(buf2, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000236 }
237}
238#endif
239
240/*
241 * Return TRUE if the buffer "buf" can be abandoned, either by making it
242 * hidden, autowriting it or unloading it.
243 */
244 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100245can_abandon(buf_T *buf, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000246{
Bram Moolenaareb44a682017-08-03 22:44:55 +0200247 return ( buf_hide(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000248 || !bufIsChanged(buf)
249 || buf->b_nwindows > 1
250 || autowrite(buf, forceit) == OK
251 || forceit);
252}
253
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100254/*
255 * Add a buffer number to "bufnrs", unless it's already there.
256 */
257 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100258add_bufnum(int *bufnrs, int *bufnump, int nr)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100259{
260 int i;
261
262 for (i = 0; i < *bufnump; ++i)
263 if (bufnrs[i] == nr)
264 return;
265 bufnrs[*bufnump] = nr;
266 *bufnump = *bufnump + 1;
267}
268
Bram Moolenaar071d4272004-06-13 20:20:40 +0000269/*
270 * Return TRUE if any buffer was changed and cannot be abandoned.
271 * That changed buffer becomes the current buffer.
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100272 * When "unload" is TRUE the current buffer is unloaded instead of making it
Bram Moolenaar027387f2016-01-02 22:25:52 +0100273 * hidden. This is used for ":q!".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000274 */
275 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100276check_changed_any(
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100277 int hidden, // Only check hidden buffers
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100278 int unload)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000279{
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100280 int ret = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000281 buf_T *buf;
282 int save;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100283 int i;
284 int bufnum = 0;
285 int bufcount = 0;
286 int *bufnrs;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100287 tabpage_T *tp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000288 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000289
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100290 // Make a list of all buffers, with the most important ones first.
Bram Moolenaar29323592016-07-24 22:04:11 +0200291 FOR_ALL_BUFFERS(buf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100292 ++bufcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000293
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100294 if (bufcount == 0)
295 return FALSE;
296
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200297 bufnrs = ALLOC_MULT(int, bufcount);
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100298 if (bufnrs == NULL)
299 return FALSE;
300
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100301 // curbuf
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100302 bufnrs[bufnum++] = curbuf->b_fnum;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100303
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100304 // buffers in current tab
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100305 FOR_ALL_WINDOWS(wp)
306 if (wp->w_buffer != curbuf)
307 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
308
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100309 // buffers in other tabs
Bram Moolenaar29323592016-07-24 22:04:11 +0200310 FOR_ALL_TABPAGES(tp)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100311 if (tp != curtab)
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200312 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100313 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100314
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100315 // any other buffer
Bram Moolenaar29323592016-07-24 22:04:11 +0200316 FOR_ALL_BUFFERS(buf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100317 add_bufnum(bufnrs, &bufnum, buf->b_fnum);
318
319 for (i = 0; i < bufnum; ++i)
320 {
321 buf = buflist_findnr(bufnrs[i]);
322 if (buf == NULL)
323 continue;
324 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
325 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200326 bufref_T bufref;
327
328 set_bufref(&bufref, buf);
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100329#ifdef FEAT_TERMINAL
330 if (term_job_running(buf->b_term))
331 {
332 if (term_try_stop_job(buf) == FAIL)
333 break;
334 }
335 else
336#endif
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100337 // Try auto-writing the buffer. If this fails but the buffer no
338 // longer exists it's not changed, that's OK.
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100339 if (check_changed(buf, (p_awa ? CCGD_AW : 0)
340 | CCGD_MULTWIN
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200341 | CCGD_ALLBUF) && bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100342 break; // didn't save - still changes
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100343 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000344 }
345
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100346 if (i >= bufnum)
347 goto theend;
348
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100349 // Get here if "buf" cannot be abandoned.
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100350 ret = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000351 exiting = FALSE;
352#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
353 /*
354 * When ":confirm" used, don't give an error message.
355 */
Bram Moolenaare1004402020-10-24 20:49:43 +0200356 if (!(p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000357#endif
358 {
Bram Moolenaar13608d82022-08-29 15:06:50 +0100359 // There must be a wait_return() for this message, do_buffer()
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100360 // may cause a redraw. But wait_return() is a no-op when vgetc()
361 // is busy (Quit used from window menu), then make sure we don't
362 // cause a scroll up.
Bram Moolenaar61660ea2006-04-07 21:40:07 +0000363 if (vgetc_busy > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000364 {
365 msg_row = cmdline_row;
366 msg_col = 0;
367 msg_didout = FALSE;
368 }
Bram Moolenaareb44a682017-08-03 22:44:55 +0200369 if (
370#ifdef FEAT_TERMINAL
371 term_job_running(buf->b_term)
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000372 ? semsg(_(e_job_still_running_in_buffer_str), buf->b_fname)
Bram Moolenaareb44a682017-08-03 22:44:55 +0200373 :
374#endif
Bram Moolenaar1a992222021-12-31 17:25:48 +0000375 semsg(_(e_no_write_since_last_change_for_buffer_str),
Bram Moolenaare1704ba2012-10-03 18:25:00 +0200376 buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000377 {
378 save = no_wait_return;
379 no_wait_return = FALSE;
380 wait_return(FALSE);
381 no_wait_return = save;
382 }
383 }
384
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100385 // Try to find a window that contains the buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000386 if (buf != curbuf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100387 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000388 if (wp->w_buffer == buf)
389 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200390 bufref_T bufref;
391
392 set_bufref(&bufref, buf);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100393
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100394 goto_tabpage_win(tp, wp);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100395
Bram Moolenaarbdace832019-03-02 10:13:42 +0100396 // Paranoia: did autocmd wipe out the buffer with changes?
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200397 if (!bufref_valid(&bufref))
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100398 goto theend;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100399 goto buf_found;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000400 }
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100401buf_found:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000402
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100403 // Open the changed buffer in the current window.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000404 if (buf != curbuf)
Bram Moolenaar027387f2016-01-02 22:25:52 +0100405 set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000406
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100407theend:
408 vim_free(bufnrs);
409 return ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410}
411
412/*
413 * return FAIL if there is no file name, OK if there is one
414 * give error message for FAIL
415 */
416 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100417check_fname(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000418{
419 if (curbuf->b_ffname == NULL)
420 {
Bram Moolenaare29a27f2021-07-20 21:07:36 +0200421 emsg(_(e_no_file_name));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000422 return FAIL;
423 }
424 return OK;
425}
426
427/*
428 * flush the contents of a buffer, unless it has no file name
429 *
430 * return FAIL for failure, OK otherwise
431 */
432 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100433buf_write_all(buf_T *buf, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000434{
435 int retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000436 buf_T *old_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000437
438 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
439 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
440 FALSE, forceit, TRUE, FALSE));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000441 if (curbuf != old_curbuf)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +0000442 {
Bram Moolenaar8820b482017-03-16 17:23:31 +0100443 msg_source(HL_ATTR(HLF_W));
Bram Moolenaar32526b32019-01-19 17:43:09 +0100444 msg(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +0000445 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446 return retval;
447}
448
449/*
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200450 * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000451 */
452 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100453ex_listdo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000454{
455 int i;
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000456 win_T *wp;
457 tabpage_T *tp;
Bram Moolenaare25bb902015-02-27 20:33:37 +0100458 buf_T *buf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000459 int next_fnum = 0;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100460#if defined(FEAT_SYN_HL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000461 char_u *save_ei = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000462#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000463 char_u *p_shm_save;
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200464#ifdef FEAT_QUICKFIX
Bram Moolenaared84b762015-09-09 22:35:29 +0200465 int qf_size = 0;
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200466 int qf_idx;
467#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000468
Bram Moolenaar0106e3d2016-02-23 18:55:43 +0100469#ifndef FEAT_QUICKFIX
470 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo ||
471 eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
472 {
473 ex_ni(eap);
474 return;
475 }
476#endif
477
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100478#if defined(FEAT_SYN_HL)
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000479 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200480 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100481 // Don't do syntax HL autocommands. Skipping the syntax file is a
482 // great speed improvement.
Bram Moolenaardcaf10e2005-01-21 11:55:25 +0000483 save_ei = au_event_disable(",Syntax");
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200484
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200485 FOR_ALL_BUFFERS(buf)
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200486 buf->b_flags &= ~BF_SYN_SET;
487 buf = curbuf;
488 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000489#endif
Bram Moolenaar6b1ee342014-08-06 18:17:11 +0200490#ifdef FEAT_CLIPBOARD
491 start_global_changes();
492#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493
494 if (eap->cmdidx == CMD_windo
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000495 || eap->cmdidx == CMD_tabdo
Bram Moolenaareb44a682017-08-03 22:44:55 +0200496 || buf_hide(curbuf)
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100497 || !check_changed(curbuf, CCGD_AW
498 | (eap->forceit ? CCGD_FORCEIT : 0)
499 | CCGD_EXCMD))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000500 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000501 i = 0;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100502 // start at the eap->line1 argument/window/buffer
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000503 wp = firstwin;
504 tp = first_tabpage;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100505 switch (eap->cmdidx)
506 {
Bram Moolenaara162bc52015-01-07 16:54:21 +0100507 case CMD_windo:
508 for ( ; wp != NULL && i + 1 < eap->line1; wp = wp->w_next)
509 i++;
510 break;
511 case CMD_tabdo:
512 for( ; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next)
513 i++;
514 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100515 case CMD_argdo:
516 i = eap->line1 - 1;
517 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100518 default:
519 break;
520 }
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100521 // set pcmark now
Bram Moolenaar071d4272004-06-13 20:20:40 +0000522 if (eap->cmdidx == CMD_bufdo)
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200523 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100524 // Advance to the first listed buffer after "eap->line1".
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200525 for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1
Bram Moolenaare25bb902015-02-27 20:33:37 +0100526 || !buf->b_p_bl); buf = buf->b_next)
527 if (buf->b_fnum > eap->line2)
528 {
529 buf = NULL;
530 break;
531 }
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200532 if (buf != NULL)
Bram Moolenaare25bb902015-02-27 20:33:37 +0100533 goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200534 }
535#ifdef FEAT_QUICKFIX
536 else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
537 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
538 {
Bram Moolenaar25190db2019-05-04 15:05:28 +0200539 qf_size = qf_get_valid_size(eap);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200540 if (qf_size <= 0 || eap->line1 > qf_size)
541 buf = NULL;
542 else
543 {
544 ex_cc(eap);
545
546 buf = curbuf;
547 i = eap->line1 - 1;
548 if (eap->addr_count <= 0)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100549 // default is all the quickfix/location list entries
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200550 eap->line2 = qf_size;
551 }
552 }
553#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000554 else
555 setpcmark();
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100556 listcmd_busy = TRUE; // avoids setting pcmark below
Bram Moolenaar071d4272004-06-13 20:20:40 +0000557
Bram Moolenaare25bb902015-02-27 20:33:37 +0100558 while (!got_int && buf != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000559 {
560 if (eap->cmdidx == CMD_argdo)
561 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100562 // go to argument "i"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000563 if (i == ARGCOUNT)
564 break;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100565 // Don't call do_argfile() when already there, it will try
566 // reloading the file.
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000567 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000568 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100569 // Clear 'shm' to avoid that the file message overwrites
570 // any output from the command.
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000571 p_shm_save = vim_strsave(p_shm);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100572 set_option_value_give_err((char_u *)"shm",
573 0L, (char_u *)"", 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000574 do_argfile(eap, i);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100575 set_option_value_give_err((char_u *)"shm",
576 0L, p_shm_save, 0);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000577 vim_free(p_shm_save);
578 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000579 if (curwin->w_arg_idx != i)
580 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000581 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000582 else if (eap->cmdidx == CMD_windo)
583 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100584 // go to window "wp"
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000585 if (!win_valid(wp))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000586 break;
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000587 win_goto(wp);
Bram Moolenaar41423242007-05-03 20:11:13 +0000588 if (curwin != wp)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100589 break; // something must be wrong
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000590 wp = curwin->w_next;
591 }
592 else if (eap->cmdidx == CMD_tabdo)
593 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100594 // go to window "tp"
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000595 if (!valid_tabpage(tp))
596 break;
Bram Moolenaar49e649f2013-05-06 04:50:35 +0200597 goto_tabpage_tp(tp, TRUE, TRUE);
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000598 tp = tp->tp_next;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000599 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000600 else if (eap->cmdidx == CMD_bufdo)
601 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100602 // Remember the number of the next listed buffer, in case
603 // ":bwipe" is used or autocommands do something strange.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000604 next_fnum = -1;
605 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
606 if (buf->b_p_bl)
607 {
608 next_fnum = buf->b_fnum;
609 break;
610 }
611 }
612
Bram Moolenaara162bc52015-01-07 16:54:21 +0100613 ++i;
614
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100615 // execute the command
Bram Moolenaar071d4272004-06-13 20:20:40 +0000616 do_cmdline(eap->arg, eap->getline, eap->cookie,
617 DOCMD_VERBOSE + DOCMD_NOWAIT);
618
619 if (eap->cmdidx == CMD_bufdo)
620 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100621 // Done?
Bram Moolenaara162bc52015-01-07 16:54:21 +0100622 if (next_fnum < 0 || next_fnum > eap->line2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000623 break;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100624 // Check if the buffer still exists.
Bram Moolenaar29323592016-07-24 22:04:11 +0200625 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626 if (buf->b_fnum == next_fnum)
627 break;
628 if (buf == NULL)
629 break;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000630
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100631 // Go to the next buffer. Clear 'shm' to avoid that the file
632 // message overwrites any output from the command.
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000633 p_shm_save = vim_strsave(p_shm);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100634 set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000635 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100636 set_option_value_give_err((char_u *)"shm", 0L, p_shm_save, 0);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000637 vim_free(p_shm_save);
638
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100639 // If autocommands took us elsewhere, quit here.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000640 if (curbuf->b_fnum != next_fnum)
641 break;
642 }
643
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200644#ifdef FEAT_QUICKFIX
645 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
646 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
647 {
648 if (i >= qf_size || i >= eap->line2)
649 break;
650
651 qf_idx = qf_get_cur_idx(eap);
652
Bram Moolenaar14798ab2020-05-28 21:30:11 +0200653 // Clear 'shm' to avoid that the file message overwrites
654 // any output from the command.
655 p_shm_save = vim_strsave(p_shm);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100656 set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200657 ex_cnext(eap);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100658 set_option_value_give_err((char_u *)"shm", 0L, p_shm_save, 0);
Bram Moolenaar14798ab2020-05-28 21:30:11 +0200659 vim_free(p_shm_save);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200660
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100661 // If jumping to the next quickfix entry fails, quit here
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200662 if (qf_get_cur_idx(eap) == qf_idx)
663 break;
664 }
665#endif
666
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 if (eap->cmdidx == CMD_windo)
668 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100669 validate_cursor(); // cursor may have moved
Bram Moolenaar8a3bb562018-03-04 20:14:14 +0100670
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100671 // required when 'scrollbind' has been set
Bram Moolenaar071d4272004-06-13 20:20:40 +0000672 if (curwin->w_p_scb)
673 do_check_scrollbind(TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000674 }
Bram Moolenaara162bc52015-01-07 16:54:21 +0100675
Bram Moolenaara162bc52015-01-07 16:54:21 +0100676 if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo)
677 if (i+1 > eap->line2)
678 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100679 if (eap->cmdidx == CMD_argdo && i >= eap->line2)
680 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681 }
682 listcmd_busy = FALSE;
683 }
684
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100685#if defined(FEAT_SYN_HL)
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000686 if (save_ei != NULL)
687 {
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200688 buf_T *bnext;
689 aco_save_T aco;
690
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000691 au_event_restore(save_ei);
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200692
693 for (buf = firstbuf; buf != NULL; buf = bnext)
694 {
695 bnext = buf->b_next;
696 if (buf->b_nwindows > 0 && (buf->b_flags & BF_SYN_SET))
697 {
698 buf->b_flags &= ~BF_SYN_SET;
699
700 // buffer was opened while Syntax autocommands were disabled,
701 // need to trigger them now.
702 if (buf == curbuf)
703 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000704 curbuf->b_fname, TRUE, curbuf);
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200705 else
706 {
707 aucmd_prepbuf(&aco, buf);
708 apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
709 buf->b_fname, TRUE, buf);
710 aucmd_restbuf(&aco);
711 }
712
713 // start over, in case autocommands messed things up.
714 bnext = firstbuf;
715 }
716 }
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000717 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718#endif
Bram Moolenaar6b1ee342014-08-06 18:17:11 +0200719#ifdef FEAT_CLIPBOARD
720 end_global_changes();
721#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000722}
723
Bram Moolenaar071d4272004-06-13 20:20:40 +0000724#ifdef FEAT_EVAL
725/*
726 * ":compiler[!] {name}"
727 */
728 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100729ex_compiler(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000730{
731 char_u *buf;
732 char_u *old_cur_comp = NULL;
733 char_u *p;
734
735 if (*eap->arg == NUL)
736 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100737 // List all compiler scripts.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000738 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100739 // ) keep the indenter happy...
Bram Moolenaar071d4272004-06-13 20:20:40 +0000740 }
741 else
742 {
Bram Moolenaar964b3742019-05-24 18:54:09 +0200743 buf = alloc(STRLEN(eap->arg) + 14);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000744 if (buf != NULL)
745 {
746 if (eap->forceit)
747 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100748 // ":compiler! {name}" sets global options
Bram Moolenaar071d4272004-06-13 20:20:40 +0000749 do_cmdline_cmd((char_u *)
750 "command -nargs=* CompilerSet set <args>");
751 }
752 else
753 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100754 // ":compiler! {name}" sets local options.
755 // To remain backwards compatible "current_compiler" is always
756 // used. A user's compiler plugin may set it, the distributed
757 // plugin will then skip the settings. Afterwards set
758 // "b:current_compiler" and restore "current_compiler".
759 // Explicitly prepend "g:" to make it work in a function.
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100760 old_cur_comp = get_var_value((char_u *)"g:current_compiler");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000761 if (old_cur_comp != NULL)
762 old_cur_comp = vim_strsave(old_cur_comp);
763 do_cmdline_cmd((char_u *)
Bram Moolenaar58ef8a32021-11-12 11:25:11 +0000764 "command -nargs=* -keepscript CompilerSet setlocal <args>");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000765 }
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100766 do_unlet((char_u *)"g:current_compiler", TRUE);
Bram Moolenaar2ce06f62005-01-31 19:19:04 +0000767 do_unlet((char_u *)"b:current_compiler", TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000768
769 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
Bram Moolenaar7f8989d2016-03-12 22:11:39 +0100770 if (source_runtime(buf, DIP_ALL) == FAIL)
Bram Moolenaara6f79292022-01-04 21:30:47 +0000771 semsg(_(e_compiler_not_supported_str), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000772 vim_free(buf);
773
774 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
775
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100776 // Set "b:current_compiler" from "current_compiler".
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100777 p = get_var_value((char_u *)"g:current_compiler");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000778 if (p != NULL)
779 set_internal_string_var((char_u *)"b:current_compiler", p);
780
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100781 // Restore "current_compiler" for ":compiler {name}".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782 if (!eap->forceit)
783 {
784 if (old_cur_comp != NULL)
785 {
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100786 set_internal_string_var((char_u *)"g:current_compiler",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000787 old_cur_comp);
788 vim_free(old_cur_comp);
789 }
790 else
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100791 do_unlet((char_u *)"g:current_compiler", TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000792 }
793 }
794 }
795}
796#endif
797
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100798#if defined(FEAT_PYTHON3) || defined(FEAT_PYTHON) || defined(PROTO)
799
800# if (defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO)
801/*
802 * Detect Python 3 or 2, and initialize 'pyxversion'.
803 */
804 void
805init_pyxversion(void)
806{
807 if (p_pyx == 0)
808 {
809 if (python3_enabled(FALSE))
810 p_pyx = 3;
811 else if (python_enabled(FALSE))
812 p_pyx = 2;
813 }
814}
815# endif
816
817/*
818 * Does a file contain one of the following strings at the beginning of any
819 * line?
820 * "#!(any string)python2" => returns 2
821 * "#!(any string)python3" => returns 3
822 * "# requires python 2.x" => returns 2
823 * "# requires python 3.x" => returns 3
824 * otherwise return 0.
825 */
826 static int
827requires_py_version(char_u *filename)
828{
829 FILE *file;
830 int requires_py_version = 0;
831 int i, lines;
832
833 lines = (int)p_mls;
834 if (lines < 0)
835 lines = 5;
836
837 file = mch_fopen((char *)filename, "r");
838 if (file != NULL)
839 {
840 for (i = 0; i < lines; i++)
841 {
842 if (vim_fgets(IObuff, IOSIZE, file))
843 break;
844 if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!')
845 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100846 // Check shebang.
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100847 if (strstr((char *)IObuff + 2, "python2") != NULL)
848 {
849 requires_py_version = 2;
850 break;
851 }
852 if (strstr((char *)IObuff + 2, "python3") != NULL)
853 {
854 requires_py_version = 3;
855 break;
856 }
857 }
858 IObuff[21] = '\0';
859 if (STRCMP("# requires python 2.x", IObuff) == 0)
860 {
861 requires_py_version = 2;
862 break;
863 }
864 if (STRCMP("# requires python 3.x", IObuff) == 0)
865 {
866 requires_py_version = 3;
867 break;
868 }
869 }
870 fclose(file);
871 }
872 return requires_py_version;
873}
874
875
876/*
877 * Source a python file using the requested python version.
878 */
879 static void
880source_pyx_file(exarg_T *eap, char_u *fname)
881{
882 exarg_T ex;
883 int v = requires_py_version(fname);
884
885# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
886 init_pyxversion();
887# endif
888 if (v == 0)
889 {
890# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100891 // user didn't choose a preference, 'pyx' is used
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100892 v = p_pyx;
893# elif defined(FEAT_PYTHON)
894 v = 2;
895# elif defined(FEAT_PYTHON3)
896 v = 3;
897# endif
898 }
899
900 /*
901 * now source, if required python version is not supported show
902 * unobtrusive message.
903 */
904 if (eap == NULL)
Bram Moolenaara80faa82020-04-12 19:37:17 +0200905 CLEAR_FIELD(ex);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100906 else
907 ex = *eap;
908 ex.arg = fname;
909 ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3");
910
911 if (v == 2)
912 {
913# ifdef FEAT_PYTHON
914 ex_pyfile(&ex);
915# else
916 vim_snprintf((char *)IObuff, IOSIZE,
917 _("W20: Required python version 2.x not supported, ignoring file: %s"),
918 fname);
Bram Moolenaar32526b32019-01-19 17:43:09 +0100919 msg((char *)IObuff);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100920# endif
921 return;
922 }
923 else
924 {
925# ifdef FEAT_PYTHON3
926 ex_py3file(&ex);
927# else
928 vim_snprintf((char *)IObuff, IOSIZE,
929 _("W21: Required python version 3.x not supported, ignoring file: %s"),
930 fname);
Bram Moolenaar32526b32019-01-19 17:43:09 +0100931 msg((char *)IObuff);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100932# endif
933 return;
934 }
935}
936
937/*
938 * ":pyxfile {fname}"
939 */
940 void
941ex_pyxfile(exarg_T *eap)
942{
943 source_pyx_file(eap, eap->arg);
944}
945
946/*
947 * ":pyx"
948 */
949 void
950ex_pyx(exarg_T *eap)
951{
952# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
953 init_pyxversion();
954 if (p_pyx == 2)
955 ex_python(eap);
956 else
957 ex_py3(eap);
958# elif defined(FEAT_PYTHON)
959 ex_python(eap);
960# elif defined(FEAT_PYTHON3)
961 ex_py3(eap);
962# endif
963}
964
965/*
966 * ":pyxdo"
967 */
968 void
969ex_pyxdo(exarg_T *eap)
970{
971# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
972 init_pyxversion();
973 if (p_pyx == 2)
974 ex_pydo(eap);
975 else
976 ex_py3do(eap);
977# elif defined(FEAT_PYTHON)
978 ex_pydo(eap);
979# elif defined(FEAT_PYTHON3)
980 ex_py3do(eap);
981# endif
982}
983
984#endif
985
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000987 * ":checktime [buffer]"
988 */
989 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100990ex_checktime(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000991{
992 buf_T *buf;
993 int save_no_check_timestamps = no_check_timestamps;
994
995 no_check_timestamps = 0;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100996 if (eap->addr_count == 0) // default is all buffers
Bram Moolenaar071d4272004-06-13 20:20:40 +0000997 check_timestamps(FALSE);
998 else
999 {
1000 buf = buflist_findnr((int)eap->line2);
Bram Moolenaar217e1b82019-12-01 21:41:28 +01001001 if (buf != NULL) // cannot happen?
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 (void)buf_check_timestamp(buf, FALSE);
1003 }
1004 no_check_timestamps = save_no_check_timestamps;
1005}