# HG changeset patch # User Bram Moolenaar # Date 1626718504 -7200 # Node ID c626fd34b66fcfad9192e3305569135b45bf1264 # Parent d3f443bd2edd0115446de234e4bf0d5b9aa75a4a patch 8.2.3184: cannot add a digraph with a leading space Commit: https://github.com/vim/vim/commit/6106504e9edc8500131f7a36e59bc146f90180fa Author: mityu Date: Mon Jul 19 20:07:21 2021 +0200 patch 8.2.3184: cannot add a digraph with a leading space Problem: Cannot add a digraph with a leading space. It is not easy to list existing digraphs. Solution: Add setdigraph(), setdigraphlist(), getdigraph() and getdigraphlist(). (closes #8580) diff --git a/runtime/doc/digraph.txt b/runtime/doc/digraph.txt --- a/runtime/doc/digraph.txt +++ b/runtime/doc/digraph.txt @@ -38,6 +38,9 @@ 1. Defining digraphs *digraphs-defin < Avoid defining a digraph with '_' (underscore) as the first character, it has a special meaning in the future. + NOTE: This command cannot add a digraph that starts + with a white space. If you want to add such digraph, + you can use |setdigraph()| instead. Vim is normally compiled with the |+digraphs| feature. If the feature is disabled, the ":digraph" command will display an error message. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2620,6 +2620,8 @@ getcompletion({pat}, {type} [, {filtered getcurpos([{winnr}]) List position of the cursor getcursorcharpos([{winnr}]) List character position of the cursor getcwd([{winnr} [, {tabnr}]]) String get the current working directory +getdigraph({chars}) String get the digraph of {chars} +getdigraphlist([{listall}]) List get all |digraph|s getenv({name}) String return environment variable getfontname([{name}]) String name of font being used getfperm({fname}) String file permissions of file {fname} @@ -2886,6 +2888,8 @@ setcharpos({expr}, {list}) Number set th setcharsearch({dict}) Dict set character search from {dict} setcmdpos({pos}) Number set cursor position in command-line setcursorcharpos({list}) Number move cursor to position in {list} +setdigraph({chars}, {digraph}) Boolean register |digraph| +setdigraphlist({digraphlist}) Boolean register multiple |digraph|s setenv({name}, {val}) none set environment variable setfperm({fname}, {mode}) Number set {fname} file permissions to {mode} setline({lnum}, {line}) Number set line {lnum} to {line} @@ -5572,6 +5576,61 @@ getcwd([{winnr} [, {tabnr}]]) < Can also be used as a |method|: > GetWinnr()->getcwd() < + *getdigraph()* *E1214* +getdigraph({chars}) + Return the digraph of {chars}. This should be a string with + exactly two characters. If {chars} are not just two + characters, or the digraph of {chars} does not exist, an error + is given and an empty string is returned. + + The character will be converted from Unicode to 'encoding' + when needed. This does require the conversion to be + available, it might fail. + + Also see |getdigraphlist()|. + + Examples: > + " Get a built-in digraph + :echo getdigraph('00') " Returns '∞' + + " Get a user-defined digraph + :call setdigraph('aa', 'あ') + :echo getdigraph('aa') " Returns 'あ' +< + Can also be used as a |method|: > + GetChars()->getdigraph() +< + This function works only when compiled with the |+digraphs| + feature. If this feature is disabled, this function will + display an error message. + + +getdigraphlist([{listall}]) *getdigraphlist()* + Return a list of digraphs. If the {listall} argument is given + and it is TRUE, return all digraphs, including the default + digraphs. Otherwise, return only user-defined digraphs. + + The characters will be converted from Unicode to 'encoding' + when needed. This does require the conservation to be + available, it might fail. + + Also see |getdigraph()|. + + Examples: > + " Get user-defined digraphs + :echo getdigraphlist() + + " Get all the digraphs, including default digraphs + :echo digraphlist(1) +< + Can also be used as a |method|: > + GetNumber()->getdigraphlist() +< + This function works only when compiled with the |+digraphs| + feature. If this feature is disabled, this function will + display an error message. + + getenv({name}) *getenv()* Return the value of environment variable {name}. When the variable does not exist |v:null| is returned. That @@ -9490,6 +9549,54 @@ setcursorcharpos({list}) Can also be used as a |method|: > GetCursorPos()->setcursorcharpos() + +setdigraph({chars}, {digraph}) *setdigraph()* *E1205* + Add digraph {chars} to the list. {chars} must be a string + with two characters. {digraph} is a string with one utf-8 + encoded character. Be careful, composing characters are NOT + ignored. This function is similar to |:digraphs| command, but + useful to add digraphs start with a white space. + + The function result is v:true if |digraph| is registered. If + this fails an error message is given and v:false is returned. + + If you want to define multiple digraphs at once, you can use + |setdigraphlist()|. + + Example: > + call setdigraph(' ', 'あ') +< + Can be used as a |method|: > + GetString()->setdigraph('あ') +< + This function works only when compiled with the |+digraphs| + feature. If this feature is disabled, this function will + display an error message. + + +setdigraphlist({digraphlist}) *setdigraphlist()* + Similar to |setdigraph()| but this function can add multiple + digraphs at once. {digraphlist} is a list composed of lists, + where each list contains two strings with {chars} and + {digraph} as in |setdigraph()|. + Example: > + call setdigraphlist([['aa', 'あ'], ['ii', 'い']]) +< + It is similar to the following: > + for [chars, digraph] in [['aa', 'あ'], ['ii', 'い']] + call setdigraph(chars, digraph) + endfor +< Except that the function returns after the first error, + following digraphs will not be added. + + Can be used as a |method|: > + GetList()->setdigraphlist() +< + This function works only when compiled with the |+digraphs| + feature. If this feature is disabled, this function will + display an error message. + + setenv({name}, {val}) *setenv()* Set environment variable {name} to {val}. When {val} is |v:null| the environment variable is deleted. diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1000,6 +1000,10 @@ Mappings and Menus: *mapping-funct mapset() restore a mapping menu_info() get information about a menu item wildmenumode() check if the wildmode is active + getdigraph() get |digraph| + getdigraphlist() get all |digraph|s + setdigraph() register |digraph| + setdigraphlist() register multiple |digraph|s Testing: *test-functions* assert_equal() assert that two expressions values are equal diff --git a/src/digraph.c b/src/digraph.c --- a/src/digraph.c +++ b/src/digraph.c @@ -1993,6 +1993,65 @@ getdigraph(int char1, int char2, int met } /* + * Add a digraph to the digraph table. + */ + static void +registerdigraph(int char1, int char2, int n) +{ + int i; + digr_T *dp; + + // If the digraph already exists, replace "result". + dp = (digr_T *)user_digraphs.ga_data; + for (i = 0; i < user_digraphs.ga_len; ++i) + { + if ((int)dp->char1 == char1 && (int)dp->char2 == char2) + { + dp->result = n; + return; + } + ++dp; + } + + // Add a new digraph to the table. + if (ga_grow(&user_digraphs, 1) == OK) + { + dp = (digr_T *)user_digraphs.ga_data + user_digraphs.ga_len; + dp->char1 = char1; + dp->char2 = char2; + dp->result = n; + ++user_digraphs.ga_len; + } +} + +/* + * Check the characters are valid for a digraph. + * If they are valid, returns TRUE; otherwise, give an error message and + * returns FALSE. + */ + int +check_digraph_chars_valid(int char1, int char2) +{ + if (char2 == 0) + { + char_u msg[MB_MAXBYTES + 1]; + + msg[mb_char2bytes(char1, msg)] = NUL; + + semsg(_(e_digraph_must_be_just_two_characters_str), msg); + return FALSE; + } + if (char1 == ESC || char2 == ESC) + { + emsg(_("E104: Escape not allowed in digraph")); + return FALSE; + } + return TRUE; +} + + + +/* * Add the digraphs in the argument to the digraph table. * format: {c1}{c2} char {c1}{c2} char ... */ @@ -2000,8 +2059,6 @@ getdigraph(int char1, int char2, int met putdigraph(char_u *str) { int char1, char2, n; - int i; - digr_T *dp; while (*str != NUL) { @@ -2010,16 +2067,10 @@ putdigraph(char_u *str) return; char1 = *str++; char2 = *str++; - if (char2 == 0) - { - emsg(_(e_invarg)); + + if (!check_digraph_chars_valid(char1, char2)) return; - } - if (char1 == ESC || char2 == ESC) - { - emsg(_("E104: Escape not allowed in digraph")); - return; - } + str = skipwhite(str); if (!VIM_ISDIGIT(*str)) { @@ -2028,30 +2079,7 @@ putdigraph(char_u *str) } n = getdigits(&str); - // If the digraph already exists, replace the result. - dp = (digr_T *)user_digraphs.ga_data; - for (i = 0; i < user_digraphs.ga_len; ++i) - { - if ((int)dp->char1 == char1 && (int)dp->char2 == char2) - { - dp->result = n; - break; - } - ++dp; - } - - // Add a new digraph to the table. - if (i == user_digraphs.ga_len) - { - if (ga_grow(&user_digraphs, 1) == OK) - { - dp = (digr_T *)user_digraphs.ga_data + user_digraphs.ga_len; - dp->char1 = char1; - dp->char2 = char2; - dp->result = n; - ++user_digraphs.ga_len; - } - } + registerdigraph(char1, char2, n); } } @@ -2114,6 +2142,97 @@ listdigraphs(int use_headers) // wrong, in which case we messed up ScreenLines } + static void +getdigraphlist_appendpair(digr_T *dp, list_T *l) +{ + char_u buf[30]; + char_u *p; + list_T *l2; + listitem_T *li, *li2; + + + li = listitem_alloc(); + if (li == NULL) + return; + list_append(l, li); + li->li_tv.v_type = VAR_LIST; + li->li_tv.v_lock = 0; + + l2 = list_alloc(); + li->li_tv.vval.v_list = l2; + if (l2 == NULL) + return; + ++l2->lv_refcount; + + li2 = listitem_alloc(); + if (li2 == NULL) + return; + list_append(l2, li2); + li2->li_tv.v_type = VAR_STRING; + li2->li_tv.v_lock = 0; + + buf[0] = dp->char1; + buf[1] = dp->char2; + buf[2] = NUL; + li2->li_tv.vval.v_string = vim_strsave(&buf[0]); + + li2 = listitem_alloc(); + if (li2 == NULL) + return; + list_append(l2, li2); + li2->li_tv.v_type = VAR_STRING; + li2->li_tv.v_lock = 0; + + p = buf; + if (has_mbyte) + p += (*mb_char2bytes)(dp->result, p); + else + *p++ = (char_u)dp->result; + *p = NUL; + + li2->li_tv.vval.v_string = vim_strsave(buf); +} + + void +getdigraphlist_common(int list_all, typval_T *rettv) +{ + int i; + digr_T *dp; + + if (rettv_list_alloc(rettv) == FAIL) + return; + + if (list_all) + { + dp = digraphdefault; + for (i = 0; dp->char1 != NUL && !got_int; ++i) + { +#ifdef USE_UNICODE_DIGRAPHS + digr_T tmp; + + tmp.char1 = dp->char1; + tmp.char2 = dp->char2; + tmp.result = getexactdigraph(tmp.char1, tmp.char2, FALSE); + if (tmp.result != 0 && tmp.result != tmp.char2 + && (has_mbyte || tmp.result <= 255)) + getdigraphlist_appendpair(&tmp, rettv->vval.v_list); +#else + if (getexactdigraph(dp->char1, dp->char2, FALSE) == dp->result + && (has_mbyte || dp->result <= 255)) + getdigraphlist_appendpair(dp, rettv->vval.v_list); +#endif + ++dp; + } + } + + dp = (digr_T *)user_digraphs.ga_data; + for (i = 0; i < user_digraphs.ga_len && !got_int; ++i) + { + getdigraphlist_appendpair(dp, rettv->vval.v_list); + ++dp; + } +} + static struct dg_header_entry { int dg_start; char *dg_header; @@ -2210,8 +2329,207 @@ printdigraph(digr_T *dp, result_T *previ } } +# ifdef FEAT_EVAL +/* + * Get the two digraph characters from a typval. + * Return OK or FAIL. + */ + static int +get_digraph_chars(typval_T *arg, int *char1, int *char2) +{ + char_u buf_chars[NUMBUFLEN]; + char_u *chars = tv_get_string_buf_chk(arg, buf_chars); + char_u *p = chars; + + if (p != NULL) + { + if (*p != NUL) + { + *char1 = mb_cptr2char_adv(&p); + if (*p != NUL) + { + *char2 = mb_cptr2char_adv(&p); + if (*p == NUL) + { + if (check_digraph_chars_valid(*char1, *char2)) + return OK; + return FAIL; + } + } + } + } + semsg(_(e_digraph_must_be_just_two_characters_str), chars); + return FAIL; +} + + static int +setdigraph_common(typval_T *argchars, typval_T *argdigraph) +{ + int char1, char2; + char_u *digraph; + char_u *p; + char_u buf_digraph[NUMBUFLEN]; + varnumber_T n; + + if (get_digraph_chars(argchars, &char1, &char2) == FAIL) + return FALSE; + + digraph = tv_get_string_buf_chk(argdigraph, buf_digraph); + if (digraph == NULL) + return FALSE; + p = digraph; + n = mb_cptr2char_adv(&p); + if (*p != NUL) + { + semsg(_(e_digraph_argument_must_be_one_character_str), digraph); + return FALSE; + } + + registerdigraph(char1, char2, (int)n); + return TRUE; +} +# endif + #endif // FEAT_DIGRAPHS +#if defined(FEAT_EVAL) || defined(PROTO) +/* + * "getdigraph()" function + */ + void +f_getdigraph(typval_T *argvars, typval_T *rettv) +{ +# ifdef FEAT_DIGRAPHS + int code; + char_u buf[NUMBUFLEN]; + char_u *digraphs; + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; // Return empty string for failure + digraphs = tv_get_string_chk(&argvars[0]); + + if (digraphs == NULL) + return; + else if (STRLEN(digraphs) != 2) + { + semsg(_(e_digraph_must_be_just_two_characters_str), digraphs); + return; + } + code = getdigraph(digraphs[0], digraphs[1], FALSE); + + if (has_mbyte) + buf[(*mb_char2bytes)(code, buf)] = NUL; + else { + buf[0] = code; + buf[1] = NUL; + } + + rettv->vval.v_string = vim_strsave(buf); +# else + emsg(_(e_no_digraphs_version)); +# endif +} + +/* + * "getdigraphlist()" function + */ + void +f_getdigraphlist(typval_T *argvars, typval_T *rettv) +{ +# ifdef FEAT_DIGRAPHS + int flag_list_all; + + if (argvars[0].v_type == VAR_UNKNOWN) + flag_list_all = FALSE; + else + { + int error = FALSE; + varnumber_T flag = tv_get_number_chk(&argvars[0], &error); + if (error) + return; + flag_list_all = flag ? TRUE : FALSE; + } + + getdigraphlist_common(flag_list_all, rettv); +# else + emsg(_(e_no_digraphs_version)); +# endif +} + +/* + * "setdigraph()" function + */ + void +f_setdigraph(typval_T *argvars, typval_T *rettv) +{ +# ifdef FEAT_DIGRAPHS + rettv->v_type = VAR_BOOL; + rettv->vval.v_number = VVAL_FALSE; + + if (!setdigraph_common(&argvars[0], &argvars[1])) + return; + + rettv->vval.v_number = VVAL_TRUE; +# else + emsg(_(e_no_digraphs_version)); +# endif +} + +/* + * "setdigraphlist()" function + */ + void +f_setdigraphlist(typval_T * argvars, typval_T *rettv) +{ +# ifdef FEAT_DIGRAPHS + list_T *pl, *l; + listitem_T *pli; + + rettv->v_type = VAR_BOOL; + rettv->vval.v_number = VVAL_FALSE; + + if (argvars[0].v_type != VAR_LIST) + { + emsg(_(e_setdigraphlist_argument_must_be_list_of_lists_with_two_items)); + return; + } + + pl = argvars[0].vval.v_list; + if (pl == NULL) + { + // Empty list always results in success. + rettv->vval.v_number = VVAL_TRUE; + return; + } + + FOR_ALL_LIST_ITEMS(pl, pli) + { + if (pli->li_tv.v_type != VAR_LIST) + { + emsg(_(e_setdigraphlist_argument_must_be_list_of_lists_with_two_items)); + return; + } + + l = pli->li_tv.vval.v_list; + if (l == NULL || l->lv_len != 2) + { + emsg(_(e_setdigraphlist_argument_must_be_list_of_lists_with_two_items)); + return; + } + + if (!setdigraph_common(&l->lv_first->li_tv, + &l->lv_first->li_next->li_tv)) + return; + } + rettv->vval.v_number = VVAL_TRUE; +# else + emsg(_(e_no_digraphs_version)); +# endif +} + +#endif // FEAT_EVAL + + #if defined(FEAT_KEYMAP) || defined(PROTO) // structure used for b_kmap_ga.ga_data diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -54,6 +54,10 @@ EXTERN char e_undefined_variable_str[] EXTERN char e_undefined_variable_char_str[] INIT(= N_("E121: Undefined variable: %c:%s")); #endif +#ifndef FEAT_DIGRAPHS +EXTERN char e_no_digraphs_version[] + INIT(= N_("E196: No digraphs in this version")); +#endif EXTERN char e_ambiguous_use_of_user_defined_command[] INIT(= N_("E464: Ambiguous use of user-defined command")); EXTERN char e_invalid_command[] @@ -508,3 +512,11 @@ EXTERN char e_bool_required_for_argument INIT(= N_("E1212: Bool required for argument %d")); EXTERN char e_redefining_imported_item_str[] INIT(= N_("E1213: Redefining imported item %s")); +#if defined(FEAT_DIGRAPHS) && defined(FEAT_EVAL) +EXTERN char e_digraph_must_be_just_two_characters_str[] + INIT(= N_("E1214: Digraph must be just two characters: %s")); +EXTERN char e_digraph_argument_must_be_one_character_str[] + INIT(= N_("E1215: Digraph must be one character: %s")); +EXTERN char e_setdigraphlist_argument_must_be_list_of_lists_with_two_items[] + INIT(= N_("E1216: setdigraphlist() argument must be a list of lists with two items")); +#endif diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -493,6 +493,7 @@ static argcheck_T arg1_chan_or_job[] = { static argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr}; static argcheck_T arg2_number[] = {arg_number, arg_number}; static argcheck_T arg2_string[] = {arg_string, arg_string}; +static argcheck_T arg2_string_number[] = {arg_string, arg_number}; static argcheck_T arg2_list_nr[] = {arg_list_number, arg_list_number}; static argcheck_T arg2_nr_string[] = {arg_number, arg_string}; static argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string}; @@ -585,6 +586,12 @@ ret_list_items(int argcount UNUSED, type { return &t_list_list_any; } + + static type_T * +ret_list_string_items(int argcount UNUSED, type_T **argtypes UNUSED) +{ + return &t_list_list_string; +} static type_T * ret_dict_any(int argcount UNUSED, type_T **argtypes UNUSED) { @@ -1107,6 +1114,10 @@ static funcentry_T global_functions[] = ret_list_number, f_getcursorcharpos}, {"getcwd", 0, 2, FEARG_1, arg2_number, ret_string, f_getcwd}, + {"getdigraph", 1, 1, FEARG_1, arg1_string, + ret_string, f_getdigraph}, + {"getdigraphlist", 0, 1, FEARG_1, arg1_number, + ret_list_string_items, f_getdigraphlist}, {"getenv", 1, 1, FEARG_1, arg1_string, ret_any, f_getenv}, {"getfontname", 0, 1, 0, arg1_string, @@ -1567,6 +1578,10 @@ static funcentry_T global_functions[] = ret_number_bool, f_setcmdpos}, {"setcursorcharpos", 1, 3, FEARG_1, NULL, ret_number_bool, f_setcursorcharpos}, + {"setdigraph", 2, 2, FEARG_1, arg2_string_number, + ret_bool, f_setdigraph}, + {"setdigraphlist", 1, 1, FEARG_1, arg1_list_string, + ret_bool, f_setdigraphlist}, {"setenv", 2, 2, FEARG_2, NULL, ret_void, f_setenv}, {"setfperm", 2, 2, FEARG_1, arg2_string, diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -9315,7 +9315,7 @@ ex_digraphs(exarg_T *eap UNUSED) else listdigraphs(eap->forceit); #else - emsg(_("E196: No digraphs in this version")); + emsg(_(e_no_digraphs_version)); #endif } diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -442,6 +442,7 @@ EXTERN type_T t_list_string INIT6(VAR_LI EXTERN type_T t_list_job INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_job, NULL); EXTERN type_T t_list_dict_any INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_dict_any, NULL); EXTERN type_T t_list_list_any INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_any, NULL); +EXTERN type_T t_list_list_string INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_string, NULL); EXTERN type_T t_dict_bool INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_bool, NULL); EXTERN type_T t_dict_number INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_number, NULL); @@ -1805,6 +1806,7 @@ EXTERN char e_nowhitespace[] INIT(= N_(" EXTERN char e_lock_unlock[] INIT(= N_("E940: Cannot lock or unlock variable %s")); #endif + #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) EXTERN char e_alloc_color[] INIT(= N_("E254: Cannot allocate color %s")); #endif diff --git a/src/proto/digraph.pro b/src/proto/digraph.pro --- a/src/proto/digraph.pro +++ b/src/proto/digraph.pro @@ -3,8 +3,14 @@ int do_digraph(int c); char_u *get_digraph_for_char(int val_arg); int get_digraph(int cmdline); int getdigraph(int char1, int char2, int meta_char); +int check_digraph_chars_valid(int char1, int char2); void putdigraph(char_u *str); void listdigraphs(int use_headers); +void getdigraphlist_common(int list_all, typval_T *rettv); +void f_getdigraph(typval_T *argvars, typval_T *rettv); +void f_getdigraphlist(typval_T *argvars, typval_T *rettv); +void f_setdigraph(typval_T *argvars, typval_T *rettv); +void f_setdigraphlist(typval_T *argvars, typval_T *rettv); char *keymap_init(void); void ex_loadkeymap(exarg_T *eap); void keymap_clear(garray_T *kmap); diff --git a/src/testdir/test_digraph.vim b/src/testdir/test_digraph.vim --- a/src/testdir/test_digraph.vim +++ b/src/testdir/test_digraph.vim @@ -214,7 +214,7 @@ func Test_digraphs() call assert_fails('exe "digraph a\ 100"', 'E104:') call assert_fails('exe "digraph \a 100"', 'E104:') call assert_fails('digraph xy z', 'E39:') - call assert_fails('digraph x', 'E474:') + call assert_fails('digraph x', 'E1214:') bw! endfunc @@ -515,4 +515,81 @@ func Test_entering_digraph() call StopVimInTerminal(buf) endfunc +func Test_setdigraph_function() + new + call setdigraph('aa', 'あ') + call Put_Dig('aa') + call assert_equal('あ', getline('$')) + call setdigraph(' i', 'い') + call Put_Dig(' i') + call assert_equal('い', getline('$')) + call setdigraph(' ', 'う') + call Put_Dig(' ') + call assert_equal('う', getline('$')) + + eval 'aa'->setdigraph('え') + call Put_Dig('aa') + call assert_equal('え', getline('$')) + + call assert_fails('call setdigraph("aaa", "あ")', 'E1214: Digraph must be just two characters: aaa') + call assert_fails('call setdigraph("b", "あ")', 'E1214: Digraph must be just two characters: b') + call assert_fails('call setdigraph("あ", "あ")', 'E1214: Digraph must be just two characters: あ') + call assert_fails('call setdigraph("aa", "ああ")', 'E1215: Digraph must be one character: ああ') + call assert_fails('call setdigraph("aa", "か" .. nr2char(0x3099))', 'E1215: Digraph must be one character: か' .. nr2char(0x3099)) + bwipe! +endfunc + +func Test_getdigraph_function() + " Built-in digraphs + call assert_equal('∞', getdigraph('00')) + + " User-defined digraphs + call setdigraph('aa', 'あ') + call setdigraph(' i', 'い') + call setdigraph(' ', 'う') + call assert_equal('あ', getdigraph('aa')) + call assert_equal('あ', 'aa'->getdigraph()) + call assert_equal('い', getdigraph(' i')) + call assert_equal('う', getdigraph(' ')) + call assert_fails('call getdigraph("aaa")', 'E1214: Digraph must be just two characters: aaa') + call assert_fails('call getdigraph("b")', 'E1214: Digraph must be just two characters: b') +endfunc + +func Test_getdigraph_function_encode() + CheckFeature iconv + let testcases = { + \'00': '∞', + \'aa': 'あ', + \} + for [key, ch] in items(testcases) + call setdigraph(key, ch) + set encoding=japan + call assert_equal(iconv(ch, 'utf-8', 'japan'), getdigraph(key)) + set encoding& + endfor +endfunc + +func Test_setdigraphlist_function() + call setdigraphlist([['aa', 'き'], ['bb', 'く']]) + call assert_equal('き', getdigraph('aa')) + call assert_equal('く', getdigraph('bb')) + + call assert_fails('call setdigraphlist([[]])', 'E1216:') + call assert_fails('call setdigraphlist([["aa", "b", "cc"]])', '1216:') + call assert_fails('call setdigraphlist([["あ", "あ"]])', 'E1214: Digraph must be just two characters: あ') +endfunc + +func Test_getdigraphlist_function() + " Make sure user-defined digraphs are defined + call setdigraphlist([['aa', 'き'], ['bb', 'く']]) + + for pair in getdigraphlist(1) + call assert_equal(getdigraph(pair[0]), pair[1]) + endfor + + " We don't know how many digraphs are registered before, so check the number + " of digraphs returned. + call assert_equal(getdigraphlist()->len(), getdigraphlist(0)->len()) + call assert_notequal((getdigraphlist()->len()), getdigraphlist(1)->len()) +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3184, +/**/ 3183, /**/ 3182,