Patch 8.2.3184
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)
Files:      runtime/doc/digraph.txt, runtime/doc/eval.txt,
            runtime/doc/usr_41.txt, src/digraph.c, src/evalfunc.c,
            src/ex_docmd.c, src/globals.h, src/errors.h,
            src/proto/digraph.pro, src/testdir/test_digraph.vim


*** ../vim-8.2.3183/runtime/doc/digraph.txt     2021-01-31 17:02:06.246490203 
+0100
--- runtime/doc/digraph.txt     2021-07-19 18:57:04.350126301 +0200
***************
*** 38,43 ****
--- 38,46 ----
  <                     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.
*** ../vim-8.2.3183/runtime/doc/eval.txt        2021-07-03 19:27:32.690065101 
+0200
--- runtime/doc/eval.txt        2021-07-19 19:11:05.959967096 +0200
***************
*** 2603,2608 ****
--- 2620,2627 ----
  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}
***************
*** 2869,2874 ****
--- 2888,2895 ----
  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}
***************
*** 5542,5547 ****
--- 5582,5642 ----
  <             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
***************
*** 9445,9450 ****
--- 9576,9629 ----
                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.
*** ../vim-8.2.3183/runtime/doc/usr_41.txt      2021-06-23 20:46:46.914256853 
+0200
--- runtime/doc/usr_41.txt      2021-07-19 19:11:32.315908360 +0200
***************
*** 992,997 ****
--- 1000,1009 ----
        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
*** ../vim-8.2.3183/src/digraph.c       2020-09-08 19:05:41.723819080 +0200
--- src/digraph.c       2021-07-19 19:42:05.716206316 +0200
***************
*** 1993,1998 ****
--- 1993,2057 ----
  }
  
  /*
+  * 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,2007 ****
  putdigraph(char_u *str)
  {
      int               char1, char2, n;
-     int               i;
-     digr_T    *dp;
  
      while (*str != NUL)
      {
--- 2059,2064 ----
***************
*** 2010,2025 ****
            return;
        char1 = *str++;
        char2 = *str++;
!       if (char2 == 0)
!       {
!           emsg(_(e_invarg));
!           return;
!       }
!       if (char1 == ESC || char2 == ESC)
!       {
!           emsg(_("E104: Escape not allowed in digraph"));
            return;
!       }
        str = skipwhite(str);
        if (!VIM_ISDIGIT(*str))
        {
--- 2067,2076 ----
            return;
        char1 = *str++;
        char2 = *str++;
! 
!       if (!check_digraph_chars_valid(char1, char2))
            return;
! 
        str = skipwhite(str);
        if (!VIM_ISDIGIT(*str))
        {
***************
*** 2028,2057 ****
        }
        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;
!           }
!       }
      }
  }
  
--- 2079,2085 ----
        }
        n = getdigits(&str);
  
!       registerdigraph(char1, char2, n);
      }
  }
  
***************
*** 2114,2119 ****
--- 2142,2238 ----
                            // 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,2217 ****
--- 2329,2535 ----
      }
  }
  
+ # 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
*** ../vim-8.2.3183/src/evalfunc.c      2021-07-17 19:11:03.576709073 +0200
--- src/evalfunc.c      2021-07-19 19:35:37.493136385 +0200
***************
*** 493,498 ****
--- 493,499 ----
  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,590 ****
--- 586,597 ----
  {
      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,1112 ****
--- 1114,1123 ----
                        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,1572 ****
--- 1578,1587 ----
                        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,
*** ../vim-8.2.3183/src/ex_docmd.c      2021-06-27 22:03:28.641707728 +0200
--- src/ex_docmd.c      2021-07-19 19:37:00.388922056 +0200
***************
*** 9315,9321 ****
      else
        listdigraphs(eap->forceit);
  #else
!     emsg(_("E196: No digraphs in this version"));
  #endif
  }
  
--- 9315,9321 ----
      else
        listdigraphs(eap->forceit);
  #else
!     emsg(_(e_no_digraphs_version));
  #endif
  }
  
*** ../vim-8.2.3183/src/globals.h       2021-07-17 19:11:03.576709073 +0200
--- src/globals.h       2021-07-19 18:43:42.211288993 +0200
***************
*** 442,447 ****
--- 442,448 ----
  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,1810 ****
--- 1806,1812 ----
  
  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
*** ../vim-8.2.3183/src/errors.h        2021-07-19 10:38:45.402686087 +0200
--- src/errors.h        2021-07-19 18:55:57.530221475 +0200
***************
*** 54,59 ****
--- 54,63 ----
  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,510 ****
--- 512,522 ----
        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
*** ../vim-8.2.3183/src/proto/digraph.pro       2019-12-12 12:55:17.000000000 
+0100
--- src/proto/digraph.pro       2021-07-19 19:30:12.405791033 +0200
***************
*** 3,10 ****
--- 3,16 ----
  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);
*** ../vim-8.2.3183/src/testdir/test_digraph.vim        2020-08-20 
18:59:02.106779176 +0200
--- src/testdir/test_digraph.vim        2021-07-19 19:43:15.476054837 +0200
***************
*** 214,220 ****
    call assert_fails('exe "digraph a\<Esc> 100"', 'E104:')
    call assert_fails('exe "digraph \<Esc>a 100"', 'E104:')
    call assert_fails('digraph xy z', 'E39:')
!   call assert_fails('digraph x', 'E474:')
    bw!
  endfunc
  
--- 214,220 ----
    call assert_fails('exe "digraph a\<Esc> 100"', 'E104:')
    call assert_fails('exe "digraph \<Esc>a 100"', 'E104:')
    call assert_fails('digraph xy z', 'E39:')
!   call assert_fails('digraph x', 'E1214:')
    bw!
  endfunc
  
***************
*** 515,518 ****
--- 515,595 ----
    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
*** ../vim-8.2.3183/src/version.c       2021-07-19 10:38:45.406686083 +0200
--- src/version.c       2021-07-19 18:42:16.491417608 +0200
***************
*** 757,758 ****
--- 757,760 ----
  {   /* Add new patch number below this line */
+ /**/
+     3184,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
184. You no longer ask prospective dates what their sign is, instead
     your line is "Hi, what's your URL?"

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202107191807.16JI7oKA3080186%40masaka.moolenaar.net.

Raspunde prin e-mail lui