Compare commits

...

11 Commits

Author SHA1 Message Date
=?UTF-8?q?Magnus=20Gro=C3=9F?=
25def2c8b8 patch 8.2.3555: ModeChanged is not triggered on every mode change
Problem:    ModeChanged is not triggered on every mode change.
Solution:   Also trigger on minor mode changes. (Maguns Gross, closes #8999)
2021-10-22 18:56:39 +01:00
DungSaga
a2ffb43520 patch 8.2.3554: xxd has various way to exit
Problem:    Xxd has various way to exit.
Solution:   Add function to print error and exit. (closes #9035)
2021-10-22 15:55:31 +01:00
Bram Moolenaar
5a5c111e79 patch 8.2.3553: xxd test fails on MS-Windows
Problem:    Xxd test fails on MS-Windows.
Solution:   Split shell command in two.
2021-10-22 15:11:37 +01:00
DungSaga
47810464aa patch 8.2.3552: xxd revert does not handle end of line correctly
Problem:    Xxd revert does not handle end of line correctly.
Solution:   Check for newline first. (closes #9034)
2021-10-22 12:55:42 +01:00
itchyny
94e7d345c1 patch 8.2.3551: checking first character of url twice
Problem:    Checking first character of url twice.
Solution:   Only check once. (closes #9026)
2021-10-21 18:01:13 +01:00
Shougo Matsushita
ae38a9db77 patch 8.2.3550: completion() does not work properly
Problem:    completion() does not work properly.
Solution:   Set xp_line and add WILD_HOME_REPLACE. (Shougo Matsushita,
            closes #9016)
2021-10-21 11:39:53 +01:00
zeertzjq
b811de5d49 patch 8.2.3549: mistakes in test comments
Problem:    Mistakes in test comments.
Solution:   Fix the comments. (closes #9029)
2021-10-21 10:50:44 +01:00
Bram Moolenaar
d68a004485 patch 8.2.3548: GTK GUI crashen when reading from stdin
Problem:    GTK GUI crashen when reading from stdin.
Solution:   Do not overwrite the NUL after the string. (closes #9028)
2021-10-20 23:08:11 +01:00
Bram Moolenaar
1d30fde3c9 patch 8.2.3547: opening the quickfix window triggers BufWinEnter twice
Problem:    Opening the quickfix window triggers BufWinEnter twice. (Yorick
            Peterse)
Solution:   Only trigger BufWinEnter with "quickfix". (closes #9022)
2021-10-20 21:58:42 +01:00
zeertzjq
09f7723d5a patch 8.2.3546: build failure without the +eval feature
Problem:    Build failure without the +eval feature.
Solution:   Add #ifdef. (closes #9025)
2021-10-20 17:21:24 +01:00
zeertzjq
94358a1e6e patch 8.2.3545: setcellwidths() may make 'listchars' or 'fillchars' invalid
Problem:    setcellwidths() may make 'listchars' or 'fillchars' invalid.
Solution:   Check the value and give an error. (closes #9024)
2021-10-20 11:01:15 +01:00
25 changed files with 352 additions and 125 deletions

View File

@@ -930,18 +930,23 @@ MenuPopup Just before showing the popup menu (under the
*ModeChanged*
ModeChanged After changing the mode. The pattern is
matched against `'old_mode:new_mode'`, for
example match against `i:*` to simulate
|InsertLeave|.
example match against `*:c*` to simulate
|CmdlineEnter|.
The following values of |v:event| are set:
old_mode The mode before it changed.
new_mode The new mode as also returned
by |mode()|.
by |mode()| called with a
non-zero argument.
When ModeChanged is triggered, old_mode will
have the value of new_mode when the event was
last triggered.
This will be triggered on every minor mode
change.
Usage example to use relative line numbers
when entering Visual mode: >
:autocmd ModeChanged *:v set relativenumber
:au ModeChanged [vV\x16]*:* let &l:rnu = mode() =~# '^[vV\x16]'
:au ModeChanged *:[vV\x16]* let &l:rnu = mode() =~# '^[vV\x16]'
:au WinEnter,WinLeave * let &l:rnu = mode() =~# '^[vV\x16]'
< *OptionSet*
OptionSet After setting an option. The pattern is
matched against the long option name.

View File

@@ -9648,6 +9648,9 @@ setcellwidths({list}) *setcellwidths()*
range overlaps with another.
Only characters with value 0x100 and higher can be used.
If the new value causes 'fillchars' or 'listchars' to become
invalid it is rejected and an error is given.
To clear the overrides pass an empty list: >
setcellwidths([]);
< You can use the script $VIMRUNTIME/tools/emoji_list.vim to see

View File

@@ -1218,6 +1218,23 @@ do_autocmd_event(
return FAIL;
}
#ifdef FEAT_EVAL
// need to initialize last_mode for the first ModeChanged
// autocmd
if (event == EVENT_MODECHANGED && !has_modechanged())
{
typval_T rettv;
typval_T tv[2];
tv[0].v_type = VAR_NUMBER;
tv[0].vval.v_number = 1;
tv[1].v_type = VAR_UNKNOWN;
f_mode(tv, &rettv);
STRCPY(last_mode, rettv.vval.v_string);
vim_free(rettv.vval.v_string);
}
#endif
if (is_buflocal)
{
ap->buflocal_nr = buflocal_nr;

View File

@@ -360,11 +360,12 @@ open_buffer(
do_modelines(0);
curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);
if ((flags & READ_NOWINENTER) == 0)
#ifdef FEAT_EVAL
apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf,
&retval);
apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE,
curbuf, &retval);
#else
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
#endif
// restore curwin/curbuf and a few other things

View File

@@ -978,6 +978,7 @@ set_one_cmd_context(
ExpandInit(xp);
xp->xp_pattern = buff;
xp->xp_line = buff;
xp->xp_context = EXPAND_COMMANDS; // Default until we get past command
ea.argt = 0;
@@ -2891,7 +2892,7 @@ f_getcompletion(typval_T *argvars, typval_T *rettv)
expand_T xpc;
int filtered = FALSE;
int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH
| WILD_NO_BEEP;
| WILD_NO_BEEP | WILD_HOME_REPLACE;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL

View File

@@ -160,6 +160,12 @@ EXTERN char e_list_value_does_not_have_enough_items[]
INIT(= N_("E711: List value does not have enough items"));
EXTERN char e_cannot_slice_dictionary[]
INIT(= N_("E719: Cannot slice a Dictionary"));
#endif
EXTERN char e_conflicts_with_value_of_listchars[]
INIT(= N_("E834: Conflicts with value of 'listchars'"));
EXTERN char e_conflicts_with_value_of_fillchars[]
INIT(= N_("E835: Conflicts with value of 'fillchars'"));
#ifdef FEAT_EVAL
EXTERN char e_assert_fails_second_arg[]
INIT(= N_("E856: \"assert_fails()\" second argument must be a string or a list with one or two strings"));
EXTERN char e_using_invalid_value_as_string_str[]

View File

@@ -2473,6 +2473,7 @@ theend:
* ECMD_FORCEIT: ! used for Ex command
* ECMD_ADDBUF: don't edit, just add to buffer list
* ECMD_ALTBUF: like ECMD_ADDBUF and also set the alternate file
* ECMD_NOWINENTER: Do not trigger BufWinEnter
* oldwin: Should be "curwin" when editing a new buffer in the current
* window, NULL when splitting the window first. When not NULL info
* of the previous buffer for "oldwin" is stored.
@@ -3030,6 +3031,8 @@ do_ecmd(
/*
* Open the buffer and read the file.
*/
if (flags & ECMD_NOWINENTER)
readfile_flags |= READ_NOWINENTER;
#if defined(FEAT_EVAL)
if (should_abort(open_buffer(FALSE, eap, readfile_flags)))
retval = FAIL;
@@ -3051,10 +3054,11 @@ do_ecmd(
// changed by the user.
do_modelines(OPT_WINONLY);
apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf,
&retval);
apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf,
&retval);
apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE,
curbuf, &retval);
if ((flags & ECMD_NOWINENTER) == 0)
apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE,
curbuf, &retval);
}
check_arg_idx(curwin);

View File

@@ -5744,12 +5744,16 @@ gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags)
}
}
// temporarily zero terminate substring, print, restore char, wrap
backup_ch = *(cs + slen);
*(cs + slen) = 0;
if (slen < len)
{
// temporarily zero terminate substring, print, restore char, wrap
backup_ch = *(cs + slen);
*(cs + slen) = NUL;
}
len_sum += gui_gtk2_draw_string_ext(row, col + len_sum,
cs, slen, flags, needs_pango);
*(cs + slen) = backup_ch;
if (slen < len)
*(cs + slen) = backup_ch;
cs += slen;
byte_sum += slen;
needs_pango = should_need_pango;

View File

@@ -243,6 +243,8 @@ ins_ctrl_x(void)
// CTRL-X in CTRL-X CTRL-V mode behaves differently to make CTRL-X
// CTRL-V look like CTRL-N
ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X;
trigger_modechanged();
}
/*
@@ -2150,6 +2152,8 @@ ins_compl_prep(int c)
// upon the (possibly failed) completion.
ins_apply_autocmds(EVENT_COMPLETEDONE);
trigger_modechanged();
// reset continue_* if we left expansion-mode, if we stay they'll be
// (re)set properly in ins_complete()
if (!vim_is_ctrl_x_key(c))
@@ -2487,6 +2491,7 @@ set_completion(colnr_T startcol, list_T *list)
// Lazily show the popup menu, unless we got interrupted.
if (!compl_interrupted)
show_pum(save_w_wrow, save_w_leftcol);
trigger_modechanged();
out_flush();
}
@@ -3255,6 +3260,8 @@ ins_compl_get_exp(pos_T *ini)
if (compl_curr_match == NULL)
compl_curr_match = compl_old_match;
}
trigger_modechanged();
return i;
}

View File

@@ -5510,6 +5510,8 @@ f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED)
int i;
listitem_T **ptrs;
cw_interval_T *table;
cw_interval_T *cw_table_save;
size_t cw_table_size_save;
if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL)
return;
@@ -5620,9 +5622,41 @@ f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED)
}
vim_free(ptrs);
vim_free(cw_table);
cw_table_save = cw_table;
cw_table_size_save = cw_table_size;
cw_table = table;
cw_table_size = l->lv_len;
// Check that the new value does not conflict with 'fillchars' or
// 'listchars'.
if (set_chars_option(curwin, &p_fcs) != NULL)
{
emsg(_(e_conflicts_with_value_of_fillchars));
cw_table = cw_table_save;
cw_table_size = cw_table_size_save;
vim_free(table);
return;
}
else
{
tabpage_T *tp;
win_T *wp;
FOR_ALL_TAB_WINDOWS(tp, wp)
{
if (set_chars_option(wp, &wp->w_p_lcs) != NULL)
{
emsg((e_conflicts_with_value_of_listchars));
cw_table = cw_table_save;
cw_table_size = cw_table_size_save;
vim_free(table);
return;
}
}
}
vim_free(cw_table_save);
}
void

View File

@@ -2643,7 +2643,7 @@ path_with_url(char_u *fname)
return 0;
// check body: alpha or dash
for (p = fname; (isalpha(*p) || (*p == '-')); ++p)
for (p = fname + 1; (isalpha(*p) || (*p == '-')); ++p)
;
// check last char is not a dash
@@ -2670,12 +2670,17 @@ trigger_modechanged()
if (!has_modechanged())
return;
v_event = get_vim_var_dict(VV_EVENT);
tv[0].v_type = VAR_NUMBER;
tv[0].vval.v_number = 1; // get full mode
tv[1].v_type = VAR_UNKNOWN;
f_mode(tv, &rettv);
if (STRCMP(rettv.vval.v_string, last_mode) == 0)
{
vim_free(rettv.vval.v_string);
return;
}
v_event = get_vim_var_dict(VV_EVENT);
(void)dict_add_string(v_event, "new_mode", rettv.vval.v_string);
(void)dict_add_string(v_event, "old_mode", last_mode);
dict_set_items_ro(v_event);
@@ -2688,9 +2693,9 @@ trigger_modechanged()
apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf);
STRCPY(last_mode, rettv.vval.v_string);
vim_free(rettv.vval.v_string);
vim_free(pat);
dict_free_contents(v_event);
hash_init(&v_event->dv_hashtab);
vim_free(rettv.vval.v_string);
#endif
}

View File

@@ -527,6 +527,7 @@ normal_cmd(
# endif
}
#endif
trigger_modechanged();
// When not finishing an operator and no register name typed, reset the
// count.
@@ -1221,6 +1222,7 @@ normal_end:
c = finish_op;
#endif
finish_op = FALSE;
trigger_modechanged();
#ifdef CURSOR_SHAPE
// Redraw the cursor with another shape, if we were in Operator-pending
// mode or did a replace command.
@@ -1278,6 +1280,7 @@ normal_end:
if (restart_VIsual_select == 1)
{
VIsual_select = TRUE;
trigger_modechanged();
showmode();
restart_VIsual_select = 0;
}
@@ -1386,7 +1389,6 @@ end_visual_mode_keep_button()
#endif
VIsual_active = FALSE;
trigger_modechanged();
setmouse();
mouse_dragging = 0;
@@ -1403,6 +1405,7 @@ end_visual_mode_keep_button()
may_clear_cmdline();
adjust_cursor_eol();
trigger_modechanged();
}
/*
@@ -3439,6 +3442,7 @@ nv_ctrlg(cmdarg_T *cap)
if (VIsual_active) // toggle Selection/Visual mode
{
VIsual_select = !VIsual_select;
trigger_modechanged();
showmode();
}
else if (!checkclearop(cap->oap))
@@ -3501,6 +3505,7 @@ nv_ctrlo(cmdarg_T *cap)
if (VIsual_active && VIsual_select)
{
VIsual_select = FALSE;
trigger_modechanged();
showmode();
restart_VIsual_select = 2; // restart Select mode later
}

View File

@@ -871,7 +871,7 @@ did_set_string_option(
if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK)
errmsg = e_invarg;
else if (set_chars_option(curwin, &p_fcs) != NULL)
errmsg = _("E835: Conflicts with value of 'fillchars'");
errmsg = _(e_conflicts_with_value_of_fillchars);
else
{
tabpage_T *tp;
@@ -881,7 +881,7 @@ did_set_string_option(
{
if (set_chars_option(wp, &wp->w_p_lcs) != NULL)
{
errmsg = _("E834: Conflicts with value of 'listchars'");
errmsg = _(e_conflicts_with_value_of_listchars);
goto ambw_end;
}
}

View File

@@ -4199,13 +4199,14 @@ qf_open_new_cwindow(qf_info_T *qi, int height)
{
// Use the existing quickfix buffer
if (do_ecmd(qf_buf->b_fnum, NULL, NULL, NULL, ECMD_ONE,
ECMD_HIDE + ECMD_OLDBUF, oldwin) == FAIL)
ECMD_HIDE + ECMD_OLDBUF + ECMD_NOWINENTER, oldwin) == FAIL)
return FAIL;
}
else
{
// Create a new quickfix buffer
if (do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, oldwin) == FAIL)
if (do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE + ECMD_NOWINENTER,
oldwin) == FAIL)
return FAIL;
// save the number of the new buffer

View File

@@ -1995,6 +1995,7 @@ term_check_timers(int next_due_arg, proftime_T *now)
set_terminal_mode(term_T *term, int normal_mode)
{
term->tl_normal_mode = normal_mode;
trigger_modechanged();
if (!normal_mode)
handle_postponed_scrollback(term);
VIM_CLEAR(term->tl_status_text);

View File

@@ -760,33 +760,33 @@ func Test_OptionSet()
call assert_equal(g:opt[0], g:opt[1])
" 19a: Setting string local-global (to buffer) option"
" 19a: Setting string global-local (to buffer) option"
let oldval = &tags
let g:options = [['tags', oldval, oldval, oldval, 'tagpath', 'global', 'set']]
set tags=tagpath
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19b: Resetting string local-global (to buffer) option"
" 19b: Resetting string global-local (to buffer) option"
let g:options = [['tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set']]
set tags&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19c: Setting global string local-global (to buffer) option "
" 19c: Setting global string global-local (to buffer) option "
let g:options = [['tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal']]
setglobal tags=tagpath1
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19d: Setting local string local-global (to buffer) option"
" 19d: Setting local string global-local (to buffer) option"
let g:options = [['tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal']]
setlocal tags=tagpath2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19e: Setting again string local-global (to buffer) option"
" Note: v:option_old is the old global value for local-global string options
" 19e: Setting again string global-local (to buffer) option"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
noa setglobal tags=tag_global " Reset global and local value (without triggering autocmd)
noa setlocal tags=tag_local
@@ -795,8 +795,8 @@ func Test_OptionSet()
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19f: Setting string local-global (to buffer) option to an empty string"
" Note: v:option_old is the old global value for local-global string options
" 19f: Setting string global-local (to buffer) option to an empty string"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
noa set tags=tag_global " Reset global and local value (without triggering autocmd)
noa setlocal tags= " empty string
@@ -833,7 +833,7 @@ func Test_OptionSet()
call assert_equal(g:opt[0], g:opt[1])
" 20e: Setting again string local (to buffer) option"
" Note: v:option_old is the old global value for local-global string options
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
noa setglobal spelllang=spellglobal " Reset global and local value (without triggering autocmd)
noa setlocal spelllang=spelllocal
@@ -843,36 +843,36 @@ func Test_OptionSet()
call assert_equal(g:opt[0], g:opt[1])
" 21a: Setting string local-global (to window) option"
" 21a: Setting string global-local (to window) option"
let oldval = &statusline
let g:options = [['statusline', oldval, oldval, oldval, 'foo', 'global', 'set']]
set statusline=foo
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21b: Resetting string local-global (to window) option"
" Note: v:option_old is the old global value for local-global string options
" 21b: Resetting string global-local (to window) option"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
let g:options = [['statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
set statusline&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21c: Setting global string local-global (to window) option"
" 21c: Setting global string global-local (to window) option"
let g:options = [['statusline', oldval, '', oldval, 'bar', 'global', 'setglobal']]
setglobal statusline=bar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21d: Setting local string local-global (to window) option"
" 21d: Setting local string global-local (to window) option"
noa set statusline& " Reset global and local value (without triggering autocmd)
let g:options = [['statusline', oldval, oldval, '', 'baz', 'local', 'setlocal']]
setlocal statusline=baz
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21e: Setting again string local-global (to window) option"
" Note: v:option_old is the old global value for local-global string options
" 21e: Setting again string global-local (to window) option"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
noa setglobal statusline=bar " Reset global and local value (without triggering autocmd)
noa setlocal statusline=baz
@@ -917,7 +917,7 @@ func Test_OptionSet()
call assert_equal(g:opt[0], g:opt[1])
" 23a: Setting global number local option"
" 23a: Setting global number global option"
noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
noa setlocal cmdheight=1 " Sets the global(!) value!
let g:options = [['cmdheight', '1', '', '1', '2', 'global', 'setglobal']]
@@ -1041,7 +1041,7 @@ func Test_OptionSet()
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 27d: Ssettin again global number local (to window) option"
" 27d: Setting again global number local (to window) option"
noa set foldcolumn=8 " Reset global and local value (without triggering autocmd)
let g:options = [['foldcolumn', '8', '8', '8', '2', 'global', 'set']]
set foldcolumn=2

View File

@@ -305,6 +305,11 @@ func Test_getcompletion()
let l = getcompletion('NoMatch', 'dir')
call assert_equal([], l)
if glob('~/*') !=# ''
let l = getcompletion('~/', 'dir')
call assert_true(l[0][0] ==# '~')
endif
let l = getcompletion('exe', 'expression')
call assert_true(index(l, 'executable(') >= 0)
let l = getcompletion('kill', 'expression')
@@ -418,6 +423,16 @@ func Test_getcompletion()
let l = getcompletion('call paint', 'cmdline')
call assert_equal([], l)
func T(a, c, p)
return "oneA\noneB\noneC"
endfunc
command -nargs=1 -complete=custom,T MyCmd
let l = getcompletion('MyCmd ', 'cmdline')
call assert_equal(['oneA', 'oneB', 'oneC'], l)
delcommand MyCmd
delfunc T
" For others test if the name is recognized.
let names = ['buffer', 'environment', 'file_in_path', 'mapping', 'tag', 'tag_listfiles', 'user']
if has('cmdline_hist')

View File

@@ -1959,12 +1959,8 @@ endfunc
" Test for ModeChanged pattern
func Test_mode_changes()
let g:count = 0
func! DoIt()
let g:count += 1
endfunc
let g:index = 0
let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'n', 'V', 'v', 'n']
let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'i', 'ix', 'i', 'ic', 'i', 'n', 'no', 'n', 'V', 'v', 's', 'n']
func! TestMode()
call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode"))
call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode"))
@@ -1973,13 +1969,15 @@ func Test_mode_changes()
endfunc
au ModeChanged * :call TestMode()
au ModeChanged n:* :call DoIt()
call feedkeys("i\<esc>vV\<esc>", 'tnix')
call assert_equal(2, g:count)
let g:n_to_any = 0
au ModeChanged n:* let g:n_to_any += 1
call feedkeys("i\<esc>vVca\<CR>\<C-X>\<C-L>\<esc>ggdG", 'tnix')
au ModeChanged V:v :call DoIt()
call feedkeys("Vv\<esc>", 'tnix')
call assert_equal(4, g:count)
let g:V_to_v = 0
au ModeChanged V:v let g:V_to_v += 1
call feedkeys("Vv\<C-G>\<esc>", 'tnix')
call assert_equal(len(filter(g:mode_seq[1:], {idx, val -> val == 'n'})), g:n_to_any)
call assert_equal(1, g:V_to_v)
call assert_equal(len(g:mode_seq) - 1, g:index)
let g:n_to_i = 0
@@ -2008,12 +2006,32 @@ func Test_mode_changes()
call assert_equal(2, g:i_to_any)
call assert_equal(3, g:nori_to_any)
if has('terminal')
let g:mode_seq += ['c', 'n', 't', 'nt', 'c', 'nt', 'n']
call feedkeys(":term\<CR>\<C-W>N:bd!\<CR>", 'tnix')
call assert_equal(len(g:mode_seq) - 1, g:index)
call assert_equal(1, g:n_to_i)
call assert_equal(1, g:n_to_niI)
call assert_equal(1, g:niI_to_i)
call assert_equal(2, g:nany_to_i)
call assert_equal(1, g:i_to_n)
call assert_equal(2, g:i_to_any)
call assert_equal(5, g:nori_to_any)
endif
au! ModeChanged
delfunc TestMode
unlet! g:mode_seq
unlet! g:index
delfunc DoIt
unlet! g:count
unlet! g:n_to_any
unlet! g:V_to_v
unlet! g:n_to_i
unlet! g:n_to_niI
unlet! g:niI_to_i
unlet! g:nany_to_i
unlet! g:i_to_n
unlet! g:nori_to_any
unlet! g:i_to_any
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -145,6 +145,28 @@ func Test_quoteplus()
let @+ = quoteplus_saved
endfunc
func Test_gui_read_stdin()
CheckUnix
call writefile(['some', 'lines'], 'Xstdin')
let script =<< trim END
call writefile(getline(1, '$'), 'XstdinOK')
qa!
END
call writefile(script, 'Xscript')
" Cannot use --not-a-term here, the "reading from stdin" message would not be
" displayed.
let vimcmd = substitute(GetVimCommand(), '--not-a-term', '', '')
call system('cat Xstdin | ' .. vimcmd .. ' -f -g -S Xscript -')
call assert_equal(['some', 'lines'], readfile('XstdinOK'))
call delete('Xstdin')
call delete('XstdinOK')
call delete('Xscript')
endfunc
func Test_set_background()
let background_saved = &background

View File

@@ -786,6 +786,23 @@ func Test_vimgreptitle()
augroup! QfBufWinEnter
endfunc
func Test_bufwinenter_once()
augroup QfBufWinEnter
au!
au BufWinEnter * let g:got_afile ..= 'got ' .. expand('<afile>')
augroup END
let g:got_afile = ''
copen
call assert_equal('got quickfix', g:got_afile)
cclose
unlet g:got_afile
augroup QfBufWinEnter
au!
augroup END
augroup! QfBufWinEnter
endfunc
func XqfTitleTests(cchar)
call s:setup_commands(a:cchar)

View File

@@ -185,6 +185,16 @@ func Test_setcellwidths()
call assert_fails('call setcellwidths([[0x111, 0x122, 1], [0x122, 0x123, 2]])', 'E1113:')
call assert_fails('call setcellwidths([[0x33, 0x44, 2]])', 'E1114:')
set listchars=tab:--\\u2192
call assert_fails('call setcellwidths([[0x2192, 0x2192, 2]])', 'E834:')
set fillchars=stl:\\u2501
call assert_fails('call setcellwidths([[0x2501, 0x2501, 2]])', 'E835:')
set listchars&
set fillchars&
call setcellwidths([])
endfunc
func Test_print_overlong()

View File

@@ -213,6 +213,46 @@ func Test_xxd()
call delete('XXDfile')
endfunc
func Test_xxd_patch()
let cmd1 = 'silent !' .. s:xxd_cmd .. ' -r Xxxdin Xxxdfile'
let cmd2 = 'silent !' .. s:xxd_cmd .. ' -g1 Xxxdfile > Xxxdout'
call writefile(["2: 41 41", "8: 42 42"], 'Xxxdin')
call writefile(['::::::::'], 'Xxxdfile')
exe cmd1
exe cmd2
call assert_equal(['00000000: 3a 3a 41 41 3a 3a 3a 3a 42 42 ::AA::::BB'], readfile('Xxxdout'))
call writefile(["2: 43 43 ", "8: 44 44"], 'Xxxdin')
exe cmd1
exe cmd2
call assert_equal(['00000000: 3a 3a 43 43 3a 3a 3a 3a 44 44 ::CC::::DD'], readfile('Xxxdout'))
call writefile(["2: 45 45 ", "8: 46 46"], 'Xxxdin')
exe cmd1
exe cmd2
call assert_equal(['00000000: 3a 3a 45 45 3a 3a 3a 3a 46 46 ::EE::::FF'], readfile('Xxxdout'))
call writefile(["2: 41 41", "08: 42 42"], 'Xxxdin')
call writefile(['::::::::'], 'Xxxdfile')
exe cmd1
exe cmd2
call assert_equal(['00000000: 3a 3a 41 41 3a 3a 3a 3a 42 42 ::AA::::BB'], readfile('Xxxdout'))
call writefile(["2: 43 43 ", "09: 44 44"], 'Xxxdin')
exe cmd1
exe cmd2
call assert_equal(['00000000: 3a 3a 43 43 3a 3a 3a 3a 42 44 44 ::CC::::BDD'], readfile('Xxxdout'))
call writefile(["2: 45 45 ", "0a: 46 46"], 'Xxxdin')
exe cmd1
exe cmd2
call assert_equal(['00000000: 3a 3a 45 45 3a 3a 3a 3a 42 44 46 46 ::EE::::BDFF'], readfile('Xxxdout'))
call delete('Xxxdin')
call delete('Xxxdfile')
call delete('Xxxdout')
endfunc
" Various ways with wrong arguments that trigger the usage output.
func Test_xxd_usage()
for arg in ['-c', '-g', '-o', '-s', '-l', '-X', 'one two three']

View File

@@ -757,6 +757,28 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
3555,
/**/
3554,
/**/
3553,
/**/
3552,
/**/
3551,
/**/
3550,
/**/
3549,
/**/
3548,
/**/
3547,
/**/
3546,
/**/
3545,
/**/
3544,
/**/

View File

@@ -977,6 +977,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define READ_DUMMY 0x10 // reading into a dummy buffer
#define READ_KEEP_UNDO 0x20 // keep undo info
#define READ_FIFO 0x40 // read from fifo or socket
#define READ_NOWINENTER 0x80 // do not trigger BufWinEnter
// Values for change_indent()
#define INDENT_SET 1 // set indent
@@ -1043,6 +1044,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define ECMD_FORCEIT 0x08 // ! used in Ex command
#define ECMD_ADDBUF 0x10 // don't edit, just add to buffer list
#define ECMD_ALTBUF 0x20 // like ECMD_ADDBUF and set the alternate file
#define ECMD_NOWINENTER 0x40 // do not trigger BufWinEnter
// for lnum argument in do_ecmd()
#define ECMD_LASTL (linenr_T)0 // use last position in loaded file

View File

@@ -131,7 +131,7 @@ extern void perror __P((char *));
extern long int strtol();
extern long int ftell();
char version[] = "xxd 2020-02-04 by Juergen Weigert et al.";
char version[] = "xxd 2021-10-22 by Juergen Weigert et al.";
#ifdef WIN32
char osver[] = " (Win32)";
#else
@@ -188,13 +188,6 @@ char osver[] = "";
# endif
#endif
/* Let's collect some prototypes */
/* CodeWarrior is really picky about missing prototypes */
static void exit_with_usage __P((void));
static void die __P((int));
static int huntype __P((FILE *, FILE *, FILE *, int, int, long));
static void xxdline __P((FILE *, char *, int));
#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
#define COLS 256 /* change here, if you ever need more columns */
#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
@@ -245,13 +238,20 @@ exit_with_usage(void)
}
static void
die(int ret)
perror_exit(int ret)
{
fprintf(stderr, "%s: ", pname);
perror(NULL);
exit(ret);
}
static void
error_exit(int ret, char *msg)
{
fprintf(stderr, "%s: %s\n", pname, msg);
exit(ret);
}
/*
* Max. cols binary characters are decoded from the input stream per line.
* Two adjacent garbage characters after evaluated data delimit valid data.
@@ -263,7 +263,6 @@ die(int ret)
huntype(
FILE *fpi,
FILE *fpo,
FILE *fperr,
int cols,
int hextype,
long base_off)
@@ -316,26 +315,22 @@ huntype(
if (base_off + want_off != have_off)
{
if (fflush(fpo) != 0)
die(3);
perror_exit(3);
#ifdef TRY_SEEK
c = fseek(fpo, base_off + want_off - have_off, 1);
if (c >= 0)
if (fseek(fpo, base_off + want_off - have_off, 1) >= 0)
have_off = base_off + want_off;
#endif
if (base_off + want_off < have_off)
{
fprintf(fperr, "%s: sorry, cannot seek backwards.\n", pname);
return 5;
}
error_exit(5, "sorry, cannot seek backwards.");
for (; have_off < base_off + want_off; have_off++)
if (putc(0, fpo) == EOF)
die(3);
perror_exit(3);
}
if (n2 >= 0 && n1 >= 0)
{
if (putc((n2 << 4) | n1, fpo) == EOF)
die(3);
perror_exit(3);
have_off++;
want_off++;
n1 = -1;
@@ -349,24 +344,28 @@ huntype(
if (n1 < 0 && n2 < 0 && n3 < 0)
{
/* already stumbled into garbage, skip line, wait and see */
while (c != '\n' && c != EOF)
c = getc(fpi);
if (c == EOF && ferror(fpi))
perror_exit(2);
}
if (c == '\n')
{
if (!hextype)
want_off = 0;
while ((c = getc(fpi)) != '\n' && c != EOF)
;
if (c == EOF && ferror(fpi))
die(2);
p = cols;
ign_garb = 1;
}
}
if (fflush(fpo) != 0)
die(3);
perror_exit(3);
#ifdef TRY_SEEK
fseek(fpo, 0L, 2);
#endif
if (fclose(fpo) != 0)
die(3);
perror_exit(3);
if (fclose(fpi) != 0)
die(2);
perror_exit(2);
return 0;
}
@@ -399,14 +398,14 @@ xxdline(FILE *fp, char *l, int nz)
zero_seen--;
if (zero_seen == 2)
if (fputs(z, fp) == EOF)
die(3);
perror_exit(3);
if (zero_seen > 2)
if (fputs("*\n", fp) == EOF)
die(3);
perror_exit(3);
}
if (nz >= 0 || zero_seen > 0)
if (fputs(l, fp) == EOF)
die(3);
perror_exit(3);
if (nz)
zero_seen = 0;
}
@@ -637,12 +636,7 @@ main(int argc, char *argv[])
if (octspergrp < 1 || octspergrp > cols)
octspergrp = cols;
else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
{
fprintf(stderr,
"%s: number of octets per group must be a power of 2 with -e.\n",
pname);
exit(1);
}
error_exit(1, "number of octets per group must be a power of 2 with -e.");
if (argc > 3)
exit_with_usage();
@@ -679,11 +673,8 @@ main(int argc, char *argv[])
if (revert)
{
if (hextype && (hextype != HEX_POSTSCRIPT))
{
fprintf(stderr, "%s: sorry, cannot revert this type of hexdump\n", pname);
return -1;
}
return huntype(fp, fpo, stderr, cols, hextype,
error_exit(-1, "sorry, cannot revert this type of hexdump");
return huntype(fp, fpo, cols, hextype,
negseek ? -seekoff : seekoff);
}
@@ -695,10 +686,7 @@ main(int argc, char *argv[])
else
e = fseek(fp, negseek ? -seekoff : seekoff, negseek ? 2 : 0);
if (e < 0 && negseek)
{
fprintf(stderr, "%s: sorry cannot seek.\n", pname);
return 4;
}
error_exit(4, "sorry cannot seek.");
if (e >= 0)
seekoff = ftell(fp);
else
@@ -711,12 +699,11 @@ main(int argc, char *argv[])
{
if (ferror(fp))
{
die(2);
perror_exit(2);
}
else
{
fprintf(stderr, "%s: sorry cannot seek.\n", pname);
return 4;
error_exit(4, "sorry cannot seek.");
}
}
}
@@ -727,12 +714,12 @@ main(int argc, char *argv[])
if (fp != stdin)
{
if (fprintf(fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : "") < 0)
die(3);
perror_exit(3);
for (e = 0; (c = argv[1][e]) != 0; e++)
if (putc(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo) == EOF)
die(3);
perror_exit(3);
if (fputs("[] = {\n", fpo) == EOF)
die(3);
perror_exit(3);
}
p = 0;
@@ -741,32 +728,32 @@ main(int argc, char *argv[])
{
if (fprintf(fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
(p % cols) ? ", " : &",\n "[2*!p], c) < 0)
die(3);
perror_exit(3);
p++;
}
if (c == EOF && ferror(fp))
die(2);
perror_exit(2);
if (p && fputs("\n", fpo) == EOF)
die(3);
perror_exit(3);
if (fputs(&"};\n"[3 * (fp == stdin)], fpo) == EOF)
die(3);
perror_exit(3);
if (fp != stdin)
{
if (fprintf(fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : "") < 0)
die(3);
perror_exit(3);
for (e = 0; (c = argv[1][e]) != 0; e++)
if (putc(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo) == EOF)
die(3);
perror_exit(3);
if (fprintf(fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p) < 0)
die(3);
perror_exit(3);
}
if (fclose(fp))
die(2);
perror_exit(2);
if (fclose(fpo))
die(3);
perror_exit(3);
return 0;
}
@@ -778,24 +765,24 @@ main(int argc, char *argv[])
{
if (putc(hexx[(e >> 4) & 0xf], fpo) == EOF
|| putc(hexx[e & 0xf], fpo) == EOF)
die(3);
perror_exit(3);
n++;
if (!--p)
{
if (putc('\n', fpo) == EOF)
die(3);
perror_exit(3);
p = cols;
}
}
if (e == EOF && ferror(fp))
die(2);
perror_exit(2);
if (p < cols)
if (putc('\n', fpo) == EOF)
die(3);
perror_exit(3);
if (fclose(fp))
die(2);
perror_exit(2);
if (fclose(fpo))
die(3);
perror_exit(3);
return 0;
}
@@ -860,7 +847,7 @@ main(int argc, char *argv[])
}
}
if (e == EOF && ferror(fp))
die(2);
perror_exit(2);
if (p)
{
l[c = (addrlen + 3 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
@@ -870,9 +857,9 @@ main(int argc, char *argv[])
xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
if (fclose(fp))
die(2);
perror_exit(2);
if (fclose(fpo))
die(3);
perror_exit(3);
return 0;
}