Mercurial > vim
view src/ex_cmds2.c @ 34686:83875247fbc0 v9.1.0224
patch 9.1.0224: cursor may move too many lines over "right" & "below" virt text
Commit: https://github.com/vim/vim/commit/515f734e687f28f7199b2a8042197624d9f3ec15
Author: Dylan Thacker-Smith <dylan.ah.smith@gmail.com>
Date: Thu Mar 28 12:01:14 2024 +0100
patch 9.1.0224: cursor may move too many lines over "right" & "below" virt text
Problem: If a line has "right" & "below" virtual text properties,
where the "below" property may be stored first due to lack of
ordering between them, then the line height is calculated to
be 1 more and causes the cursor to far over the line.
Solution: Remove some unnecessary setting of a
`next_right_goes_below = TRUE` flag for "below" and "above"
text properties. (Dylan Thacker-Smith)
I modified a regression test I recently added to cover this case,
leveraging the fact that "after", "right" & "below" text properties are
being stored in the reverse of the order they are added in. The
previous version of this regression test was crafted to workaround this
issue so it can be addressed by this separate patch.
closes: #14317
Signed-off-by: Dylan Thacker-Smith <dylan.ah.smith@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 28 Mar 2024 12:15:03 +0100 |
parents | 4da97f213d15 |
children | 54890be01c00 |
line wrap: on
line source
/* vi:set ts=8 sts=4 sw=4 noet: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * ex_cmds2.c: some more functions for command line commands */ #include "vim.h" #include "version.h" /* * If 'autowrite' option set, try to write the file. * Careful: autocommands may make "buf" invalid! * * return FAIL for failure, OK otherwise */ int autowrite(buf_T *buf, int forceit) { int r; bufref_T bufref; if (!(p_aw || p_awa) || !p_write // never autowrite a "nofile" or "nowrite" buffer || bt_dontwrite(buf) || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) return FAIL; set_bufref(&bufref, buf); r = buf_write_all(buf, forceit); // Writing may succeed but the buffer still changed, e.g., when there is a // conversion error. We do want to return FAIL then. if (bufref_valid(&bufref) && bufIsChanged(buf)) r = FAIL; return r; } /* * Flush all buffers, except the ones that are readonly or are never written. */ void autowrite_all(void) { buf_T *buf; if (!(p_aw || p_awa) || !p_write) return; FOR_ALL_BUFFERS(buf) if (bufIsChanged(buf) && !buf->b_p_ro && !bt_dontwrite(buf)) { bufref_T bufref; set_bufref(&bufref, buf); (void)buf_write_all(buf, FALSE); // an autocommand may have deleted the buffer if (!bufref_valid(&bufref)) buf = firstbuf; } } /* * Return TRUE if buffer was changed and cannot be abandoned. * For flags use the CCGD_ values. */ int check_changed(buf_T *buf, int flags) { int forceit = (flags & CCGD_FORCEIT); bufref_T bufref; set_bufref(&bufref, buf); if ( !forceit && bufIsChanged(buf) && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1) && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL)) { #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write) { # ifdef FEAT_TERMINAL if (term_job_running(buf->b_term)) { return term_confirm_stop(buf) == FAIL; } # endif buf_T *buf2; int count = 0; if (flags & CCGD_ALLBUF) FOR_ALL_BUFFERS(buf2) if (bufIsChanged(buf2) && (buf2->b_ffname != NULL # ifdef FEAT_BROWSE || (cmdmod.cmod_flags & CMOD_BROWSE) # endif )) ++count; if (!bufref_valid(&bufref)) // Autocommand deleted buffer, oops! It's not changed now. return FALSE; dialog_changed(buf, count > 1); if (!bufref_valid(&bufref)) // Autocommand deleted buffer, oops! It's not changed now. return FALSE; return bufIsChanged(buf); } #endif if (flags & CCGD_EXCMD) no_write_message(); else no_write_message_nobang(curbuf); return TRUE; } return FALSE; } #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO) #if defined(FEAT_BROWSE) || defined(PROTO) /* * When wanting to write a file without a file name, ask the user for a name. */ void browse_save_fname(buf_T *buf) { if (buf->b_fname != NULL) return; char_u *fname; fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"), NULL, NULL, NULL, NULL, buf); if (fname == NULL) return; if (setfname(buf, fname, NULL, TRUE) == OK) buf->b_flags |= BF_NOTEDITED; vim_free(fname); } #endif /* * Ask the user what to do when abandoning a changed buffer. * Must check 'write' option first! */ void dialog_changed( buf_T *buf, int checkall) // may abandon all changed buffers { char_u buff[DIALOG_MSG_SIZE]; int ret; buf_T *buf2; exarg_T ea; dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname); if (checkall) ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1); else ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1); // Init ea pseudo-structure, this is needed for the check_overwrite() // function. CLEAR_FIELD(ea); if (ret == VIM_YES) { #ifdef FEAT_BROWSE // May get file name, when there is none browse_save_fname(buf); #endif if (buf->b_fname != NULL && check_overwrite(&ea, buf, buf->b_fname, buf->b_ffname, FALSE) == OK) // didn't hit Cancel (void)buf_write_all(buf, FALSE); } else if (ret == VIM_NO) { unchanged(buf, TRUE, FALSE); } else if (ret == VIM_ALL) { /* * Write all modified files that can be written. * Skip readonly buffers, these need to be confirmed * individually. */ FOR_ALL_BUFFERS(buf2) { if (bufIsChanged(buf2) && (buf2->b_ffname != NULL #ifdef FEAT_BROWSE || (cmdmod.cmod_flags & CMOD_BROWSE) #endif ) && !bt_dontwrite(buf2) && !buf2->b_p_ro) { bufref_T bufref; set_bufref(&bufref, buf2); #ifdef FEAT_BROWSE // May get file name, when there is none browse_save_fname(buf2); #endif if (buf2->b_fname != NULL && check_overwrite(&ea, buf2, buf2->b_fname, buf2->b_ffname, FALSE) == OK) // didn't hit Cancel (void)buf_write_all(buf2, FALSE); // an autocommand may have deleted the buffer if (!bufref_valid(&bufref)) buf2 = firstbuf; } } } else if (ret == VIM_DISCARDALL) { /* * mark all buffers as unchanged */ FOR_ALL_BUFFERS(buf2) unchanged(buf2, TRUE, FALSE); } } #endif /* * Return TRUE if the buffer "buf" can be abandoned, either by making it * hidden, autowriting it or unloading it. */ int can_abandon(buf_T *buf, int forceit) { return ( buf_hide(buf) || !bufIsChanged(buf) || buf->b_nwindows > 1 || autowrite(buf, forceit) == OK || forceit); } /* * Add a buffer number to "bufnrs", unless it's already there. */ static void add_bufnum(int *bufnrs, int *bufnump, int nr) { int i; for (i = 0; i < *bufnump; ++i) if (bufnrs[i] == nr) return; bufnrs[*bufnump] = nr; *bufnump = *bufnump + 1; } /* * Return TRUE if any buffer was changed and cannot be abandoned. * That changed buffer becomes the current buffer. * When "unload" is TRUE the current buffer is unloaded instead of making it * hidden. This is used for ":q!". */ int check_changed_any( int hidden, // Only check hidden buffers int unload) { int ret = FALSE; buf_T *buf; int save; int i; int bufnum = 0; int bufcount = 0; int *bufnrs; tabpage_T *tp; win_T *wp; // Make a list of all buffers, with the most important ones first. FOR_ALL_BUFFERS(buf) ++bufcount; if (bufcount == 0) return FALSE; bufnrs = ALLOC_MULT(int, bufcount); if (bufnrs == NULL) return FALSE; // curbuf bufnrs[bufnum++] = curbuf->b_fnum; // buffers in current tab FOR_ALL_WINDOWS(wp) if (wp->w_buffer != curbuf) add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); // buffers in other tabs FOR_ALL_TABPAGES(tp) if (tp != curtab) FOR_ALL_WINDOWS_IN_TAB(tp, wp) add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); // any other buffer FOR_ALL_BUFFERS(buf) add_bufnum(bufnrs, &bufnum, buf->b_fnum); for (i = 0; i < bufnum; ++i) { buf = buflist_findnr(bufnrs[i]); if (buf == NULL) continue; if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) { bufref_T bufref; set_bufref(&bufref, buf); #ifdef FEAT_TERMINAL if (term_job_running(buf->b_term)) { if (term_try_stop_job(buf) == FAIL) break; } else #endif // Try auto-writing the buffer. If this fails but the buffer no // longer exists it's not changed, that's OK. if (check_changed(buf, (p_awa ? CCGD_AW : 0) | CCGD_MULTWIN | CCGD_ALLBUF) && bufref_valid(&bufref)) break; // didn't save - still changes } } if (i >= bufnum) goto theend; // Get here if "buf" cannot be abandoned. ret = TRUE; exiting = FALSE; #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) /* * When ":confirm" used, don't give an error message. */ if (!(p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM))) #endif { // There must be a wait_return() for this message, do_buffer() // may cause a redraw. But wait_return() is a no-op when vgetc() // is busy (Quit used from window menu), then make sure we don't // cause a scroll up. if (vgetc_busy > 0) { msg_row = cmdline_row; msg_col = 0; msg_didout = FALSE; } if ( #ifdef FEAT_TERMINAL term_job_running(buf->b_term) ? semsg(_(e_job_still_running_in_buffer_str), buf->b_fname) : #endif semsg(_(e_no_write_since_last_change_for_buffer_str), buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname)) { save = no_wait_return; no_wait_return = FALSE; wait_return(FALSE); no_wait_return = save; } } // Try to find a window that contains the buffer. if (buf != curbuf) FOR_ALL_TAB_WINDOWS(tp, wp) if (wp->w_buffer == buf) { bufref_T bufref; set_bufref(&bufref, buf); goto_tabpage_win(tp, wp); // Paranoia: did autocmd wipe out the buffer with changes? if (!bufref_valid(&bufref)) goto theend; goto buf_found; } buf_found: // Open the changed buffer in the current window. if (buf != curbuf) set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO); theend: vim_free(bufnrs); return ret; } /* * return FAIL if there is no file name, OK if there is one * give error message for FAIL */ int check_fname(void) { if (curbuf->b_ffname == NULL) { emsg(_(e_no_file_name)); return FAIL; } return OK; } /* * flush the contents of a buffer, unless it has no file name * * return FAIL for failure, OK otherwise */ int buf_write_all(buf_T *buf, int forceit) { int retval; buf_T *old_curbuf = curbuf; retval = (buf_write(buf, buf->b_ffname, buf->b_fname, (linenr_T)1, buf->b_ml.ml_line_count, NULL, FALSE, forceit, TRUE, FALSE)); if (curbuf != old_curbuf) { msg_source(HL_ATTR(HLF_W)); msg(_("Warning: Entered other buffer unexpectedly (check autocommands)")); } return retval; } /* * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo" */ void ex_listdo(exarg_T *eap) { int i; win_T *wp; tabpage_T *tp; buf_T *buf = curbuf; int next_fnum = 0; if (curwin->w_p_wfb) { if ((eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) && !eap->forceit) { // Disallow :ldo if 'winfixbuf' is applied emsg(_(e_winfixbuf_cannot_go_to_buffer)); return; } if (win_valid(prevwin) && !prevwin->w_p_wfb) // 'winfixbuf' is set; attempt to change to a window without it. win_goto(prevwin); if (curwin->w_p_wfb) { // Split the window, which will be 'nowinfixbuf', and set curwin to // that (void)win_split(0, 0); if (curwin->w_p_wfb) { // Autocommands set 'winfixbuf' or sent us to another window // with it set, or we failed to split the window. Give up. emsg(_(e_winfixbuf_cannot_go_to_buffer)); return; } } } #if defined(FEAT_SYN_HL) char_u *save_ei = NULL; #endif #ifdef FEAT_QUICKFIX int qf_size = 0; int qf_idx; #endif #ifndef FEAT_QUICKFIX if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) { ex_ni(eap); return; } #endif #if defined(FEAT_SYN_HL) if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo) { // Don't do syntax HL autocommands. Skipping the syntax file is a // great speed improvement. save_ei = au_event_disable(",Syntax"); FOR_ALL_BUFFERS(buf) buf->b_flags &= ~BF_SYN_SET; buf = curbuf; } #endif #ifdef FEAT_CLIPBOARD start_global_changes(); #endif if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo || buf_hide(curbuf) || !check_changed(curbuf, CCGD_AW | (eap->forceit ? CCGD_FORCEIT : 0) | CCGD_EXCMD)) { i = 0; // start at the eap->line1 argument/window/buffer wp = firstwin; tp = first_tabpage; switch (eap->cmdidx) { case CMD_windo: for ( ; wp != NULL && i + 1 < eap->line1; wp = wp->w_next) i++; break; case CMD_tabdo: for ( ; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next) i++; break; case CMD_argdo: i = eap->line1 - 1; break; default: break; } // set pcmark now if (eap->cmdidx == CMD_bufdo) { // Advance to the first listed buffer after "eap->line1". for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1 || !buf->b_p_bl); buf = buf->b_next) if (buf->b_fnum > eap->line2) { buf = NULL; break; } if (buf != NULL) goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum); } #ifdef FEAT_QUICKFIX else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) { qf_size = qf_get_valid_size(eap); if (qf_size <= 0 || eap->line1 > qf_size) buf = NULL; else { save_clear_shm_value(); ex_cc(eap); restore_shm_value(); buf = curbuf; i = eap->line1 - 1; if (eap->addr_count <= 0) // default is all the quickfix/location list entries eap->line2 = qf_size; } } #endif else setpcmark(); listcmd_busy = TRUE; // avoids setting pcmark below while (!got_int && buf != NULL) { if (eap->cmdidx == CMD_argdo) { // go to argument "i" if (i == ARGCOUNT) break; // Don't call do_argfile() when already there, it will try // reloading the file. if (curwin->w_arg_idx != i || !editing_arg_idx(curwin)) { // Clear 'shm' to avoid that the file message overwrites // any output from the command. save_clear_shm_value(); do_argfile(eap, i); restore_shm_value(); } if (curwin->w_arg_idx != i) break; } else if (eap->cmdidx == CMD_windo) { // go to window "wp" if (!win_valid(wp)) break; win_goto(wp); if (curwin != wp) break; // something must be wrong wp = curwin->w_next; } else if (eap->cmdidx == CMD_tabdo) { // go to window "tp" if (!valid_tabpage(tp)) break; goto_tabpage_tp(tp, TRUE, TRUE); tp = tp->tp_next; } else if (eap->cmdidx == CMD_bufdo) { // Remember the number of the next listed buffer, in case // ":bwipe" is used or autocommands do something strange. next_fnum = -1; for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next) if (buf->b_p_bl) { next_fnum = buf->b_fnum; break; } } ++i; // execute the command do_cmdline(eap->arg, eap->ea_getline, eap->cookie, DOCMD_VERBOSE + DOCMD_NOWAIT); if (eap->cmdidx == CMD_bufdo) { // Done? if (next_fnum < 0 || next_fnum > eap->line2) break; // Check if the buffer still exists. FOR_ALL_BUFFERS(buf) if (buf->b_fnum == next_fnum) break; if (buf == NULL) break; // Go to the next buffer. Clear 'shm' to avoid that the file // message overwrites any output from the command. save_clear_shm_value(); goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); restore_shm_value(); // If autocommands took us elsewhere, quit here. if (curbuf->b_fnum != next_fnum) break; } #ifdef FEAT_QUICKFIX if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) { if (i >= qf_size || i >= eap->line2) break; qf_idx = qf_get_cur_idx(eap); save_clear_shm_value(); ex_cnext(eap); restore_shm_value(); // If jumping to the next quickfix entry fails, quit here if (qf_get_cur_idx(eap) == qf_idx) break; } #endif if (eap->cmdidx == CMD_windo) { validate_cursor(); // cursor may have moved // required when 'scrollbind' has been set if (curwin->w_p_scb) do_check_scrollbind(TRUE); } if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo) if (i+1 > eap->line2) break; if (eap->cmdidx == CMD_argdo && i >= eap->line2) break; } listcmd_busy = FALSE; } #if defined(FEAT_SYN_HL) if (save_ei != NULL) { buf_T *bnext; aco_save_T aco; au_event_restore(save_ei); for (buf = firstbuf; buf != NULL; buf = bnext) { bnext = buf->b_next; if (buf->b_nwindows > 0 && (buf->b_flags & BF_SYN_SET)) { buf->b_flags &= ~BF_SYN_SET; // buffer was opened while Syntax autocommands were disabled, // need to trigger them now. if (buf == curbuf) apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname, TRUE, curbuf); else { aucmd_prepbuf(&aco, buf); if (curbuf == buf) { apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname, TRUE, buf); aucmd_restbuf(&aco); } } // start over, in case autocommands messed things up. bnext = firstbuf; } } } #endif #ifdef FEAT_CLIPBOARD end_global_changes(); #endif } #ifdef FEAT_EVAL /* * ":compiler[!] {name}" */ void ex_compiler(exarg_T *eap) { char_u *buf; char_u *old_cur_comp = NULL; char_u *p; if (*eap->arg == NUL) { // List all compiler scripts. do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')"); // ) keep the indenter happy... return; } buf = alloc(STRLEN(eap->arg) + 14); if (buf == NULL) return; if (eap->forceit) { // ":compiler! {name}" sets global options do_cmdline_cmd((char_u *) "command -nargs=* CompilerSet set <args>"); } else { // ":compiler! {name}" sets local options. // To remain backwards compatible "current_compiler" is always // used. A user's compiler plugin may set it, the distributed // plugin will then skip the settings. Afterwards set // "b:current_compiler" and restore "current_compiler". // Explicitly prepend "g:" to make it work in a function. old_cur_comp = get_var_value((char_u *)"g:current_compiler"); if (old_cur_comp != NULL) old_cur_comp = vim_strsave(old_cur_comp); do_cmdline_cmd((char_u *) "command -nargs=* -keepscript CompilerSet setlocal <args>"); } do_unlet((char_u *)"g:current_compiler", TRUE); do_unlet((char_u *)"b:current_compiler", TRUE); sprintf((char *)buf, "compiler/%s.vim", eap->arg); if (source_runtime(buf, DIP_ALL) == FAIL) semsg(_(e_compiler_not_supported_str), eap->arg); vim_free(buf); do_cmdline_cmd((char_u *)":delcommand CompilerSet"); // Set "b:current_compiler" from "current_compiler". p = get_var_value((char_u *)"g:current_compiler"); if (p != NULL) set_internal_string_var((char_u *)"b:current_compiler", p); // Restore "current_compiler" for ":compiler {name}". if (!eap->forceit) { if (old_cur_comp != NULL) { set_internal_string_var((char_u *)"g:current_compiler", old_cur_comp); vim_free(old_cur_comp); } else do_unlet((char_u *)"g:current_compiler", TRUE); } } #endif #if defined(FEAT_PYTHON3) || defined(FEAT_PYTHON) || defined(PROTO) # if (defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO) /* * Detect Python 3 or 2, and initialize 'pyxversion'. */ void init_pyxversion(void) { if (p_pyx == 0) { if (python3_enabled(FALSE)) p_pyx = 3; else if (python_enabled(FALSE)) p_pyx = 2; } } # endif /* * Does a file contain one of the following strings at the beginning of any * line? * "#!(any string)python2" => returns 2 * "#!(any string)python3" => returns 3 * "# requires python 2.x" => returns 2 * "# requires python 3.x" => returns 3 * otherwise return 0. */ static int requires_py_version(char_u *filename) { FILE *file; int requires_py_version = 0; int i, lines; lines = (int)p_mls; if (lines < 0) lines = 5; file = mch_fopen((char *)filename, "r"); if (file == NULL) return 0; for (i = 0; i < lines; i++) { if (vim_fgets(IObuff, IOSIZE, file)) break; if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!') { // Check shebang. if (strstr((char *)IObuff + 2, "python2") != NULL) { requires_py_version = 2; break; } if (strstr((char *)IObuff + 2, "python3") != NULL) { requires_py_version = 3; break; } } IObuff[21] = '\0'; if (STRCMP("# requires python 2.x", IObuff) == 0) { requires_py_version = 2; break; } if (STRCMP("# requires python 3.x", IObuff) == 0) { requires_py_version = 3; break; } } fclose(file); return requires_py_version; } /* * Source a python file using the requested python version. */ static void source_pyx_file(exarg_T *eap, char_u *fname) { exarg_T ex; int v = requires_py_version(fname); # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) init_pyxversion(); # endif if (v == 0) { # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) // user didn't choose a preference, 'pyx' is used v = p_pyx; # elif defined(FEAT_PYTHON) v = 2; # elif defined(FEAT_PYTHON3) v = 3; # endif } /* * now source, if required python version is not supported show * unobtrusive message. */ if (eap == NULL) CLEAR_FIELD(ex); else ex = *eap; ex.arg = fname; ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3"); if (v == 2) { # ifdef FEAT_PYTHON ex_pyfile(&ex); # else vim_snprintf((char *)IObuff, IOSIZE, _("W20: Required python version 2.x not supported, ignoring file: %s"), fname); msg((char *)IObuff); # endif return; } else { # ifdef FEAT_PYTHON3 ex_py3file(&ex); # else vim_snprintf((char *)IObuff, IOSIZE, _("W21: Required python version 3.x not supported, ignoring file: %s"), fname); msg((char *)IObuff); # endif return; } } /* * ":pyxfile {fname}" */ void ex_pyxfile(exarg_T *eap) { source_pyx_file(eap, eap->arg); } /* * ":pyx" */ void ex_pyx(exarg_T *eap) { # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) init_pyxversion(); if (p_pyx == 2) ex_python(eap); else ex_py3(eap); # elif defined(FEAT_PYTHON) ex_python(eap); # elif defined(FEAT_PYTHON3) ex_py3(eap); # endif } /* * ":pyxdo" */ void ex_pyxdo(exarg_T *eap) { # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) init_pyxversion(); if (p_pyx == 2) ex_pydo(eap); else ex_py3do(eap); # elif defined(FEAT_PYTHON) ex_pydo(eap); # elif defined(FEAT_PYTHON3) ex_py3do(eap); # endif } #endif /* * ":checktime [buffer]" */ void ex_checktime(exarg_T *eap) { buf_T *buf; int save_no_check_timestamps = no_check_timestamps; no_check_timestamps = 0; if (eap->addr_count == 0) // default is all buffers check_timestamps(FALSE); else { buf = buflist_findnr((int)eap->line2); if (buf != NULL) // cannot happen? (void)buf_check_timestamp(buf, FALSE); } no_check_timestamps = save_no_check_timestamps; }