xref: /vim-8.2.3635/src/ex_cmds2.c (revision 58ef8a31)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
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 
14 #include "vim.h"
15 #include "version.h"
16 
17 /*
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
autowrite(buf_T * buf,int forceit)24 autowrite(buf_T *buf, int forceit)
25 {
26     int		r;
27     bufref_T	bufref;
28 
29     if (!(p_aw || p_awa) || !p_write
30 #ifdef FEAT_QUICKFIX
31 	    // never autowrite a "nofile" or "nowrite" buffer
32 	    || bt_dontwrite(buf)
33 #endif
34 	    || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
35 	return FAIL;
36     set_bufref(&bufref, buf);
37     r = buf_write_all(buf, forceit);
38 
39     // Writing may succeed but the buffer still changed, e.g., when there is a
40     // conversion error.  We do want to return FAIL then.
41     if (bufref_valid(&bufref) && bufIsChanged(buf))
42 	r = FAIL;
43     return r;
44 }
45 
46 /*
47  * Flush all buffers, except the ones that are readonly or are never written.
48  */
49     void
autowrite_all(void)50 autowrite_all(void)
51 {
52     buf_T	*buf;
53 
54     if (!(p_aw || p_awa) || !p_write)
55 	return;
56     FOR_ALL_BUFFERS(buf)
57 	if (bufIsChanged(buf) && !buf->b_p_ro && !bt_dontwrite(buf))
58 	{
59 	    bufref_T	bufref;
60 
61 	    set_bufref(&bufref, buf);
62 
63 	    (void)buf_write_all(buf, FALSE);
64 
65 	    // an autocommand may have deleted the buffer
66 	    if (!bufref_valid(&bufref))
67 		buf = firstbuf;
68 	}
69 }
70 
71 /*
72  * Return TRUE if buffer was changed and cannot be abandoned.
73  * For flags use the CCGD_ values.
74  */
75     int
check_changed(buf_T * buf,int flags)76 check_changed(buf_T *buf, int flags)
77 {
78     int		forceit = (flags & CCGD_FORCEIT);
79     bufref_T	bufref;
80 
81     set_bufref(&bufref, buf);
82 
83     if (       !forceit
84 	    && bufIsChanged(buf)
85 	    && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1)
86 	    && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL))
87     {
88 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
89 	if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
90 	{
91 	    buf_T	*buf2;
92 	    int		count = 0;
93 
94 	    if (flags & CCGD_ALLBUF)
95 		FOR_ALL_BUFFERS(buf2)
96 		    if (bufIsChanged(buf2)
97 				     && (buf2->b_ffname != NULL
98 # ifdef FEAT_BROWSE
99 					 || (cmdmod.cmod_flags & CMOD_BROWSE)
100 # endif
101 					))
102 			++count;
103 	    if (!bufref_valid(&bufref))
104 		// Autocommand deleted buffer, oops!  It's not changed now.
105 		return FALSE;
106 
107 	    dialog_changed(buf, count > 1);
108 
109 	    if (!bufref_valid(&bufref))
110 		// Autocommand deleted buffer, oops!  It's not changed now.
111 		return FALSE;
112 	    return bufIsChanged(buf);
113 	}
114 #endif
115 	if (flags & CCGD_EXCMD)
116 	    no_write_message();
117 	else
118 	    no_write_message_nobang(curbuf);
119 	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
browse_save_fname(buf_T * buf)131 browse_save_fname(buf_T *buf)
132 {
133     if (buf->b_fname == NULL)
134     {
135 	char_u *fname;
136 
137 	fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
138 						 NULL, NULL, NULL, NULL, buf);
139 	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 /*
150  * Ask the user what to do when abandoning a changed buffer.
151  * Must check 'write' option first!
152  */
153     void
dialog_changed(buf_T * buf,int checkall)154 dialog_changed(
155     buf_T	*buf,
156     int		checkall)	// may abandon all changed buffers
157 {
158     char_u	buff[DIALOG_MSG_SIZE];
159     int		ret;
160     buf_T	*buf2;
161     exarg_T     ea;
162 
163     dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname);
164     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 
169     // Init ea pseudo-structure, this is needed for the check_overwrite()
170     // function.
171     CLEAR_FIELD(ea);
172 
173     if (ret == VIM_YES)
174     {
175 #ifdef FEAT_BROWSE
176 	// May get file name, when there is none
177 	browse_save_fname(buf);
178 #endif
179 	if (buf->b_fname != NULL && check_overwrite(&ea, buf,
180 				    buf->b_fname, buf->b_ffname, FALSE) == OK)
181 	    // didn't hit Cancel
182 	    (void)buf_write_all(buf, FALSE);
183     }
184     else if (ret == VIM_NO)
185     {
186 	unchanged(buf, TRUE, FALSE);
187     }
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 	 */
195 	FOR_ALL_BUFFERS(buf2)
196 	{
197 	    if (bufIsChanged(buf2)
198 		    && (buf2->b_ffname != NULL
199 #ifdef FEAT_BROWSE
200 			|| (cmdmod.cmod_flags & CMOD_BROWSE)
201 #endif
202 			)
203 		    && !buf2->b_p_ro)
204 	    {
205 		bufref_T bufref;
206 
207 		set_bufref(&bufref, buf2);
208 #ifdef FEAT_BROWSE
209 		// May get file name, when there is none
210 		browse_save_fname(buf2);
211 #endif
212 		if (buf2->b_fname != NULL && check_overwrite(&ea, buf2,
213 				  buf2->b_fname, buf2->b_ffname, FALSE) == OK)
214 		    // didn't hit Cancel
215 		    (void)buf_write_all(buf2, FALSE);
216 
217 		// an autocommand may have deleted the buffer
218 		if (!bufref_valid(&bufref))
219 		    buf2 = firstbuf;
220 	    }
221 	}
222     }
223     else if (ret == VIM_DISCARDALL)
224     {
225 	/*
226 	 * mark all buffers as unchanged
227 	 */
228 	FOR_ALL_BUFFERS(buf2)
229 	    unchanged(buf2, TRUE, FALSE);
230     }
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
can_abandon(buf_T * buf,int forceit)239 can_abandon(buf_T *buf, int forceit)
240 {
241     return (	   buf_hide(buf)
242 		|| !bufIsChanged(buf)
243 		|| buf->b_nwindows > 1
244 		|| autowrite(buf, forceit) == OK
245 		|| forceit);
246 }
247 
248 /*
249  * Add a buffer number to "bufnrs", unless it's already there.
250  */
251     static void
add_bufnum(int * bufnrs,int * bufnump,int nr)252 add_bufnum(int *bufnrs, int *bufnump, int nr)
253 {
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 
263 /*
264  * Return TRUE if any buffer was changed and cannot be abandoned.
265  * That changed buffer becomes the current buffer.
266  * When "unload" is TRUE the current buffer is unloaded instead of making it
267  * hidden.  This is used for ":q!".
268  */
269     int
check_changed_any(int hidden,int unload)270 check_changed_any(
271     int		hidden,		// Only check hidden buffers
272     int		unload)
273 {
274     int		ret = FALSE;
275     buf_T	*buf;
276     int		save;
277     int		i;
278     int		bufnum = 0;
279     int		bufcount = 0;
280     int		*bufnrs;
281     tabpage_T   *tp;
282     win_T	*wp;
283 
284     // Make a list of all buffers, with the most important ones first.
285     FOR_ALL_BUFFERS(buf)
286 	++bufcount;
287 
288     if (bufcount == 0)
289 	return FALSE;
290 
291     bufnrs = ALLOC_MULT(int, bufcount);
292     if (bufnrs == NULL)
293 	return FALSE;
294 
295     // curbuf
296     bufnrs[bufnum++] = curbuf->b_fnum;
297 
298     // buffers in current tab
299     FOR_ALL_WINDOWS(wp)
300 	if (wp->w_buffer != curbuf)
301 	    add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
302 
303     // buffers in other tabs
304     FOR_ALL_TABPAGES(tp)
305 	if (tp != curtab)
306 	    FOR_ALL_WINDOWS_IN_TAB(tp, wp)
307 		add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
308 
309     // any other buffer
310     FOR_ALL_BUFFERS(buf)
311 	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 	{
320 	    bufref_T bufref;
321 
322 	    set_bufref(&bufref, buf);
323 #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
331 	    // Try auto-writing the buffer.  If this fails but the buffer no
332 	    // longer exists it's not changed, that's OK.
333 	    if (check_changed(buf, (p_awa ? CCGD_AW : 0)
334 				 | CCGD_MULTWIN
335 				 | CCGD_ALLBUF) && bufref_valid(&bufref))
336 		break;	    // didn't save - still changes
337 	}
338     }
339 
340     if (i >= bufnum)
341 	goto theend;
342 
343     // Get here if "buf" cannot be abandoned.
344     ret = TRUE;
345     exiting = FALSE;
346 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
347     /*
348      * When ":confirm" used, don't give an error message.
349      */
350     if (!(p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)))
351 #endif
352     {
353 	// 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.
357 	if (vgetc_busy > 0)
358 	{
359 	    msg_row = cmdline_row;
360 	    msg_col = 0;
361 	    msg_didout = FALSE;
362 	}
363 	if (
364 #ifdef FEAT_TERMINAL
365 		term_job_running(buf->b_term)
366 		    ? semsg(_("E947: Job still running in buffer \"%s\""),
367 								  buf->b_fname)
368 		    :
369 #endif
370 		semsg(_("E162: No write since last change for buffer \"%s\""),
371 		    buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
372 	{
373 	    save = no_wait_return;
374 	    no_wait_return = FALSE;
375 	    wait_return(FALSE);
376 	    no_wait_return = save;
377 	}
378     }
379 
380     // Try to find a window that contains the buffer.
381     if (buf != curbuf)
382 	FOR_ALL_TAB_WINDOWS(tp, wp)
383 	    if (wp->w_buffer == buf)
384 	    {
385 		bufref_T bufref;
386 
387 		set_bufref(&bufref, buf);
388 
389 		goto_tabpage_win(tp, wp);
390 
391 		// Paranoia: did autocmd wipe out the buffer with changes?
392 		if (!bufref_valid(&bufref))
393 		    goto theend;
394 		goto buf_found;
395 	    }
396 buf_found:
397 
398     // Open the changed buffer in the current window.
399     if (buf != curbuf)
400 	set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
401 
402 theend:
403     vim_free(bufnrs);
404     return ret;
405 }
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
check_fname(void)412 check_fname(void)
413 {
414     if (curbuf->b_ffname == NULL)
415     {
416 	emsg(_(e_no_file_name));
417 	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
buf_write_all(buf_T * buf,int forceit)428 buf_write_all(buf_T *buf, int forceit)
429 {
430     int	    retval;
431     buf_T	*old_curbuf = curbuf;
432 
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));
436     if (curbuf != old_curbuf)
437     {
438 	msg_source(HL_ATTR(HLF_W));
439 	msg(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
440     }
441     return retval;
442 }
443 
444 /*
445  * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo"
446  */
447     void
ex_listdo(exarg_T * eap)448 ex_listdo(exarg_T *eap)
449 {
450     int		i;
451     win_T	*wp;
452     tabpage_T	*tp;
453     buf_T	*buf = curbuf;
454     int		next_fnum = 0;
455 #if defined(FEAT_SYN_HL)
456     char_u	*save_ei = NULL;
457 #endif
458     char_u	*p_shm_save;
459 #ifdef FEAT_QUICKFIX
460     int		qf_size = 0;
461     int		qf_idx;
462 #endif
463 
464 #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 
473 #if defined(FEAT_SYN_HL)
474     if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
475     {
476 	// Don't do syntax HL autocommands.  Skipping the syntax file is a
477 	// great speed improvement.
478 	save_ei = au_event_disable(",Syntax");
479 
480 	FOR_ALL_BUFFERS(buf)
481 	    buf->b_flags &= ~BF_SYN_SET;
482 	buf = curbuf;
483     }
484 #endif
485 #ifdef FEAT_CLIPBOARD
486     start_global_changes();
487 #endif
488 
489     if (eap->cmdidx == CMD_windo
490 	    || eap->cmdidx == CMD_tabdo
491 	    || buf_hide(curbuf)
492 	    || !check_changed(curbuf, CCGD_AW
493 				    | (eap->forceit ? CCGD_FORCEIT : 0)
494 				    | CCGD_EXCMD))
495     {
496 	i = 0;
497 	// start at the eap->line1 argument/window/buffer
498 	wp = firstwin;
499 	tp = first_tabpage;
500 	switch (eap->cmdidx)
501 	{
502 	    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;
510 	    case CMD_argdo:
511 		i = eap->line1 - 1;
512 		break;
513 	    default:
514 		break;
515 	}
516 	// set pcmark now
517 	if (eap->cmdidx == CMD_bufdo)
518 	{
519 	    // Advance to the first listed buffer after "eap->line1".
520 	    for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1
521 					  || !buf->b_p_bl); buf = buf->b_next)
522 		if (buf->b_fnum > eap->line2)
523 		{
524 		    buf = NULL;
525 		    break;
526 		}
527 	    if (buf != NULL)
528 		goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum);
529 	}
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 	{
534 	    qf_size = qf_get_valid_size(eap);
535 	    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)
544 		    // default is all the quickfix/location list entries
545 		    eap->line2 = qf_size;
546 	    }
547 	}
548 #endif
549 	else
550 	    setpcmark();
551 	listcmd_busy = TRUE;	    // avoids setting pcmark below
552 
553 	while (!got_int && buf != NULL)
554 	{
555 	    if (eap->cmdidx == CMD_argdo)
556 	    {
557 		// go to argument "i"
558 		if (i == ARGCOUNT)
559 		    break;
560 		// Don't call do_argfile() when already there, it will try
561 		// reloading the file.
562 		if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
563 		{
564 		    // Clear 'shm' to avoid that the file message overwrites
565 		    // any output from the command.
566 		    p_shm_save = vim_strsave(p_shm);
567 		    set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
568 		    do_argfile(eap, i);
569 		    set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
570 		    vim_free(p_shm_save);
571 		}
572 		if (curwin->w_arg_idx != i)
573 		    break;
574 	    }
575 	    else if (eap->cmdidx == CMD_windo)
576 	    {
577 		// go to window "wp"
578 		if (!win_valid(wp))
579 		    break;
580 		win_goto(wp);
581 		if (curwin != wp)
582 		    break;  // something must be wrong
583 		wp = curwin->w_next;
584 	    }
585 	    else if (eap->cmdidx == CMD_tabdo)
586 	    {
587 		// go to window "tp"
588 		if (!valid_tabpage(tp))
589 		    break;
590 		goto_tabpage_tp(tp, TRUE, TRUE);
591 		tp = tp->tp_next;
592 	    }
593 	    else if (eap->cmdidx == CMD_bufdo)
594 	    {
595 		// Remember the number of the next listed buffer, in case
596 		// ":bwipe" is used or autocommands do something strange.
597 		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 
606 	    ++i;
607 
608 	    // execute the command
609 	    do_cmdline(eap->arg, eap->getline, eap->cookie,
610 						DOCMD_VERBOSE + DOCMD_NOWAIT);
611 
612 	    if (eap->cmdidx == CMD_bufdo)
613 	    {
614 		// Done?
615 		if (next_fnum < 0 || next_fnum > eap->line2)
616 		    break;
617 		// Check if the buffer still exists.
618 		FOR_ALL_BUFFERS(buf)
619 		    if (buf->b_fnum == next_fnum)
620 			break;
621 		if (buf == NULL)
622 		    break;
623 
624 		// Go to the next buffer.  Clear 'shm' to avoid that the file
625 		// message overwrites any output from the command.
626 		p_shm_save = vim_strsave(p_shm);
627 		set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
628 		goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
629 		set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
630 		vim_free(p_shm_save);
631 
632 		// If autocommands took us elsewhere, quit here.
633 		if (curbuf->b_fnum != next_fnum)
634 		    break;
635 	    }
636 
637 #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 
646 		// 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);
650 		ex_cnext(eap);
651 		set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
652 		vim_free(p_shm_save);
653 
654 		// If jumping to the next quickfix entry fails, quit here
655 		if (qf_get_cur_idx(eap) == qf_idx)
656 		    break;
657 	    }
658 #endif
659 
660 	    if (eap->cmdidx == CMD_windo)
661 	    {
662 		validate_cursor();	// cursor may have moved
663 
664 		// required when 'scrollbind' has been set
665 		if (curwin->w_p_scb)
666 		    do_check_scrollbind(TRUE);
667 	    }
668 
669 	    if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo)
670 		if (i+1 > eap->line2)
671 		    break;
672 	    if (eap->cmdidx == CMD_argdo && i >= eap->line2)
673 		break;
674 	}
675 	listcmd_busy = FALSE;
676     }
677 
678 #if defined(FEAT_SYN_HL)
679     if (save_ei != NULL)
680     {
681 	buf_T		*bnext;
682 	aco_save_T	aco;
683 
684 	au_event_restore(save_ei);
685 
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,
697 					       curbuf->b_fname, TRUE, curbuf);
698 		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 	}
710     }
711 #endif
712 #ifdef FEAT_CLIPBOARD
713     end_global_changes();
714 #endif
715 }
716 
717 #ifdef FEAT_EVAL
718 /*
719  * ":compiler[!] {name}"
720  */
721     void
ex_compiler(exarg_T * eap)722 ex_compiler(exarg_T *eap)
723 {
724     char_u	*buf;
725     char_u	*old_cur_comp = NULL;
726     char_u	*p;
727 
728     if (*eap->arg == NUL)
729     {
730 	// List all compiler scripts.
731 	do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
732 					// ) keep the indenter happy...
733     }
734     else
735     {
736 	buf = alloc(STRLEN(eap->arg) + 14);
737 	if (buf != NULL)
738 	{
739 	    if (eap->forceit)
740 	    {
741 		// ":compiler! {name}" sets global options
742 		do_cmdline_cmd((char_u *)
743 				   "command -nargs=* CompilerSet set <args>");
744 	    }
745 	    else
746 	    {
747 		// ":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.
753 		old_cur_comp = get_var_value((char_u *)"g:current_compiler");
754 		if (old_cur_comp != NULL)
755 		    old_cur_comp = vim_strsave(old_cur_comp);
756 		do_cmdline_cmd((char_u *)
757 		   "command -nargs=* -keepscript CompilerSet setlocal <args>");
758 	    }
759 	    do_unlet((char_u *)"g:current_compiler", TRUE);
760 	    do_unlet((char_u *)"b:current_compiler", TRUE);
761 
762 	    sprintf((char *)buf, "compiler/%s.vim", eap->arg);
763 	    if (source_runtime(buf, DIP_ALL) == FAIL)
764 		semsg(_("E666: compiler not supported: %s"), eap->arg);
765 	    vim_free(buf);
766 
767 	    do_cmdline_cmd((char_u *)":delcommand CompilerSet");
768 
769 	    // Set "b:current_compiler" from "current_compiler".
770 	    p = get_var_value((char_u *)"g:current_compiler");
771 	    if (p != NULL)
772 		set_internal_string_var((char_u *)"b:current_compiler", p);
773 
774 	    // Restore "current_compiler" for ":compiler {name}".
775 	    if (!eap->forceit)
776 	    {
777 		if (old_cur_comp != NULL)
778 		{
779 		    set_internal_string_var((char_u *)"g:current_compiler",
780 								old_cur_comp);
781 		    vim_free(old_cur_comp);
782 		}
783 		else
784 		    do_unlet((char_u *)"g:current_compiler", TRUE);
785 	    }
786 	}
787     }
788 }
789 #endif
790 
791 #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
init_pyxversion(void)798 init_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
requires_py_version(char_u * filename)820 requires_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 	    {
839 		// Check shebang.
840 		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
source_pyx_file(exarg_T * eap,char_u * fname)873 source_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)
884 	// user didn't choose a preference, 'pyx' is used
885 	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)
898 	CLEAR_FIELD(ex);
899     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);
912 	msg((char *)IObuff);
913 # 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);
924 	msg((char *)IObuff);
925 # endif
926 	return;
927     }
928 }
929 
930 /*
931  * ":pyxfile {fname}"
932  */
933     void
ex_pyxfile(exarg_T * eap)934 ex_pyxfile(exarg_T *eap)
935 {
936     source_pyx_file(eap, eap->arg);
937 }
938 
939 /*
940  * ":pyx"
941  */
942     void
ex_pyx(exarg_T * eap)943 ex_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
ex_pyxdo(exarg_T * eap)962 ex_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 
979 /*
980  * ":checktime [buffer]"
981  */
982     void
ex_checktime(exarg_T * eap)983 ex_checktime(exarg_T *eap)
984 {
985     buf_T	*buf;
986     int		save_no_check_timestamps = no_check_timestamps;
987 
988     no_check_timestamps = 0;
989     if (eap->addr_count == 0)	// default is all buffers
990 	check_timestamps(FALSE);
991     else
992     {
993 	buf = buflist_findnr((int)eap->line2);
994 	if (buf != NULL)	// cannot happen?
995 	    (void)buf_check_timestamp(buf, FALSE);
996     }
997     no_check_timestamps = save_no_check_timestamps;
998 }
999