diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index ee844c4887..ee4d811e38 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2358,6 +2358,7 @@ test_alloc_fail({id}, {countdown}, {repeat}) test_autochdir() none enable 'autochdir' during startup test_disable_char_avail({expr}) none test without typeahead test_garbagecollect_now() none free memory right now for testing +test_ignore_error({expr}) none ignore a specific error test_null_channel() Channel null value for testing test_null_dict() Dict null value for testing test_null_job() Job null value for testing @@ -7784,6 +7785,15 @@ test_garbagecollect_now() *test_garbagecollect_now()* internally, and |v:testing| must have been set before calling any function. +test_ignore_error({expr}) *test_ignore_error()* + Ignore any error containing {expr}. A normal message is given + instead. + This is only meant to be used in tests, where catching the + error with try/catch cannot be used (because it skips over + following code). + {expr} is used literally, not as a pattern. + There is currently no way to revert this. + test_null_channel() *test_null_channel()* Return a Channel that is null. Only useful for testing. {only available when compiled with the +channel feature} diff --git a/src/arabic.c b/src/arabic.c index fa5e940def..4ad2c6e89f 100644 --- a/src/arabic.c +++ b/src/arabic.c @@ -200,126 +200,48 @@ A_is_f(int cur_c) static int chg_c_a2s(int cur_c) { - int tempc; - switch (cur_c) { - case a_HAMZA: - tempc = a_s_HAMZA; - break; - case a_ALEF_MADDA: - tempc = a_s_ALEF_MADDA; - break; - case a_ALEF_HAMZA_ABOVE: - tempc = a_s_ALEF_HAMZA_ABOVE; - break; - case a_WAW_HAMZA: - tempc = a_s_WAW_HAMZA; - break; - case a_ALEF_HAMZA_BELOW: - tempc = a_s_ALEF_HAMZA_BELOW; - break; - case a_YEH_HAMZA: - tempc = a_s_YEH_HAMZA; - break; - case a_ALEF: - tempc = a_s_ALEF; - break; - case a_TEH_MARBUTA: - tempc = a_s_TEH_MARBUTA; - break; - case a_DAL: - tempc = a_s_DAL; - break; - case a_THAL: - tempc = a_s_THAL; - break; - case a_REH: - tempc = a_s_REH; - break; - case a_ZAIN: - tempc = a_s_ZAIN; - break; - case a_TATWEEL: /* exceptions */ - tempc = cur_c; - break; - case a_WAW: - tempc = a_s_WAW; - break; - case a_ALEF_MAKSURA: - tempc = a_s_ALEF_MAKSURA; - break; - case a_BEH: - tempc = a_s_BEH; - break; - case a_TEH: - tempc = a_s_TEH; - break; - case a_THEH: - tempc = a_s_THEH; - break; - case a_JEEM: - tempc = a_s_JEEM; - break; - case a_HAH: - tempc = a_s_HAH; - break; - case a_KHAH: - tempc = a_s_KHAH; - break; - case a_SEEN: - tempc = a_s_SEEN; - break; - case a_SHEEN: - tempc = a_s_SHEEN; - break; - case a_SAD: - tempc = a_s_SAD; - break; - case a_DAD: - tempc = a_s_DAD; - break; - case a_TAH: - tempc = a_s_TAH; - break; - case a_ZAH: - tempc = a_s_ZAH; - break; - case a_AIN: - tempc = a_s_AIN; - break; - case a_GHAIN: - tempc = a_s_GHAIN; - break; - case a_FEH: - tempc = a_s_FEH; - break; - case a_QAF: - tempc = a_s_QAF; - break; - case a_KAF: - tempc = a_s_KAF; - break; - case a_LAM: - tempc = a_s_LAM; - break; - case a_MEEM: - tempc = a_s_MEEM; - break; - case a_NOON: - tempc = a_s_NOON; - break; - case a_HEH: - tempc = a_s_HEH; - break; - case a_YEH: - tempc = a_s_YEH; - break; - default: - tempc = 0; + case a_HAMZA: return a_s_HAMZA; + case a_ALEF_MADDA: return a_s_ALEF_MADDA; + case a_ALEF_HAMZA_ABOVE: return a_s_ALEF_HAMZA_ABOVE; + case a_WAW_HAMZA: return a_s_WAW_HAMZA; + case a_ALEF_HAMZA_BELOW: return a_s_ALEF_HAMZA_BELOW; + case a_YEH_HAMZA: return a_s_YEH_HAMZA; + case a_ALEF: return a_s_ALEF; + case a_TEH_MARBUTA: return a_s_TEH_MARBUTA; + case a_DAL: return a_s_DAL; + case a_THAL: return a_s_THAL; + case a_REH: return a_s_REH; + case a_ZAIN: return a_s_ZAIN; + case a_TATWEEL: return cur_c; /* exceptions */ + case a_WAW: return a_s_WAW; + case a_ALEF_MAKSURA: return a_s_ALEF_MAKSURA; + case a_BEH: return a_s_BEH; + case a_TEH: return a_s_TEH; + case a_THEH: return a_s_THEH; + case a_JEEM: return a_s_JEEM; + case a_HAH: return a_s_HAH; + case a_KHAH: return a_s_KHAH; + case a_SEEN: return a_s_SEEN; + case a_SHEEN: return a_s_SHEEN; + case a_SAD: return a_s_SAD; + case a_DAD: return a_s_DAD; + case a_TAH: return a_s_TAH; + case a_ZAH: return a_s_ZAH; + case a_AIN: return a_s_AIN; + case a_GHAIN: return a_s_GHAIN; + case a_FEH: return a_s_FEH; + case a_QAF: return a_s_QAF; + case a_KAF: return a_s_KAF; + case a_LAM: return a_s_LAM; + case a_MEEM: return a_s_MEEM; + case a_NOON: return a_s_NOON; + case a_HEH: return a_s_HEH; + case a_YEH: return a_s_YEH; } - return tempc; + return 0; } @@ -329,126 +251,62 @@ chg_c_a2s(int cur_c) static int chg_c_a2i(int cur_c) { - int tempc; - switch (cur_c) { - case a_YEH_HAMZA: - tempc = a_i_YEH_HAMZA; - break; + case a_YEH_HAMZA: return a_i_YEH_HAMZA; case a_HAMZA: /* exceptions */ - tempc = a_s_HAMZA; - break; + return a_s_HAMZA; case a_ALEF_MADDA: /* exceptions */ - tempc = a_s_ALEF_MADDA; - break; + return a_s_ALEF_MADDA; case a_ALEF_HAMZA_ABOVE: /* exceptions */ - tempc = a_s_ALEF_HAMZA_ABOVE; - break; + return a_s_ALEF_HAMZA_ABOVE; case a_WAW_HAMZA: /* exceptions */ - tempc = a_s_WAW_HAMZA; - break; + return a_s_WAW_HAMZA; case a_ALEF_HAMZA_BELOW: /* exceptions */ - tempc = a_s_ALEF_HAMZA_BELOW; - break; + return a_s_ALEF_HAMZA_BELOW; case a_ALEF: /* exceptions */ - tempc = a_s_ALEF; - break; + return a_s_ALEF; case a_TEH_MARBUTA: /* exceptions */ - tempc = a_s_TEH_MARBUTA; - break; + return a_s_TEH_MARBUTA; case a_DAL: /* exceptions */ - tempc = a_s_DAL; - break; + return a_s_DAL; case a_THAL: /* exceptions */ - tempc = a_s_THAL; - break; + return a_s_THAL; case a_REH: /* exceptions */ - tempc = a_s_REH; - break; + return a_s_REH; case a_ZAIN: /* exceptions */ - tempc = a_s_ZAIN; - break; + return a_s_ZAIN; case a_TATWEEL: /* exceptions */ - tempc = cur_c; - break; + return cur_c; case a_WAW: /* exceptions */ - tempc = a_s_WAW; - break; + return a_s_WAW; case a_ALEF_MAKSURA: /* exceptions */ - tempc = a_s_ALEF_MAKSURA; - break; - case a_BEH: - tempc = a_i_BEH; - break; - case a_TEH: - tempc = a_i_TEH; - break; - case a_THEH: - tempc = a_i_THEH; - break; - case a_JEEM: - tempc = a_i_JEEM; - break; - case a_HAH: - tempc = a_i_HAH; - break; - case a_KHAH: - tempc = a_i_KHAH; - break; - case a_SEEN: - tempc = a_i_SEEN; - break; - case a_SHEEN: - tempc = a_i_SHEEN; - break; - case a_SAD: - tempc = a_i_SAD; - break; - case a_DAD: - tempc = a_i_DAD; - break; - case a_TAH: - tempc = a_i_TAH; - break; - case a_ZAH: - tempc = a_i_ZAH; - break; - case a_AIN: - tempc = a_i_AIN; - break; - case a_GHAIN: - tempc = a_i_GHAIN; - break; - case a_FEH: - tempc = a_i_FEH; - break; - case a_QAF: - tempc = a_i_QAF; - break; - case a_KAF: - tempc = a_i_KAF; - break; - case a_LAM: - tempc = a_i_LAM; - break; - case a_MEEM: - tempc = a_i_MEEM; - break; - case a_NOON: - tempc = a_i_NOON; - break; - case a_HEH: - tempc = a_i_HEH; - break; - case a_YEH: - tempc = a_i_YEH; - break; - default: - tempc = 0; + return a_s_ALEF_MAKSURA; + case a_BEH: return a_i_BEH; + case a_TEH: return a_i_TEH; + case a_THEH: return a_i_THEH; + case a_JEEM: return a_i_JEEM; + case a_HAH: return a_i_HAH; + case a_KHAH: return a_i_KHAH; + case a_SEEN: return a_i_SEEN; + case a_SHEEN: return a_i_SHEEN; + case a_SAD: return a_i_SAD; + case a_DAD: return a_i_DAD; + case a_TAH: return a_i_TAH; + case a_ZAH: return a_i_ZAH; + case a_AIN: return a_i_AIN; + case a_GHAIN: return a_i_GHAIN; + case a_FEH: return a_i_FEH; + case a_QAF: return a_i_QAF; + case a_KAF: return a_i_KAF; + case a_LAM: return a_i_LAM; + case a_MEEM: return a_i_MEEM; + case a_NOON: return a_i_NOON; + case a_HEH: return a_i_HEH; + case a_YEH: return a_i_YEH; } - return tempc; + return 0; } @@ -458,126 +316,48 @@ chg_c_a2i(int cur_c) static int chg_c_a2m(int cur_c) { - int tempc; - switch (cur_c) { - case a_HAMZA: /* exception */ - tempc = a_s_HAMZA; - break; - case a_ALEF_MADDA: /* exception */ - tempc = a_f_ALEF_MADDA; - break; - case a_ALEF_HAMZA_ABOVE: /* exception */ - tempc = a_f_ALEF_HAMZA_ABOVE; - break; - case a_WAW_HAMZA: /* exception */ - tempc = a_f_WAW_HAMZA; - break; - case a_ALEF_HAMZA_BELOW: /* exception */ - tempc = a_f_ALEF_HAMZA_BELOW; - break; - case a_YEH_HAMZA: - tempc = a_m_YEH_HAMZA; - break; - case a_ALEF: /* exception */ - tempc = a_f_ALEF; - break; - case a_BEH: - tempc = a_m_BEH; - break; - case a_TEH_MARBUTA: /* exception */ - tempc = a_f_TEH_MARBUTA; - break; - case a_TEH: - tempc = a_m_TEH; - break; - case a_THEH: - tempc = a_m_THEH; - break; - case a_JEEM: - tempc = a_m_JEEM; - break; - case a_HAH: - tempc = a_m_HAH; - break; - case a_KHAH: - tempc = a_m_KHAH; - break; - case a_DAL: /* exception */ - tempc = a_f_DAL; - break; - case a_THAL: /* exception */ - tempc = a_f_THAL; - break; - case a_REH: /* exception */ - tempc = a_f_REH; - break; - case a_ZAIN: /* exception */ - tempc = a_f_ZAIN; - break; - case a_SEEN: - tempc = a_m_SEEN; - break; - case a_SHEEN: - tempc = a_m_SHEEN; - break; - case a_SAD: - tempc = a_m_SAD; - break; - case a_DAD: - tempc = a_m_DAD; - break; - case a_TAH: - tempc = a_m_TAH; - break; - case a_ZAH: - tempc = a_m_ZAH; - break; - case a_AIN: - tempc = a_m_AIN; - break; - case a_GHAIN: - tempc = a_m_GHAIN; - break; - case a_TATWEEL: /* exception */ - tempc = cur_c; - break; - case a_FEH: - tempc = a_m_FEH; - break; - case a_QAF: - tempc = a_m_QAF; - break; - case a_KAF: - tempc = a_m_KAF; - break; - case a_LAM: - tempc = a_m_LAM; - break; - case a_MEEM: - tempc = a_m_MEEM; - break; - case a_NOON: - tempc = a_m_NOON; - break; - case a_HEH: - tempc = a_m_HEH; - break; - case a_WAW: /* exception */ - tempc = a_f_WAW; - break; - case a_ALEF_MAKSURA: /* exception */ - tempc = a_f_ALEF_MAKSURA; - break; - case a_YEH: - tempc = a_m_YEH; - break; - default: - tempc = 0; + case a_HAMZA: return a_s_HAMZA; /* exception */ + case a_ALEF_MADDA: return a_f_ALEF_MADDA; /* exception */ + case a_ALEF_HAMZA_ABOVE: return a_f_ALEF_HAMZA_ABOVE; /* exception */ + case a_WAW_HAMZA: return a_f_WAW_HAMZA; /* exception */ + case a_ALEF_HAMZA_BELOW: return a_f_ALEF_HAMZA_BELOW; /* exception */ + case a_YEH_HAMZA: return a_m_YEH_HAMZA; + case a_ALEF: return a_f_ALEF; /* exception */ + case a_BEH: return a_m_BEH; + case a_TEH_MARBUTA: return a_f_TEH_MARBUTA; /* exception */ + case a_TEH: return a_m_TEH; + case a_THEH: return a_m_THEH; + case a_JEEM: return a_m_JEEM; + case a_HAH: return a_m_HAH; + case a_KHAH: return a_m_KHAH; + case a_DAL: return a_f_DAL; /* exception */ + case a_THAL: return a_f_THAL; /* exception */ + case a_REH: return a_f_REH; /* exception */ + case a_ZAIN: return a_f_ZAIN; /* exception */ + case a_SEEN: return a_m_SEEN; + case a_SHEEN: return a_m_SHEEN; + case a_SAD: return a_m_SAD; + case a_DAD: return a_m_DAD; + case a_TAH: return a_m_TAH; + case a_ZAH: return a_m_ZAH; + case a_AIN: return a_m_AIN; + case a_GHAIN: return a_m_GHAIN; + case a_TATWEEL: return cur_c; /* exception */ + case a_FEH: return a_m_FEH; + case a_QAF: return a_m_QAF; + case a_KAF: return a_m_KAF; + case a_LAM: return a_m_LAM; + case a_MEEM: return a_m_MEEM; + case a_NOON: return a_m_NOON; + case a_HEH: return a_m_HEH; + case a_WAW: return a_f_WAW; /* exception */ + case a_ALEF_MAKSURA: return a_f_ALEF_MAKSURA; /* exception */ + case a_YEH: return a_m_YEH; } - return tempc; + return 0; } diff --git a/src/channel.c b/src/channel.c index 5bb7060a9f..96b6f215a5 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1987,7 +1987,7 @@ channel_parse_json(channel_T *channel, ch_part_T part) * more (but still incomplete): set a deadline of 100 msec. */ ch_logn(channel, "Incomplete message (%d bytes) - wait 100 msec for more", - buflen); + (int)buflen); reader.js_used = 0; chanpart->ch_wait_len = buflen; #ifdef WIN32 @@ -3324,6 +3324,7 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout) channel_read(channel, part, "channel_read_block"); } + /* We have a complete message now. */ if (mode == MODE_RAW) { msg = channel_get_all(channel, part); diff --git a/src/edit.c b/src/edit.c index cf412704f3..79062d9f4a 100644 --- a/src/edit.c +++ b/src/edit.c @@ -186,7 +186,7 @@ static int ins_compl_pum_key(int c); static int ins_compl_key2count(int c); static int ins_compl_use_match(int c); static int ins_complete(int c, int enable_pum); -static void show_pum(int save_w_wrow); +static void show_pum(int prev_w_wrow, int prev_w_leftcol); static unsigned quote_meta(char_u *dest, char_u *str, int len); #endif /* FEAT_INS_EXPAND */ @@ -2827,6 +2827,7 @@ completeopt_was_set(void) set_completion(colnr_T startcol, list_T *list) { int save_w_wrow = curwin->w_wrow; + int save_w_leftcol = curwin->w_leftcol; /* If already doing completions stop it. */ if (ctrl_x_mode != 0) @@ -2867,7 +2868,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); + show_pum(save_w_wrow, save_w_leftcol); out_flush(); } @@ -5110,6 +5111,7 @@ ins_complete(int c, int enable_pum) colnr_T curs_col; /* cursor column */ int n; int save_w_wrow; + int save_w_leftcol; int insert_match; int save_did_ai = did_ai; @@ -5553,6 +5555,7 @@ ins_complete(int c, int enable_pum) * Find next match (and following matches). */ save_w_wrow = curwin->w_wrow; + save_w_leftcol = curwin->w_leftcol; n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match, FALSE); /* may undisplay the popup menu */ @@ -5705,9 +5708,8 @@ ins_complete(int c, int enable_pum) /* Show the popup menu, unless we got interrupted. */ if (enable_pum && !compl_interrupted) - { - show_pum(save_w_wrow); - } + show_pum(save_w_wrow, save_w_leftcol); + compl_was_interrupted = compl_interrupted; compl_interrupted = FALSE; @@ -5715,21 +5717,22 @@ ins_complete(int c, int enable_pum) } static void -show_pum(int save_w_wrow) +show_pum(int prev_w_wrow, int prev_w_leftcol) { - /* RedrawingDisabled may be set when invoked through complete(). */ - int n = RedrawingDisabled; + /* RedrawingDisabled may be set when invoked through complete(). */ + int n = RedrawingDisabled; - RedrawingDisabled = 0; + RedrawingDisabled = 0; - /* If the cursor moved we need to remove the pum first. */ - setcursor(); - if (save_w_wrow != curwin->w_wrow) - ins_compl_del_pum(); + /* If the cursor moved or the display scrolled we need to remove the pum + * first. */ + setcursor(); + if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol) + ins_compl_del_pum(); - ins_compl_show_pum(); - setcursor(); - RedrawingDisabled = n; + ins_compl_show_pum(); + setcursor(); + RedrawingDisabled = n; } /* diff --git a/src/evalfunc.c b/src/evalfunc.c index 9339439ed5..0f67070025 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -389,6 +389,7 @@ static void f_test_alloc_fail(typval_T *argvars, typval_T *rettv); static void f_test_autochdir(typval_T *argvars, typval_T *rettv); static void f_test_disable_char_avail(typval_T *argvars, typval_T *rettv); static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv); +static void f_test_ignore_error(typval_T *argvars, typval_T *rettv); #ifdef FEAT_JOB_CHANNEL static void f_test_null_channel(typval_T *argvars, typval_T *rettv); #endif @@ -823,6 +824,7 @@ static struct fst {"test_autochdir", 0, 0, f_test_autochdir}, {"test_disable_char_avail", 1, 1, f_test_disable_char_avail}, {"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now}, + {"test_ignore_error", 1, 1, f_test_ignore_error}, #ifdef FEAT_JOB_CHANNEL {"test_null_channel", 0, 0, f_test_null_channel}, #endif @@ -12352,6 +12354,15 @@ f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED) garbage_collect(TRUE); } +/* + * "test_ignore_error()" function + */ + static void +f_test_ignore_error(typval_T *argvars, typval_T *rettv UNUSED) +{ + ignore_error_for_testing(get_tv_string(&argvars[0])); +} + #ifdef FEAT_JOB_CHANNEL static void f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv) diff --git a/src/fold.c b/src/fold.c index d3635a6d7b..cba1375159 100644 --- a/src/fold.c +++ b/src/fold.c @@ -1576,16 +1576,23 @@ foldMarkAdjustRecurse( { /* 5. fold is below line1 and contains line2; need to * correct nested folds too */ - foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, - line2 - fp->fd_top, amount, - amount_after + (fp->fd_top - top)); if (amount == MAXLNUM) { + foldMarkAdjustRecurse(&fp->fd_nested, + line1 - fp->fd_top, + line2 - fp->fd_top, + amount, + amount_after + (fp->fd_top - top)); fp->fd_len -= line2 - fp->fd_top + 1; fp->fd_top = line1; } else { + foldMarkAdjustRecurse(&fp->fd_nested, + line1 - fp->fd_top, + line2 - fp->fd_top, + amount, + amount_after - amount); fp->fd_len += amount_after - amount; fp->fd_top += amount; } diff --git a/src/memline.c b/src/memline.c index 01e8d5ba37..f9852e55bb 100644 --- a/src/memline.c +++ b/src/memline.c @@ -1863,7 +1863,7 @@ recover_names( else { #if defined(UNIX) || defined(WIN3264) - int len = STRLEN(dir_name); + int len = (int)STRLEN(dir_name); p = dir_name + len; if (after_pathsep(dir_name, p) && len > 1 && p[-1] == p[-2]) @@ -3924,7 +3924,7 @@ makeswapname( #endif #if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */ - int len = STRLEN(dir_name); + int len = (int)STRLEN(dir_name); s = dir_name + len; if (after_pathsep(dir_name, s) && len > 1 && s[-1] == s[-2]) diff --git a/src/message.c b/src/message.c index 1c47fa82cd..2733ce6a31 100644 --- a/src/message.c +++ b/src/message.c @@ -539,6 +539,31 @@ emsg_not_now(void) return FALSE; } +#ifdef FEAT_EVAL +static garray_T ignore_error_list = GA_EMPTY; + + void +ignore_error_for_testing(char_u *error) +{ + if (ignore_error_list.ga_itemsize == 0) + ga_init2(&ignore_error_list, sizeof(char_u *), 1); + + ga_add_string(&ignore_error_list, error); +} + + static int +ignore_error(char_u *msg) +{ + int i; + + for (i = 0; i < ignore_error_list.ga_len; ++i) + if (strstr((char *)msg, + (char *)((char_u **)(ignore_error_list.ga_data))[i]) != NULL) + return TRUE; + return FALSE; +} +#endif + #if !defined(HAVE_STRERROR) || defined(PROTO) /* * Replacement for perror() that behaves more or less like emsg() was called. @@ -577,6 +602,12 @@ emsg(char_u *s) if (emsg_not_now()) return TRUE; +#ifdef FEAT_EVAL + /* When testing some errors are turned into a normal message. */ + if (ignore_error(s)) + return msg(s); +#endif + called_emsg = TRUE; /* diff --git a/src/proto/message.pro b/src/proto/message.pro index c9d62c66e0..9a79f14a60 100644 --- a/src/proto/message.pro +++ b/src/proto/message.pro @@ -8,6 +8,7 @@ void trunc_string(char_u *s, char_u *buf, int room_in, int buflen); void reset_last_sourcing(void); void msg_source(int attr); int emsg_not_now(void); +void ignore_error_for_testing(char_u *error); void do_perror(char *msg); int emsg(char_u *s); int emsg2(char_u *s, char_u *a1); diff --git a/src/tag.c b/src/tag.c index 83890698fb..8621419db9 100644 --- a/src/tag.c +++ b/src/tag.c @@ -35,9 +35,10 @@ typedef struct tag_pointers } tagptrs_T; /* - * The matching tags are first stored in one of the ht_match[] hash tables. In + * The matching tags are first stored in one of the hash tables. In * which one depends on the priority of the match. - * At the end, all the matches from ht_match[] are concatenated, to make a list + * ht_match[] is used to find duplicates, ga_match[] to keep them in sequence. + * At the end, all the matches from ga_match[] are concatenated, to make a list * sorted on priority. */ #define MT_ST_CUR 0 /* static match in current file */ @@ -1339,7 +1340,8 @@ find_tags( #endif char_u *mfp; - hashtab_T ht_match[MT_COUNT]; + garray_T ga_match[MT_COUNT]; /* stores matches in sequence */ + hashtab_T ht_match[MT_COUNT]; /* stores matches by key */ hash_T hash = 0; int match_count = 0; /* number of matches found */ char_u **matches; @@ -1405,7 +1407,10 @@ find_tags( ebuf = alloc(LSIZE); #endif for (mtt = 0; mtt < MT_COUNT; ++mtt) + { + ga_init2(&ga_match[mtt], (int)sizeof(char_u *), 100); hash_init(&ht_match[mtt]); + } /* check for out of memory situation */ if (lbuf == NULL || tag_fname == NULL @@ -2213,7 +2218,7 @@ parse_line: } /* - * If a match is found, add it to ht_match[]. + * If a match is found, add it to ht_match[] and ga_match[]. */ if (match) { @@ -2271,7 +2276,7 @@ parse_line: } /* - * Add the found match in ht_match[mtt]. + * Add the found match in ht_match[mtt] and ga_match[mtt]. * Store the info we need later, which depends on the kind of * tags we are dealing with. */ @@ -2423,7 +2428,8 @@ parse_line: if (HASHITEM_EMPTY(hi)) { if (hash_add_item(&ht_match[mtt], hi, mfp, hash) - == FAIL) + == FAIL + || ga_grow(&ga_match[mtt], 1) != OK) { /* Out of memory! Just forget about the rest. */ retval = OK; @@ -2431,7 +2437,11 @@ parse_line: break; } else + { + ((char_u **)(ga_match[mtt].ga_data)) + [ga_match[mtt].ga_len++] = mfp; ++match_count; + } } else /* duplicate tag, drop it */ @@ -2533,7 +2543,7 @@ findtag_end: #endif /* - * Move the matches from the ht_match[] arrays into one list of + * Move the matches from the ga_match[] arrays into one list of * matches. When retval == FAIL, free the matches. */ if (retval == FAIL) @@ -2547,34 +2557,28 @@ findtag_end: match_count = 0; for (mtt = 0; mtt < MT_COUNT; ++mtt) { - hashitem_T *hi; - long_u todo; - - todo = (long)ht_match[mtt].ht_used; - for (hi = ht_match[mtt].ht_array; todo > 0; ++hi) + for (i = 0; i < ga_match[mtt].ga_len; ++i) { - if (!HASHITEM_EMPTY(hi)) + mfp = ((char_u **)(ga_match[mtt].ga_data))[i]; + if (matches == NULL) + vim_free(mfp); + else { - mfp = hi->hi_key; - if (matches == NULL) - vim_free(mfp); - else + if (!name_only) { - if (!name_only) - { - /* Change mtt back to zero-based. */ - *mfp = *mfp - 1; + /* Change mtt back to zero-based. */ + *mfp = *mfp - 1; - /* change the TAG_SEP back to NUL */ - for (p = mfp + 1; *p != NUL; ++p) - if (*p == TAG_SEP) - *p = NUL; - } - matches[match_count++] = (char_u *)mfp; + /* change the TAG_SEP back to NUL */ + for (p = mfp + 1; *p != NUL; ++p) + if (*p == TAG_SEP) + *p = NUL; } - todo--; + matches[match_count++] = (char_u *)mfp; } } + + ga_clear(&ga_match[mtt]); hash_clear(&ht_match[mtt]); } diff --git a/src/testdir/test_arabic.vim b/src/testdir/test_arabic.vim index b9e033462e..9a16833a4c 100644 --- a/src/testdir/test_arabic.vim +++ b/src/testdir/test_arabic.vim @@ -1,21 +1,23 @@ " Simplistic testing of Arabic mode. -if !has('arabic') +if !has('arabic') || !has('multi_byte') finish endif -set encoding=utf-8 -scriptencoding utf-8 +source view_util.vim -" Return list of utf8 sequences of each character at line lnum. +" Return list of Unicode characters at line lnum. " Combining characters are treated as a single item. -func GetCharsUtf8(lnum) +func s:get_chars(lnum) call cursor(a:lnum, 1) let chars = [] let numchars = strchars(getline('.'), 1) for i in range(1, numchars) exe 'norm ' i . '|' - call add(chars, execute('norm g8')) + let c=execute('ascii') + let c=substitute(c, '\n\?<.\{-}Hex\s*', 'U+', 'g') + let c=substitute(c, ',\s*Octal\s*\d*', '', 'g') + call add(chars, c) endfor return chars endfunc @@ -43,25 +45,28 @@ func Test_arabic_input() new set arabic " Typing sghl in Arabic insert mode should show the - " Arabic word 'Salaam' i.e. 'peace'. - call feedkeys('isghl', 'tx') - redraw + " Arabic word 'Salaam' i.e. 'peace', spelled: + " SEEN, LAM, ALEF, MEEM. + " See: https://www.mediawiki.org/wiki/VisualEditor/Typing/Right-to-left + call feedkeys('isghl!', 'tx') + call assert_match("^ *!\uFEE1\uFEFC\uFEB3$", ScreenLines(1, &columns)[0]) call assert_equal([ - \ "\nd8 b3 ", - \ "\nd9 84 + d8 a7 ", - \ "\nd9 85 "], GetCharsUtf8(1)) + \ 'U+0633', + \ 'U+0644 U+0627', + \ 'U+0645', + \ 'U+21'], s:get_chars(1)) " Without shaping, it should give individual Arabic letters. set noarabicshape - redraw + call assert_match("^ *!\u0645\u0627\u0644\u0633$", ScreenLines(1, &columns)[0]) call assert_equal([ - \ "\nd8 b3 ", - \ "\nd9 84 ", - \ "\nd8 a7 ", - \ "\nd9 85 "], GetCharsUtf8(1)) + \ 'U+0633', + \ 'U+0644', + \ 'U+0627', + \ 'U+0645', + \ 'U+21'], s:get_chars(1)) - set arabicshape& - set arabic& + set arabic& arabicshape& bwipe! endfunc @@ -69,7 +74,7 @@ func Test_arabic_toggle_keymap() new set arabic call feedkeys("i12\12\12", 'tx') - redraw + call assert_match("^ *٢١21٢١$", ScreenLines(1, &columns)[0]) call assert_equal('١٢12١٢', getline('.')) set arabic& bwipe! @@ -79,14 +84,389 @@ func Test_delcombine() new set arabic call feedkeys("isghl\\", 'tx') - redraw - call assert_equal(["\nd8 b3 ", "\nd9 84 "], GetCharsUtf8(1)) + call assert_match("^ *\uFEDE\uFEB3$", ScreenLines(1, &columns)[0]) + call assert_equal(['U+0633', 'U+0644'], s:get_chars(1)) - " Now the same with nodelcombine + " Now the same with 'nodelcombine' set nodelcombine %d call feedkeys("isghl\\", 'tx') - call assert_equal(["\nd8 b3 "], GetCharsUtf8(1)) + call assert_match("^ *\uFEB1$", ScreenLines(1, &columns)[0]) + call assert_equal(['U+0633'], s:get_chars(1)) set arabic& bwipe! endfunc + +" Values from src/arabic.h (not all used yet) +let s:a_COMMA = "\u060C" +let s:a_SEMICOLON = "\u061B" +let s:a_QUESTION = "\u061F" +let s:a_HAMZA = "\u0621" +let s:a_ALEF_MADDA = "\u0622" +let s:a_ALEF_HAMZA_ABOVE = "\u0623" +let s:a_WAW_HAMZA = "\u0624" +let s:a_ALEF_HAMZA_BELOW = "\u0625" +let s:a_YEH_HAMZA = "\u0626" +let s:a_ALEF = "\u0627" +let s:a_BEH = "\u0628" +let s:a_TEH_MARBUTA = "\u0629" +let s:a_TEH = "\u062a" +let s:a_THEH = "\u062b" +let s:a_JEEM = "\u062c" +let s:a_HAH = "\u062d" +let s:a_KHAH = "\u062e" +let s:a_DAL = "\u062f" +let s:a_THAL = "\u0630" +let s:a_REH = "\u0631" +let s:a_ZAIN = "\u0632" +let s:a_SEEN = "\u0633" +let s:a_SHEEN = "\u0634" +let s:a_SAD = "\u0635" +let s:a_DAD = "\u0636" +let s:a_TAH = "\u0637" +let s:a_ZAH = "\u0638" +let s:a_AIN = "\u0639" +let s:a_GHAIN = "\u063a" +let s:a_TATWEEL = "\u0640" +let s:a_FEH = "\u0641" +let s:a_QAF = "\u0642" +let s:a_KAF = "\u0643" +let s:a_LAM = "\u0644" +let s:a_MEEM = "\u0645" +let s:a_NOON = "\u0646" +let s:a_HEH = "\u0647" +let s:a_WAW = "\u0648" +let s:a_ALEF_MAKSURA = "\u0649" +let s:a_YEH = "\u064a" + +let s:a_FATHATAN = "\u064b" +let s:a_DAMMATAN = "\u064c" +let s:a_KASRATAN = "\u064d" +let s:a_FATHA = "\u064e" +let s:a_DAMMA = "\u064f" +let s:a_KASRA = "\u0650" +let s:a_SHADDA = "\u0651" +let s:a_SUKUN = "\u0652" + +let s:a_MADDA_ABOVE = "\u0653" +let s:a_HAMZA_ABOVE = "\u0654" +let s:a_HAMZA_BELOW = "\u0655" + +let s:a_ZERO = "\u0660" +let s:a_ONE = "\u0661" +let s:a_TWO = "\u0662" +let s:a_THREE = "\u0663" +let s:a_FOUR = "\u0664" +let s:a_FIVE = "\u0665" +let s:a_SIX = "\u0666" +let s:a_SEVEN = "\u0667" +let s:a_EIGHT = "\u0668" +let s:a_NINE = "\u0669" +let s:a_PERCENT = "\u066a" +let s:a_DECIMAL = "\u066b" +let s:a_THOUSANDS = "\u066c" +let s:a_STAR = "\u066d" +let s:a_MINI_ALEF = "\u0670" + +let s:a_s_FATHATAN = "\ufe70" +let s:a_m_TATWEEL_FATHATAN = "\ufe71" +let s:a_s_DAMMATAN = "\ufe72" + +let s:a_s_KASRATAN = "\ufe74" + +let s:a_s_FATHA = "\ufe76" +let s:a_m_FATHA = "\ufe77" +let s:a_s_DAMMA = "\ufe78" +let s:a_m_DAMMA = "\ufe79" +let s:a_s_KASRA = "\ufe7a" +let s:a_m_KASRA = "\ufe7b" +let s:a_s_SHADDA = "\ufe7c" +let s:a_m_SHADDA = "\ufe7d" +let s:a_s_SUKUN = "\ufe7e" +let s:a_m_SUKUN = "\ufe7f" + +let s:a_s_HAMZA = "\ufe80" +let s:a_s_ALEF_MADDA = "\ufe81" +let s:a_f_ALEF_MADDA = "\ufe82" +let s:a_s_ALEF_HAMZA_ABOVE = "\ufe83" +let s:a_f_ALEF_HAMZA_ABOVE = "\ufe84" +let s:a_s_WAW_HAMZA = "\ufe85" +let s:a_f_WAW_HAMZA = "\ufe86" +let s:a_s_ALEF_HAMZA_BELOW = "\ufe87" +let s:a_f_ALEF_HAMZA_BELOW = "\ufe88" +let s:a_s_YEH_HAMZA = "\ufe89" +let s:a_f_YEH_HAMZA = "\ufe8a" +let s:a_i_YEH_HAMZA = "\ufe8b" +let s:a_m_YEH_HAMZA = "\ufe8c" +let s:a_s_ALEF = "\ufe8d" +let s:a_f_ALEF = "\ufe8e" +let s:a_s_BEH = "\ufe8f" +let s:a_f_BEH = "\ufe90" +let s:a_i_BEH = "\ufe91" +let s:a_m_BEH = "\ufe92" +let s:a_s_TEH_MARBUTA = "\ufe93" +let s:a_f_TEH_MARBUTA = "\ufe94" +let s:a_s_TEH = "\ufe95" +let s:a_f_TEH = "\ufe96" +let s:a_i_TEH = "\ufe97" +let s:a_m_TEH = "\ufe98" +let s:a_s_THEH = "\ufe99" +let s:a_f_THEH = "\ufe9a" +let s:a_i_THEH = "\ufe9b" +let s:a_m_THEH = "\ufe9c" +let s:a_s_JEEM = "\ufe9d" +let s:a_f_JEEM = "\ufe9e" +let s:a_i_JEEM = "\ufe9f" +let s:a_m_JEEM = "\ufea0" +let s:a_s_HAH = "\ufea1" +let s:a_f_HAH = "\ufea2" +let s:a_i_HAH = "\ufea3" +let s:a_m_HAH = "\ufea4" +let s:a_s_KHAH = "\ufea5" +let s:a_f_KHAH = "\ufea6" +let s:a_i_KHAH = "\ufea7" +let s:a_m_KHAH = "\ufea8" +let s:a_s_DAL = "\ufea9" +let s:a_f_DAL = "\ufeaa" +let s:a_s_THAL = "\ufeab" +let s:a_f_THAL = "\ufeac" +let s:a_s_REH = "\ufead" +let s:a_f_REH = "\ufeae" +let s:a_s_ZAIN = "\ufeaf" +let s:a_f_ZAIN = "\ufeb0" +let s:a_s_SEEN = "\ufeb1" +let s:a_f_SEEN = "\ufeb2" +let s:a_i_SEEN = "\ufeb3" +let s:a_m_SEEN = "\ufeb4" +let s:a_s_SHEEN = "\ufeb5" +let s:a_f_SHEEN = "\ufeb6" +let s:a_i_SHEEN = "\ufeb7" +let s:a_m_SHEEN = "\ufeb8" +let s:a_s_SAD = "\ufeb9" +let s:a_f_SAD = "\ufeba" +let s:a_i_SAD = "\ufebb" +let s:a_m_SAD = "\ufebc" +let s:a_s_DAD = "\ufebd" +let s:a_f_DAD = "\ufebe" +let s:a_i_DAD = "\ufebf" +let s:a_m_DAD = "\ufec0" +let s:a_s_TAH = "\ufec1" +let s:a_f_TAH = "\ufec2" +let s:a_i_TAH = "\ufec3" +let s:a_m_TAH = "\ufec4" +let s:a_s_ZAH = "\ufec5" +let s:a_f_ZAH = "\ufec6" +let s:a_i_ZAH = "\ufec7" +let s:a_m_ZAH = "\ufec8" +let s:a_s_AIN = "\ufec9" +let s:a_f_AIN = "\ufeca" +let s:a_i_AIN = "\ufecb" +let s:a_m_AIN = "\ufecc" +let s:a_s_GHAIN = "\ufecd" +let s:a_f_GHAIN = "\ufece" +let s:a_i_GHAIN = "\ufecf" +let s:a_m_GHAIN = "\ufed0" +let s:a_s_FEH = "\ufed1" +let s:a_f_FEH = "\ufed2" +let s:a_i_FEH = "\ufed3" +let s:a_m_FEH = "\ufed4" +let s:a_s_QAF = "\ufed5" +let s:a_f_QAF = "\ufed6" +let s:a_i_QAF = "\ufed7" +let s:a_m_QAF = "\ufed8" +let s:a_s_KAF = "\ufed9" +let s:a_f_KAF = "\ufeda" +let s:a_i_KAF = "\ufedb" +let s:a_m_KAF = "\ufedc" +let s:a_s_LAM = "\ufedd" +let s:a_f_LAM = "\ufede" +let s:a_i_LAM = "\ufedf" +let s:a_m_LAM = "\ufee0" +let s:a_s_MEEM = "\ufee1" +let s:a_f_MEEM = "\ufee2" +let s:a_i_MEEM = "\ufee3" +let s:a_m_MEEM = "\ufee4" +let s:a_s_NOON = "\ufee5" +let s:a_f_NOON = "\ufee6" +let s:a_i_NOON = "\ufee7" +let s:a_m_NOON = "\ufee8" +let s:a_s_HEH = "\ufee9" +let s:a_f_HEH = "\ufeea" +let s:a_i_HEH = "\ufeeb" +let s:a_m_HEH = "\ufeec" +let s:a_s_WAW = "\ufeed" +let s:a_f_WAW = "\ufeee" +let s:a_s_ALEF_MAKSURA = "\ufeef" +let s:a_f_ALEF_MAKSURA = "\ufef0" +let s:a_s_YEH = "\ufef1" +let s:a_f_YEH = "\ufef2" +let s:a_i_YEH = "\ufef3" +let s:a_m_YEH = "\ufef4" +let s:a_s_LAM_ALEF_MADDA_ABOVE = "\ufef5" +let s:a_f_LAM_ALEF_MADDA_ABOVE = "\ufef6" +let s:a_s_LAM_ALEF_HAMZA_ABOVE = "\ufef7" +let s:a_f_LAM_ALEF_HAMZA_ABOVE = "\ufef8" +let s:a_s_LAM_ALEF_HAMZA_BELOW = "\ufef9" +let s:a_f_LAM_ALEF_HAMZA_BELOW = "\ufefa" +let s:a_s_LAM_ALEF = "\ufefb" +let s:a_f_LAM_ALEF = "\ufefc" + +let s:a_BYTE_ORDER_MARK = "\ufeff" + +func Test_shape_initial() + new + set arabicshape + + " Shaping arabic {testchar} non-arabic Tests chg_c_a2i(). + " pair[0] = testchar, pair[1] = next-result, pair[2] = current-result + for pair in [[s:a_YEH_HAMZA, s:a_f_GHAIN, s:a_i_YEH_HAMZA], + \ [s:a_HAMZA, s:a_s_GHAIN, s:a_s_HAMZA], + \ [s:a_ALEF_MADDA, s:a_s_GHAIN, s:a_s_ALEF_MADDA], + \ [s:a_ALEF_HAMZA_ABOVE, s:a_s_GHAIN, s:a_s_ALEF_HAMZA_ABOVE], + \ [s:a_WAW_HAMZA, s:a_s_GHAIN, s:a_s_WAW_HAMZA], + \ [s:a_ALEF_HAMZA_BELOW, s:a_s_GHAIN, s:a_s_ALEF_HAMZA_BELOW], + \ [s:a_ALEF, s:a_s_GHAIN, s:a_s_ALEF], + \ [s:a_TEH_MARBUTA, s:a_s_GHAIN, s:a_s_TEH_MARBUTA], + \ [s:a_DAL, s:a_s_GHAIN, s:a_s_DAL], + \ [s:a_THAL, s:a_s_GHAIN, s:a_s_THAL], + \ [s:a_REH, s:a_s_GHAIN, s:a_s_REH], + \ [s:a_ZAIN, s:a_s_GHAIN, s:a_s_ZAIN], + \ [s:a_TATWEEL, s:a_f_GHAIN, s:a_TATWEEL], + \ [s:a_WAW, s:a_s_GHAIN, s:a_s_WAW], + \ [s:a_ALEF_MAKSURA, s:a_s_GHAIN, s:a_s_ALEF_MAKSURA], + \ [s:a_BEH, s:a_f_GHAIN, s:a_i_BEH], + \ [s:a_TEH, s:a_f_GHAIN, s:a_i_TEH], + \ [s:a_THEH, s:a_f_GHAIN, s:a_i_THEH], + \ [s:a_JEEM, s:a_f_GHAIN, s:a_i_JEEM], + \ [s:a_HAH, s:a_f_GHAIN, s:a_i_HAH], + \ [s:a_KHAH, s:a_f_GHAIN, s:a_i_KHAH], + \ [s:a_SEEN, s:a_f_GHAIN, s:a_i_SEEN], + \ [s:a_SHEEN, s:a_f_GHAIN, s:a_i_SHEEN], + \ [s:a_SAD, s:a_f_GHAIN, s:a_i_SAD], + \ [s:a_DAD, s:a_f_GHAIN, s:a_i_DAD], + \ [s:a_TAH, s:a_f_GHAIN, s:a_i_TAH], + \ [s:a_ZAH, s:a_f_GHAIN, s:a_i_ZAH], + \ [s:a_AIN, s:a_f_GHAIN, s:a_i_AIN], + \ [s:a_GHAIN, s:a_f_GHAIN, s:a_i_GHAIN], + \ [s:a_FEH, s:a_f_GHAIN, s:a_i_FEH], + \ [s:a_QAF, s:a_f_GHAIN, s:a_i_QAF], + \ [s:a_KAF, s:a_f_GHAIN, s:a_i_KAF], + \ [s:a_LAM, s:a_f_GHAIN, s:a_i_LAM], + \ [s:a_MEEM, s:a_f_GHAIN, s:a_i_MEEM], + \ [s:a_NOON, s:a_f_GHAIN, s:a_i_NOON], + \ [s:a_HEH, s:a_f_GHAIN, s:a_i_HEH], + \ [s:a_YEH, s:a_f_GHAIN, s:a_i_YEH], + \ ] + call setline(1, s:a_GHAIN . pair[0] . ' ') + call assert_equal([pair[1] . pair[2] . ' '], ScreenLines(1, 3)) + endfor + + set arabicshape& + bwipe! +endfunc + +func Test_shape_isolated() + new + set arabicshape + + " Shaping non-arabic {testchar} non-arabic Tests chg_c_a2s(). + " pair[0] = testchar, pair[1] = current-result + for pair in [[s:a_HAMZA, s:a_s_HAMZA], + \ [s:a_ALEF_MADDA, s:a_s_ALEF_MADDA], + \ [s:a_ALEF_HAMZA_ABOVE, s:a_s_ALEF_HAMZA_ABOVE], + \ [s:a_WAW_HAMZA, s:a_s_WAW_HAMZA], + \ [s:a_ALEF_HAMZA_BELOW, s:a_s_ALEF_HAMZA_BELOW], + \ [s:a_YEH_HAMZA, s:a_s_YEH_HAMZA], + \ [s:a_ALEF, s:a_s_ALEF], + \ [s:a_TEH_MARBUTA, s:a_s_TEH_MARBUTA], + \ [s:a_DAL, s:a_s_DAL], + \ [s:a_THAL, s:a_s_THAL], + \ [s:a_REH, s:a_s_REH], + \ [s:a_ZAIN, s:a_s_ZAIN], + \ [s:a_TATWEEL, s:a_TATWEEL], + \ [s:a_WAW, s:a_s_WAW], + \ [s:a_ALEF_MAKSURA, s:a_s_ALEF_MAKSURA], + \ [s:a_BEH, s:a_s_BEH], + \ [s:a_TEH, s:a_s_TEH], + \ [s:a_THEH, s:a_s_THEH], + \ [s:a_JEEM, s:a_s_JEEM], + \ [s:a_HAH, s:a_s_HAH], + \ [s:a_KHAH, s:a_s_KHAH], + \ [s:a_SEEN, s:a_s_SEEN], + \ [s:a_SHEEN, s:a_s_SHEEN], + \ [s:a_SAD, s:a_s_SAD], + \ [s:a_DAD, s:a_s_DAD], + \ [s:a_TAH, s:a_s_TAH], + \ [s:a_ZAH, s:a_s_ZAH], + \ [s:a_AIN, s:a_s_AIN], + \ [s:a_GHAIN, s:a_s_GHAIN], + \ [s:a_FEH, s:a_s_FEH], + \ [s:a_QAF, s:a_s_QAF], + \ [s:a_KAF, s:a_s_KAF], + \ [s:a_LAM, s:a_s_LAM], + \ [s:a_MEEM, s:a_s_MEEM], + \ [s:a_NOON, s:a_s_NOON], + \ [s:a_HEH, s:a_s_HEH], + \ [s:a_YEH, s:a_s_YEH], + \ ] + call setline(1, ' ' . pair[0] . ' ') + call assert_equal([' ' . pair[1] . ' '], ScreenLines(1, 3)) + endfor + + set arabicshape& + bwipe! +endfunc + +func Test_shape_medial() + new + set arabicshape + + " Shaping arabic {testchar} arabic Tests chg_c_a2m(). + " pair[0] = testchar, pair[1] = next-result, pair[2] = current-result, + " pair[3] = previous-result + for pair in [[s:a_HAMZA, s:a_s_GHAIN, s:a_s_HAMZA, s:a_s_BEH], + \[s:a_ALEF_MADDA, s:a_s_GHAIN, s:a_f_ALEF_MADDA, s:a_i_BEH], + \[s:a_ALEF_HAMZA_ABOVE, s:a_s_GHAIN, s:a_f_ALEF_HAMZA_ABOVE, s:a_i_BEH], + \[s:a_WAW_HAMZA, s:a_s_GHAIN, s:a_f_WAW_HAMZA, s:a_i_BEH], + \[s:a_ALEF_HAMZA_BELOW, s:a_s_GHAIN, s:a_f_ALEF_HAMZA_BELOW, s:a_i_BEH], + \[s:a_YEH_HAMZA, s:a_f_GHAIN, s:a_m_YEH_HAMZA, s:a_i_BEH], + \[s:a_ALEF, s:a_s_GHAIN, s:a_f_ALEF, s:a_i_BEH], + \[s:a_BEH, s:a_f_GHAIN, s:a_m_BEH, s:a_i_BEH], + \[s:a_TEH_MARBUTA, s:a_s_GHAIN, s:a_f_TEH_MARBUTA, s:a_i_BEH], + \[s:a_TEH, s:a_f_GHAIN, s:a_m_TEH, s:a_i_BEH], + \[s:a_THEH, s:a_f_GHAIN, s:a_m_THEH, s:a_i_BEH], + \[s:a_JEEM, s:a_f_GHAIN, s:a_m_JEEM, s:a_i_BEH], + \[s:a_HAH, s:a_f_GHAIN, s:a_m_HAH, s:a_i_BEH], + \[s:a_KHAH, s:a_f_GHAIN, s:a_m_KHAH, s:a_i_BEH], + \[s:a_DAL, s:a_s_GHAIN, s:a_f_DAL, s:a_i_BEH], + \[s:a_THAL, s:a_s_GHAIN, s:a_f_THAL, s:a_i_BEH], + \[s:a_REH, s:a_s_GHAIN, s:a_f_REH, s:a_i_BEH], + \[s:a_ZAIN, s:a_s_GHAIN, s:a_f_ZAIN, s:a_i_BEH], + \[s:a_SEEN, s:a_f_GHAIN, s:a_m_SEEN, s:a_i_BEH], + \[s:a_SHEEN, s:a_f_GHAIN, s:a_m_SHEEN, s:a_i_BEH], + \[s:a_SAD, s:a_f_GHAIN, s:a_m_SAD, s:a_i_BEH], + \[s:a_DAD, s:a_f_GHAIN, s:a_m_DAD, s:a_i_BEH], + \[s:a_TAH, s:a_f_GHAIN, s:a_m_TAH, s:a_i_BEH], + \[s:a_ZAH, s:a_f_GHAIN, s:a_m_ZAH, s:a_i_BEH], + \[s:a_AIN, s:a_f_GHAIN, s:a_m_AIN, s:a_i_BEH], + \[s:a_GHAIN, s:a_f_GHAIN, s:a_m_GHAIN, s:a_i_BEH], + \[s:a_TATWEEL, s:a_f_GHAIN, s:a_TATWEEL, s:a_i_BEH], + \[s:a_FEH, s:a_f_GHAIN, s:a_m_FEH, s:a_i_BEH], + \[s:a_QAF, s:a_f_GHAIN, s:a_m_QAF, s:a_i_BEH], + \[s:a_KAF, s:a_f_GHAIN, s:a_m_KAF, s:a_i_BEH], + \[s:a_LAM, s:a_f_GHAIN, s:a_m_LAM, s:a_i_BEH], + \[s:a_MEEM, s:a_f_GHAIN, s:a_m_MEEM, s:a_i_BEH], + \[s:a_NOON, s:a_f_GHAIN, s:a_m_NOON, s:a_i_BEH], + \[s:a_HEH, s:a_f_GHAIN, s:a_m_HEH, s:a_i_BEH], + \[s:a_WAW, s:a_s_GHAIN, s:a_f_WAW, s:a_i_BEH], + \[s:a_ALEF_MAKSURA, s:a_s_GHAIN, s:a_f_ALEF_MAKSURA, s:a_i_BEH], + \[s:a_YEH, s:a_f_GHAIN, s:a_m_YEH, s:a_i_BEH], + \ ] + call setline(1, s:a_GHAIN . pair[0] . s:a_BEH) + call assert_equal([pair[1] . pair[2] . pair[3]], ScreenLines(1, 3)) + endfor + + set arabicshape& + bwipe! +endfunc + diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim index 2ac0004500..1f835b876f 100644 --- a/src/testdir/test_fold.vim +++ b/src/testdir/test_fold.vim @@ -1,6 +1,6 @@ " Test for folding -function! Test_address_fold() +func! Test_address_fold() new call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/', \ 'after fold 1', 'after fold 2', 'after fold 3']) @@ -62,9 +62,9 @@ function! Test_address_fold() call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1)) quit! -endfunction +endfunc -function! Test_indent_fold() +func! Test_indent_fold() new call setline(1, ['', 'a', ' b', ' c']) setl fen fdm=indent @@ -72,9 +72,9 @@ function! Test_indent_fold() norm! >> let a=map(range(1,4), 'foldclosed(v:val)') call assert_equal([-1,-1,-1,-1], a) -endfu +endfunc -function! Test_indent_fold() +func! Test_indent_fold() new call setline(1, ['', 'a', ' b', ' c']) setl fen fdm=indent @@ -83,9 +83,9 @@ function! Test_indent_fold() let a=map(range(1,4), 'foldclosed(v:val)') call assert_equal([-1,-1,-1,-1], a) bw! -endfu +endfunc -function! Test_indent_fold2() +func! Test_indent_fold2() new call setline(1, ['', '{{{', '}}}', '{{{', '}}}']) setl fen fdm=marker @@ -94,4 +94,21 @@ function! Test_indent_fold2() let a=map(range(1,5), 'foldclosed(v:val)') call assert_equal([-1,-1,-1,4,4], a) bw! -endfu +endfunc + +func Test_manual_fold_with_filter() + if !executable('cat') + return + endif + new + call setline(1, range(1, 20)) + 4,$fold + %foldopen + 10,$fold + %foldopen + " This filter command should not have an effect + 1,8! cat + call feedkeys('5ggzdzMGdd', 'xt') + call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$')) + bwipe! +endfunc diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim index 77e4f2e9a6..6c9722dacf 100644 --- a/src/testdir/test_gui.vim +++ b/src/testdir/test_gui.vim @@ -17,6 +17,9 @@ endfunc " Test for resetting "secure" flag after GUI has started. " Must be run first. func Test_1_set_secure() + " Ignore the "failed to create input context" error. + call test_ignore_error('E285') + set exrc secure gui -f call assert_equal(1, has('gui_running')) diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim index 221514db2c..0d697b3f3e 100644 --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -35,10 +35,34 @@ func Test_static_tagjump() tag one call assert_equal(2, line('.')) + bwipe! set tags& call delete('Xtags') call delete('Xfile1') +endfunc + +func Test_duplicate_tagjump() + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile1\t1;\"\td\tfile:", + \ "thesame\tXfile1\t2;\"\td\tfile:", + \ "thesame\tXfile1\t3;\"\td\tfile:", + \ ], + \ 'Xtags') + new Xfile1 + call setline(1, ['thesame one', 'thesame two', 'thesame three']) + write + tag thesame + call assert_equal(1, line('.')) + tnext + call assert_equal(2, line('.')) + tnext + call assert_equal(3, line('.')) + bwipe! + set tags& + call delete('Xtags') + call delete('Xfile1') endfunc " Tests for [ CTRL-I and CTRL-W CTRL-I commands diff --git a/src/version.c b/src/version.c index 5d43f36281..d267bf0eb6 100644 --- a/src/version.c +++ b/src/version.c @@ -779,6 +779,20 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 393, +/**/ + 392, +/**/ + 391, +/**/ + 390, +/**/ + 389, +/**/ + 388, +/**/ + 387, /**/ 386, /**/