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