blob: a41e0675b7d2ad7182e1f8c56550ded292fc82b9 [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 {
89 buf_T *buf2;
90 int count = 0;
91
Bram Moolenaar45d3b142013-11-09 03:31:51 +010092 if (flags & CCGD_ALLBUF)
Bram Moolenaar29323592016-07-24 22:04:11 +020093 FOR_ALL_BUFFERS(buf2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000094 if (bufIsChanged(buf2)
95 && (buf2->b_ffname != NULL
96# ifdef FEAT_BROWSE
Bram Moolenaare1004402020-10-24 20:49:43 +020097 || (cmdmod.cmod_flags & CMOD_BROWSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +000098# endif
99 ))
100 ++count;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200101 if (!bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100102 // Autocommand deleted buffer, oops! It's not changed now.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103 return FALSE;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100104
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105 dialog_changed(buf, count > 1);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100106
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200107 if (!bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100108 // Autocommand deleted buffer, oops! It's not changed now.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000109 return FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000110 return bufIsChanged(buf);
111 }
112#endif
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100113 if (flags & CCGD_EXCMD)
Bram Moolenaarf5be7cd2017-08-17 16:55:13 +0200114 no_write_message();
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100115 else
Bram Moolenaar7a760922018-02-19 23:10:02 +0100116 no_write_message_nobang(curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000117 return TRUE;
118 }
119 return FALSE;
120}
121
122#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
123
124#if defined(FEAT_BROWSE) || defined(PROTO)
125/*
126 * When wanting to write a file without a file name, ask the user for a name.
127 */
128 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100129browse_save_fname(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000130{
131 if (buf->b_fname == NULL)
132 {
133 char_u *fname;
134
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000135 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
136 NULL, NULL, NULL, NULL, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000137 if (fname != NULL)
138 {
139 if (setfname(buf, fname, NULL, TRUE) == OK)
140 buf->b_flags |= BF_NOTEDITED;
141 vim_free(fname);
142 }
143 }
144}
145#endif
146
147/*
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200148 * Ask the user what to do when abandoning a changed buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000149 * Must check 'write' option first!
150 */
151 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100152dialog_changed(
153 buf_T *buf,
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100154 int checkall) // may abandon all changed buffers
Bram Moolenaar071d4272004-06-13 20:20:40 +0000155{
Bram Moolenaard9462e32011-04-11 21:35:11 +0200156 char_u buff[DIALOG_MSG_SIZE];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157 int ret;
158 buf_T *buf2;
Bram Moolenaar8218f602012-04-25 17:32:18 +0200159 exarg_T ea;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000160
Bram Moolenaar3f9a1ff2017-08-21 22:06:02 +0200161 dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162 if (checkall)
163 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
164 else
165 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
166
Bram Moolenaar4ca41532019-05-09 21:48:37 +0200167 // Init ea pseudo-structure, this is needed for the check_overwrite()
168 // function.
Bram Moolenaara80faa82020-04-12 19:37:17 +0200169 CLEAR_FIELD(ea);
Bram Moolenaar8218f602012-04-25 17:32:18 +0200170
Bram Moolenaar071d4272004-06-13 20:20:40 +0000171 if (ret == VIM_YES)
172 {
173#ifdef FEAT_BROWSE
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100174 // May get file name, when there is none
Bram Moolenaar071d4272004-06-13 20:20:40 +0000175 browse_save_fname(buf);
176#endif
Bram Moolenaar8218f602012-04-25 17:32:18 +0200177 if (buf->b_fname != NULL && check_overwrite(&ea, buf,
178 buf->b_fname, buf->b_ffname, FALSE) == OK)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100179 // didn't hit Cancel
Bram Moolenaar071d4272004-06-13 20:20:40 +0000180 (void)buf_write_all(buf, FALSE);
181 }
182 else if (ret == VIM_NO)
183 {
Bram Moolenaarc024b462019-06-08 18:07:21 +0200184 unchanged(buf, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000185 }
186 else if (ret == VIM_ALL)
187 {
188 /*
189 * Write all modified files that can be written.
190 * Skip readonly buffers, these need to be confirmed
191 * individually.
192 */
Bram Moolenaar29323592016-07-24 22:04:11 +0200193 FOR_ALL_BUFFERS(buf2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000194 {
195 if (bufIsChanged(buf2)
196 && (buf2->b_ffname != NULL
197#ifdef FEAT_BROWSE
Bram Moolenaare1004402020-10-24 20:49:43 +0200198 || (cmdmod.cmod_flags & CMOD_BROWSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199#endif
200 )
201 && !buf2->b_p_ro)
202 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200203 bufref_T bufref;
204
205 set_bufref(&bufref, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000206#ifdef FEAT_BROWSE
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100207 // May get file name, when there is none
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208 browse_save_fname(buf2);
209#endif
Bram Moolenaar8218f602012-04-25 17:32:18 +0200210 if (buf2->b_fname != NULL && check_overwrite(&ea, buf2,
211 buf2->b_fname, buf2->b_ffname, FALSE) == OK)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100212 // didn't hit Cancel
Bram Moolenaar071d4272004-06-13 20:20:40 +0000213 (void)buf_write_all(buf2, FALSE);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100214
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100215 // an autocommand may have deleted the buffer
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200216 if (!bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000217 buf2 = firstbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000218 }
219 }
220 }
221 else if (ret == VIM_DISCARDALL)
222 {
223 /*
224 * mark all buffers as unchanged
225 */
Bram Moolenaar29323592016-07-24 22:04:11 +0200226 FOR_ALL_BUFFERS(buf2)
Bram Moolenaarc024b462019-06-08 18:07:21 +0200227 unchanged(buf2, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000228 }
229}
230#endif
231
232/*
233 * Return TRUE if the buffer "buf" can be abandoned, either by making it
234 * hidden, autowriting it or unloading it.
235 */
236 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100237can_abandon(buf_T *buf, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000238{
Bram Moolenaareb44a682017-08-03 22:44:55 +0200239 return ( buf_hide(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000240 || !bufIsChanged(buf)
241 || buf->b_nwindows > 1
242 || autowrite(buf, forceit) == OK
243 || forceit);
244}
245
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100246/*
247 * Add a buffer number to "bufnrs", unless it's already there.
248 */
249 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100250add_bufnum(int *bufnrs, int *bufnump, int nr)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100251{
252 int i;
253
254 for (i = 0; i < *bufnump; ++i)
255 if (bufnrs[i] == nr)
256 return;
257 bufnrs[*bufnump] = nr;
258 *bufnump = *bufnump + 1;
259}
260
Bram Moolenaar071d4272004-06-13 20:20:40 +0000261/*
262 * Return TRUE if any buffer was changed and cannot be abandoned.
263 * That changed buffer becomes the current buffer.
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100264 * When "unload" is TRUE the current buffer is unloaded instead of making it
Bram Moolenaar027387f2016-01-02 22:25:52 +0100265 * hidden. This is used for ":q!".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000266 */
267 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100268check_changed_any(
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100269 int hidden, // Only check hidden buffers
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100270 int unload)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000271{
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100272 int ret = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000273 buf_T *buf;
274 int save;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100275 int i;
276 int bufnum = 0;
277 int bufcount = 0;
278 int *bufnrs;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100279 tabpage_T *tp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000280 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000281
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100282 // Make a list of all buffers, with the most important ones first.
Bram Moolenaar29323592016-07-24 22:04:11 +0200283 FOR_ALL_BUFFERS(buf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100284 ++bufcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000285
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100286 if (bufcount == 0)
287 return FALSE;
288
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200289 bufnrs = ALLOC_MULT(int, bufcount);
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100290 if (bufnrs == NULL)
291 return FALSE;
292
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100293 // curbuf
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100294 bufnrs[bufnum++] = curbuf->b_fnum;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100295
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100296 // buffers in current tab
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100297 FOR_ALL_WINDOWS(wp)
298 if (wp->w_buffer != curbuf)
299 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
300
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100301 // buffers in other tabs
Bram Moolenaar29323592016-07-24 22:04:11 +0200302 FOR_ALL_TABPAGES(tp)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100303 if (tp != curtab)
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200304 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100305 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100306
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100307 // any other buffer
Bram Moolenaar29323592016-07-24 22:04:11 +0200308 FOR_ALL_BUFFERS(buf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100309 add_bufnum(bufnrs, &bufnum, buf->b_fnum);
310
311 for (i = 0; i < bufnum; ++i)
312 {
313 buf = buflist_findnr(bufnrs[i]);
314 if (buf == NULL)
315 continue;
316 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
317 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200318 bufref_T bufref;
319
320 set_bufref(&bufref, buf);
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100321#ifdef FEAT_TERMINAL
322 if (term_job_running(buf->b_term))
323 {
324 if (term_try_stop_job(buf) == FAIL)
325 break;
326 }
327 else
328#endif
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100329 // Try auto-writing the buffer. If this fails but the buffer no
330 // longer exists it's not changed, that's OK.
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100331 if (check_changed(buf, (p_awa ? CCGD_AW : 0)
332 | CCGD_MULTWIN
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200333 | CCGD_ALLBUF) && bufref_valid(&bufref))
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100334 break; // didn't save - still changes
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100335 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000336 }
337
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100338 if (i >= bufnum)
339 goto theend;
340
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100341 // Get here if "buf" cannot be abandoned.
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100342 ret = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000343 exiting = FALSE;
344#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
345 /*
346 * When ":confirm" used, don't give an error message.
347 */
Bram Moolenaare1004402020-10-24 20:49:43 +0200348 if (!(p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000349#endif
350 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100351 // There must be a wait_return for this message, do_buffer()
352 // may cause a redraw. But wait_return() is a no-op when vgetc()
353 // is busy (Quit used from window menu), then make sure we don't
354 // cause a scroll up.
Bram Moolenaar61660ea2006-04-07 21:40:07 +0000355 if (vgetc_busy > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000356 {
357 msg_row = cmdline_row;
358 msg_col = 0;
359 msg_didout = FALSE;
360 }
Bram Moolenaareb44a682017-08-03 22:44:55 +0200361 if (
362#ifdef FEAT_TERMINAL
363 term_job_running(buf->b_term)
Bram Moolenaard82a47d2022-01-05 20:24:39 +0000364 ? semsg(_(e_job_still_running_in_buffer_str), buf->b_fname)
Bram Moolenaareb44a682017-08-03 22:44:55 +0200365 :
366#endif
Bram Moolenaar1a992222021-12-31 17:25:48 +0000367 semsg(_(e_no_write_since_last_change_for_buffer_str),
Bram Moolenaare1704ba2012-10-03 18:25:00 +0200368 buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000369 {
370 save = no_wait_return;
371 no_wait_return = FALSE;
372 wait_return(FALSE);
373 no_wait_return = save;
374 }
375 }
376
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100377 // Try to find a window that contains the buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000378 if (buf != curbuf)
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100379 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000380 if (wp->w_buffer == buf)
381 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200382 bufref_T bufref;
383
384 set_bufref(&bufref, buf);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100385
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100386 goto_tabpage_win(tp, wp);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100387
Bram Moolenaarbdace832019-03-02 10:13:42 +0100388 // Paranoia: did autocmd wipe out the buffer with changes?
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200389 if (!bufref_valid(&bufref))
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100390 goto theend;
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100391 goto buf_found;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000392 }
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100393buf_found:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000394
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100395 // Open the changed buffer in the current window.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000396 if (buf != curbuf)
Bram Moolenaar027387f2016-01-02 22:25:52 +0100397 set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000398
Bram Moolenaar970a1b82012-03-23 18:39:18 +0100399theend:
400 vim_free(bufnrs);
401 return ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000402}
403
404/*
405 * return FAIL if there is no file name, OK if there is one
406 * give error message for FAIL
407 */
408 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100409check_fname(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410{
411 if (curbuf->b_ffname == NULL)
412 {
Bram Moolenaare29a27f2021-07-20 21:07:36 +0200413 emsg(_(e_no_file_name));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000414 return FAIL;
415 }
416 return OK;
417}
418
419/*
420 * flush the contents of a buffer, unless it has no file name
421 *
422 * return FAIL for failure, OK otherwise
423 */
424 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100425buf_write_all(buf_T *buf, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000426{
427 int retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000428 buf_T *old_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000429
430 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
431 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
432 FALSE, forceit, TRUE, FALSE));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000433 if (curbuf != old_curbuf)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +0000434 {
Bram Moolenaar8820b482017-03-16 17:23:31 +0100435 msg_source(HL_ATTR(HLF_W));
Bram Moolenaar32526b32019-01-19 17:43:09 +0100436 msg(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +0000437 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000438 return retval;
439}
440
441/*
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200442 * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000443 */
444 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100445ex_listdo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446{
447 int i;
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000448 win_T *wp;
449 tabpage_T *tp;
Bram Moolenaare25bb902015-02-27 20:33:37 +0100450 buf_T *buf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000451 int next_fnum = 0;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100452#if defined(FEAT_SYN_HL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000453 char_u *save_ei = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000454#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000455 char_u *p_shm_save;
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200456#ifdef FEAT_QUICKFIX
Bram Moolenaared84b762015-09-09 22:35:29 +0200457 int qf_size = 0;
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200458 int qf_idx;
459#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000460
Bram Moolenaar0106e3d2016-02-23 18:55:43 +0100461#ifndef FEAT_QUICKFIX
462 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo ||
463 eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
464 {
465 ex_ni(eap);
466 return;
467 }
468#endif
469
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100470#if defined(FEAT_SYN_HL)
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000471 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200472 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100473 // Don't do syntax HL autocommands. Skipping the syntax file is a
474 // great speed improvement.
Bram Moolenaardcaf10e2005-01-21 11:55:25 +0000475 save_ei = au_event_disable(",Syntax");
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200476
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200477 FOR_ALL_BUFFERS(buf)
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200478 buf->b_flags &= ~BF_SYN_SET;
479 buf = curbuf;
480 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000481#endif
Bram Moolenaar6b1ee342014-08-06 18:17:11 +0200482#ifdef FEAT_CLIPBOARD
483 start_global_changes();
484#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000485
486 if (eap->cmdidx == CMD_windo
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000487 || eap->cmdidx == CMD_tabdo
Bram Moolenaareb44a682017-08-03 22:44:55 +0200488 || buf_hide(curbuf)
Bram Moolenaar45d3b142013-11-09 03:31:51 +0100489 || !check_changed(curbuf, CCGD_AW
490 | (eap->forceit ? CCGD_FORCEIT : 0)
491 | CCGD_EXCMD))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493 i = 0;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100494 // start at the eap->line1 argument/window/buffer
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000495 wp = firstwin;
496 tp = first_tabpage;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100497 switch (eap->cmdidx)
498 {
Bram Moolenaara162bc52015-01-07 16:54:21 +0100499 case CMD_windo:
500 for ( ; wp != NULL && i + 1 < eap->line1; wp = wp->w_next)
501 i++;
502 break;
503 case CMD_tabdo:
504 for( ; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next)
505 i++;
506 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100507 case CMD_argdo:
508 i = eap->line1 - 1;
509 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100510 default:
511 break;
512 }
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100513 // set pcmark now
Bram Moolenaar071d4272004-06-13 20:20:40 +0000514 if (eap->cmdidx == CMD_bufdo)
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200515 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100516 // Advance to the first listed buffer after "eap->line1".
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200517 for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1
Bram Moolenaare25bb902015-02-27 20:33:37 +0100518 || !buf->b_p_bl); buf = buf->b_next)
519 if (buf->b_fnum > eap->line2)
520 {
521 buf = NULL;
522 break;
523 }
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200524 if (buf != NULL)
Bram Moolenaare25bb902015-02-27 20:33:37 +0100525 goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200526 }
527#ifdef FEAT_QUICKFIX
528 else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
529 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
530 {
Bram Moolenaar25190db2019-05-04 15:05:28 +0200531 qf_size = qf_get_valid_size(eap);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200532 if (qf_size <= 0 || eap->line1 > qf_size)
533 buf = NULL;
534 else
535 {
536 ex_cc(eap);
537
538 buf = curbuf;
539 i = eap->line1 - 1;
540 if (eap->addr_count <= 0)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100541 // default is all the quickfix/location list entries
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200542 eap->line2 = qf_size;
543 }
544 }
545#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000546 else
547 setpcmark();
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100548 listcmd_busy = TRUE; // avoids setting pcmark below
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549
Bram Moolenaare25bb902015-02-27 20:33:37 +0100550 while (!got_int && buf != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000551 {
552 if (eap->cmdidx == CMD_argdo)
553 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100554 // go to argument "i"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000555 if (i == ARGCOUNT)
556 break;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100557 // Don't call do_argfile() when already there, it will try
558 // reloading the file.
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000559 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000560 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100561 // Clear 'shm' to avoid that the file message overwrites
562 // any output from the command.
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000563 p_shm_save = vim_strsave(p_shm);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100564 set_option_value_give_err((char_u *)"shm",
565 0L, (char_u *)"", 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566 do_argfile(eap, i);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100567 set_option_value_give_err((char_u *)"shm",
568 0L, p_shm_save, 0);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000569 vim_free(p_shm_save);
570 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000571 if (curwin->w_arg_idx != i)
572 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000573 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000574 else if (eap->cmdidx == CMD_windo)
575 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100576 // go to window "wp"
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000577 if (!win_valid(wp))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000578 break;
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000579 win_goto(wp);
Bram Moolenaar41423242007-05-03 20:11:13 +0000580 if (curwin != wp)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100581 break; // something must be wrong
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000582 wp = curwin->w_next;
583 }
584 else if (eap->cmdidx == CMD_tabdo)
585 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100586 // go to window "tp"
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000587 if (!valid_tabpage(tp))
588 break;
Bram Moolenaar49e649f2013-05-06 04:50:35 +0200589 goto_tabpage_tp(tp, TRUE, TRUE);
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000590 tp = tp->tp_next;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000591 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000592 else if (eap->cmdidx == CMD_bufdo)
593 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100594 // Remember the number of the next listed buffer, in case
595 // ":bwipe" is used or autocommands do something strange.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000596 next_fnum = -1;
597 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
598 if (buf->b_p_bl)
599 {
600 next_fnum = buf->b_fnum;
601 break;
602 }
603 }
604
Bram Moolenaara162bc52015-01-07 16:54:21 +0100605 ++i;
606
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100607 // execute the command
Bram Moolenaar071d4272004-06-13 20:20:40 +0000608 do_cmdline(eap->arg, eap->getline, eap->cookie,
609 DOCMD_VERBOSE + DOCMD_NOWAIT);
610
611 if (eap->cmdidx == CMD_bufdo)
612 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100613 // Done?
Bram Moolenaara162bc52015-01-07 16:54:21 +0100614 if (next_fnum < 0 || next_fnum > eap->line2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000615 break;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100616 // Check if the buffer still exists.
Bram Moolenaar29323592016-07-24 22:04:11 +0200617 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000618 if (buf->b_fnum == next_fnum)
619 break;
620 if (buf == NULL)
621 break;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000622
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100623 // Go to the next buffer. Clear 'shm' to avoid that the file
624 // message overwrites any output from the command.
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000625 p_shm_save = vim_strsave(p_shm);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100626 set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000627 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100628 set_option_value_give_err((char_u *)"shm", 0L, p_shm_save, 0);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000629 vim_free(p_shm_save);
630
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100631 // If autocommands took us elsewhere, quit here.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000632 if (curbuf->b_fnum != next_fnum)
633 break;
634 }
635
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200636#ifdef FEAT_QUICKFIX
637 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
638 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
639 {
640 if (i >= qf_size || i >= eap->line2)
641 break;
642
643 qf_idx = qf_get_cur_idx(eap);
644
Bram Moolenaar14798ab2020-05-28 21:30:11 +0200645 // Clear 'shm' to avoid that the file message overwrites
646 // any output from the command.
647 p_shm_save = vim_strsave(p_shm);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100648 set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200649 ex_cnext(eap);
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100650 set_option_value_give_err((char_u *)"shm", 0L, p_shm_save, 0);
Bram Moolenaar14798ab2020-05-28 21:30:11 +0200651 vim_free(p_shm_save);
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200652
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100653 // If jumping to the next quickfix entry fails, quit here
Bram Moolenaaraa23b372015-09-08 18:46:31 +0200654 if (qf_get_cur_idx(eap) == qf_idx)
655 break;
656 }
657#endif
658
Bram Moolenaar071d4272004-06-13 20:20:40 +0000659 if (eap->cmdidx == CMD_windo)
660 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100661 validate_cursor(); // cursor may have moved
Bram Moolenaar8a3bb562018-03-04 20:14:14 +0100662
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100663 // required when 'scrollbind' has been set
Bram Moolenaar071d4272004-06-13 20:20:40 +0000664 if (curwin->w_p_scb)
665 do_check_scrollbind(TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000666 }
Bram Moolenaara162bc52015-01-07 16:54:21 +0100667
Bram Moolenaara162bc52015-01-07 16:54:21 +0100668 if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo)
669 if (i+1 > eap->line2)
670 break;
Bram Moolenaara162bc52015-01-07 16:54:21 +0100671 if (eap->cmdidx == CMD_argdo && i >= eap->line2)
672 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000673 }
674 listcmd_busy = FALSE;
675 }
676
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100677#if defined(FEAT_SYN_HL)
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000678 if (save_ei != NULL)
679 {
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200680 buf_T *bnext;
681 aco_save_T aco;
682
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000683 au_event_restore(save_ei);
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200684
685 for (buf = firstbuf; buf != NULL; buf = bnext)
686 {
687 bnext = buf->b_next;
688 if (buf->b_nwindows > 0 && (buf->b_flags & BF_SYN_SET))
689 {
690 buf->b_flags &= ~BF_SYN_SET;
691
692 // buffer was opened while Syntax autocommands were disabled,
693 // need to trigger them now.
694 if (buf == curbuf)
695 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000696 curbuf->b_fname, TRUE, curbuf);
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200697 else
698 {
699 aucmd_prepbuf(&aco, buf);
700 apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
701 buf->b_fname, TRUE, buf);
702 aucmd_restbuf(&aco);
703 }
704
705 // start over, in case autocommands messed things up.
706 bnext = firstbuf;
707 }
708 }
Bram Moolenaar6ac54292005-02-02 23:07:25 +0000709 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710#endif
Bram Moolenaar6b1ee342014-08-06 18:17:11 +0200711#ifdef FEAT_CLIPBOARD
712 end_global_changes();
713#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000714}
715
Bram Moolenaar071d4272004-06-13 20:20:40 +0000716#ifdef FEAT_EVAL
717/*
718 * ":compiler[!] {name}"
719 */
720 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100721ex_compiler(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000722{
723 char_u *buf;
724 char_u *old_cur_comp = NULL;
725 char_u *p;
726
727 if (*eap->arg == NUL)
728 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100729 // List all compiler scripts.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000730 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100731 // ) keep the indenter happy...
Bram Moolenaar071d4272004-06-13 20:20:40 +0000732 }
733 else
734 {
Bram Moolenaar964b3742019-05-24 18:54:09 +0200735 buf = alloc(STRLEN(eap->arg) + 14);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000736 if (buf != NULL)
737 {
738 if (eap->forceit)
739 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100740 // ":compiler! {name}" sets global options
Bram Moolenaar071d4272004-06-13 20:20:40 +0000741 do_cmdline_cmd((char_u *)
742 "command -nargs=* CompilerSet set <args>");
743 }
744 else
745 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100746 // ":compiler! {name}" sets local options.
747 // To remain backwards compatible "current_compiler" is always
748 // used. A user's compiler plugin may set it, the distributed
749 // plugin will then skip the settings. Afterwards set
750 // "b:current_compiler" and restore "current_compiler".
751 // Explicitly prepend "g:" to make it work in a function.
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100752 old_cur_comp = get_var_value((char_u *)"g:current_compiler");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000753 if (old_cur_comp != NULL)
754 old_cur_comp = vim_strsave(old_cur_comp);
755 do_cmdline_cmd((char_u *)
Bram Moolenaar58ef8a32021-11-12 11:25:11 +0000756 "command -nargs=* -keepscript CompilerSet setlocal <args>");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000757 }
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100758 do_unlet((char_u *)"g:current_compiler", TRUE);
Bram Moolenaar2ce06f62005-01-31 19:19:04 +0000759 do_unlet((char_u *)"b:current_compiler", TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760
761 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
Bram Moolenaar7f8989d2016-03-12 22:11:39 +0100762 if (source_runtime(buf, DIP_ALL) == FAIL)
Bram Moolenaara6f79292022-01-04 21:30:47 +0000763 semsg(_(e_compiler_not_supported_str), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764 vim_free(buf);
765
766 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
767
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100768 // Set "b:current_compiler" from "current_compiler".
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100769 p = get_var_value((char_u *)"g:current_compiler");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000770 if (p != NULL)
771 set_internal_string_var((char_u *)"b:current_compiler", p);
772
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100773 // Restore "current_compiler" for ":compiler {name}".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774 if (!eap->forceit)
775 {
776 if (old_cur_comp != NULL)
777 {
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100778 set_internal_string_var((char_u *)"g:current_compiler",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779 old_cur_comp);
780 vim_free(old_cur_comp);
781 }
782 else
Bram Moolenaar3d63e3f2010-01-19 16:13:50 +0100783 do_unlet((char_u *)"g:current_compiler", TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784 }
785 }
786 }
787}
788#endif
789
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100790#if defined(FEAT_PYTHON3) || defined(FEAT_PYTHON) || defined(PROTO)
791
792# if (defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO)
793/*
794 * Detect Python 3 or 2, and initialize 'pyxversion'.
795 */
796 void
797init_pyxversion(void)
798{
799 if (p_pyx == 0)
800 {
801 if (python3_enabled(FALSE))
802 p_pyx = 3;
803 else if (python_enabled(FALSE))
804 p_pyx = 2;
805 }
806}
807# endif
808
809/*
810 * Does a file contain one of the following strings at the beginning of any
811 * line?
812 * "#!(any string)python2" => returns 2
813 * "#!(any string)python3" => returns 3
814 * "# requires python 2.x" => returns 2
815 * "# requires python 3.x" => returns 3
816 * otherwise return 0.
817 */
818 static int
819requires_py_version(char_u *filename)
820{
821 FILE *file;
822 int requires_py_version = 0;
823 int i, lines;
824
825 lines = (int)p_mls;
826 if (lines < 0)
827 lines = 5;
828
829 file = mch_fopen((char *)filename, "r");
830 if (file != NULL)
831 {
832 for (i = 0; i < lines; i++)
833 {
834 if (vim_fgets(IObuff, IOSIZE, file))
835 break;
836 if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!')
837 {
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100838 // Check shebang.
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100839 if (strstr((char *)IObuff + 2, "python2") != NULL)
840 {
841 requires_py_version = 2;
842 break;
843 }
844 if (strstr((char *)IObuff + 2, "python3") != NULL)
845 {
846 requires_py_version = 3;
847 break;
848 }
849 }
850 IObuff[21] = '\0';
851 if (STRCMP("# requires python 2.x", IObuff) == 0)
852 {
853 requires_py_version = 2;
854 break;
855 }
856 if (STRCMP("# requires python 3.x", IObuff) == 0)
857 {
858 requires_py_version = 3;
859 break;
860 }
861 }
862 fclose(file);
863 }
864 return requires_py_version;
865}
866
867
868/*
869 * Source a python file using the requested python version.
870 */
871 static void
872source_pyx_file(exarg_T *eap, char_u *fname)
873{
874 exarg_T ex;
875 int v = requires_py_version(fname);
876
877# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
878 init_pyxversion();
879# endif
880 if (v == 0)
881 {
882# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100883 // user didn't choose a preference, 'pyx' is used
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100884 v = p_pyx;
885# elif defined(FEAT_PYTHON)
886 v = 2;
887# elif defined(FEAT_PYTHON3)
888 v = 3;
889# endif
890 }
891
892 /*
893 * now source, if required python version is not supported show
894 * unobtrusive message.
895 */
896 if (eap == NULL)
Bram Moolenaara80faa82020-04-12 19:37:17 +0200897 CLEAR_FIELD(ex);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100898 else
899 ex = *eap;
900 ex.arg = fname;
901 ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3");
902
903 if (v == 2)
904 {
905# ifdef FEAT_PYTHON
906 ex_pyfile(&ex);
907# else
908 vim_snprintf((char *)IObuff, IOSIZE,
909 _("W20: Required python version 2.x not supported, ignoring file: %s"),
910 fname);
Bram Moolenaar32526b32019-01-19 17:43:09 +0100911 msg((char *)IObuff);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100912# endif
913 return;
914 }
915 else
916 {
917# ifdef FEAT_PYTHON3
918 ex_py3file(&ex);
919# else
920 vim_snprintf((char *)IObuff, IOSIZE,
921 _("W21: Required python version 3.x not supported, ignoring file: %s"),
922 fname);
Bram Moolenaar32526b32019-01-19 17:43:09 +0100923 msg((char *)IObuff);
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +0100924# endif
925 return;
926 }
927}
928
929/*
930 * ":pyxfile {fname}"
931 */
932 void
933ex_pyxfile(exarg_T *eap)
934{
935 source_pyx_file(eap, eap->arg);
936}
937
938/*
939 * ":pyx"
940 */
941 void
942ex_pyx(exarg_T *eap)
943{
944# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
945 init_pyxversion();
946 if (p_pyx == 2)
947 ex_python(eap);
948 else
949 ex_py3(eap);
950# elif defined(FEAT_PYTHON)
951 ex_python(eap);
952# elif defined(FEAT_PYTHON3)
953 ex_py3(eap);
954# endif
955}
956
957/*
958 * ":pyxdo"
959 */
960 void
961ex_pyxdo(exarg_T *eap)
962{
963# if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
964 init_pyxversion();
965 if (p_pyx == 2)
966 ex_pydo(eap);
967 else
968 ex_py3do(eap);
969# elif defined(FEAT_PYTHON)
970 ex_pydo(eap);
971# elif defined(FEAT_PYTHON3)
972 ex_py3do(eap);
973# endif
974}
975
976#endif
977
Bram Moolenaar071d4272004-06-13 20:20:40 +0000978/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000979 * ":checktime [buffer]"
980 */
981 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100982ex_checktime(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000983{
984 buf_T *buf;
985 int save_no_check_timestamps = no_check_timestamps;
986
987 no_check_timestamps = 0;
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100988 if (eap->addr_count == 0) // default is all buffers
Bram Moolenaar071d4272004-06-13 20:20:40 +0000989 check_timestamps(FALSE);
990 else
991 {
992 buf = buflist_findnr((int)eap->line2);
Bram Moolenaar217e1b82019-12-01 21:41:28 +0100993 if (buf != NULL) // cannot happen?
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994 (void)buf_check_timestamp(buf, FALSE);
995 }
996 no_check_timestamps = save_no_check_timestamps;
997}