diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index e6747adcfd..9f91f47d42 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2025 Apr 23 +*builtin.txt* For Vim version 9.1. Last change: 2025 Apr 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -136,6 +136,7 @@ complete({startcol}, {matches}) none set Insert mode completion complete_add({expr}) Number add completion match complete_check() Number check for key typed during completion complete_info([{what}]) Dict get current completion information +complete_match([{lnum}, {col}]) List get completion column and trigger text confirm({msg} [, {choices} [, {default} [, {type}]]]) Number number of choice picked by user copy({expr}) any make a shallow copy of {expr} @@ -2032,6 +2033,50 @@ complete_info([{what}]) *complete_info()* < Return type: dict +complete_match([{lnum}, {col}]) *complete_match()* + Returns a List of matches found according to the 'isexpand' + option. Each match is represented as a List containing + [startcol, trigger_text] where: + - startcol: column position where completion should start, + or -1 if no trigger position is found. For multi-character + triggers, returns the column of the first character. + - trigger_text: the matching trigger string from 'isexpand', + or empty string if no match was found or when using the + default 'iskeyword' pattern. + + When 'isexpand' is empty, uses the 'iskeyword' pattern + "\k\+$" to find the start of the current keyword. + + When no arguments are provided, uses the current cursor + position. + + Examples: > + set isexpand=.,->,/,/*,abc + func CustomComplete() + let res = complete_match() + if res->len() == 0 | return | endif + let [col, trigger] = res[0] + let items = [] + if trigger == '/*' + let items = ['/** */'] + elseif trigger == '/' + let items = ['/*! */', '// TODO:', '// fixme:'] + elseif trigger == '.' + let items = ['length()'] + elseif trigger =~ '^\->' + let items = ['map()', 'reduce()'] + elseif trigger =~ '^\abc' + let items = ['def', 'ghk'] + endif + if items->len() > 0 + let startcol = trigger =~ '^/' ? col : col + len(trigger) + call complete(startcol, items) + endif + endfunc + inoremap call CustomComplete() +< + Return type: list> + *confirm()* confirm({msg} [, {choices} [, {default} [, {type}]]]) confirm() offers the user a dialog, from which a choice can be diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 8073457a02..03a6a6c5c3 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.1. Last change: 2025 Apr 19 +*options.txt* For Vim version 9.1. Last change: 2025 Apr 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4983,6 +4983,19 @@ A jump table for the options with a short description can be found at |Q_op|. and there is a letter before it, the completed part is made uppercase. With 'noinfercase' the match is used as-is. + *'isexpand'* *'ise'* +'isexpand' 'ise' string (default: "") + local to buffer + Defines characters and patterns for completion in insert mode. Used by + the |complete_match()| function to determine the starting position for + completion. This is a comma-separated list of triggers. Each trigger + can be: + - A single character like "." or "/" + - A sequence of characters like "->", "/*", or "/**" + + Note: Use "\\," to add a literal comma as trigger character, see + |option-backslash|. + *'insertmode'* *'im'* *'noinsertmode'* *'noim'* 'insertmode' 'im' boolean (default off) global diff --git a/runtime/doc/tags b/runtime/doc/tags index 636977084a..a094e14837 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -436,6 +436,8 @@ $quote eval.txt /*$quote* 'infercase' options.txt /*'infercase'* 'insertmode' options.txt /*'insertmode'* 'is' options.txt /*'is'* +'ise' options.txt /*'ise'* +'isexpand' options.txt /*'isexpand'* 'isf' options.txt /*'isf'* 'isfname' options.txt /*'isfname'* 'isi' options.txt /*'isi'* @@ -6663,6 +6665,7 @@ complete_add() builtin.txt /*complete_add()* complete_check() builtin.txt /*complete_check()* complete_info() builtin.txt /*complete_info()* complete_info_mode builtin.txt /*complete_info_mode* +complete_match() builtin.txt /*complete_match()* completed_item-variable eval.txt /*completed_item-variable* completion-functions usr_41.txt /*completion-functions* complex-change change.txt /*complex-change* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index a3f2d7cfcf..5223687870 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 9.1. Last change: 2025 Mar 27 +*todo.txt* For Vim version 9.1. Last change: 2025 Apr 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4749,20 +4749,10 @@ Insert mode completion/expansion: 7 When expanding file names with an environment variable, add the match with the unexpanded var. So $HOME/tm expands to "/home/guy/tmp" and "$HOME/tmp" -8 When there is no word before the cursor but something like "sys." complete - with "sys.". Works well for C and similar languages. 9 ^X^L completion doesn't repeat correctly. It uses the first match with the last added line, instead of continuing where the last match ended. (Webb) -8 Add option to set different behavior for Insert mode completion: - - ignore/match case - - different characters than 'iskeyword' -8 Add option 'isexpand', containing characters when doing expansion (so that - "." and "\" can be included, without changing 'iskeyword'). (Goldfarb) - Also: 'istagword': characters used for CTRL-]. - When 'isexpand' or 'istagword' are empty, use 'iskeyword'. - Alternative: Use a pattern so that start and end of a keyword can be - defined, only allow dash in the middle, etc. +8 Add option 'istagword': characters used for CTRL-]. like 'isexpand' 8 Add a command to undo the completion, go back to the original text. 7 Completion of an abbreviation: Can leave letters out, like what Instant text does: www.textware.com diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 0c24b8469f..a22b6f7980 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1,4 +1,4 @@ -*usr_41.txt* For Vim version 9.1. Last change: 2025 Apr 21 +*usr_41.txt* For Vim version 9.1. Last change: 2025 Apr 24 VIM USER MANUAL - by Bram Moolenaar @@ -1124,6 +1124,8 @@ Insert mode completion: *completion-functions* complete_add() add to found matches complete_check() check if completion should be aborted complete_info() get current completion information + complete_match() get insert completion start match col and + trigger text pumvisible() check if the popup menu is displayed pum_getpos() position and size of popup menu if visible diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index dfbe457a26..9560b1dfb9 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2025 Apr 23 +*version9.txt* For Vim version 9.1. Last change: 2025 Apr 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41688,6 +41688,7 @@ Functions: ~ |blob2str()| convert a blob into a List of strings |bindtextdomain()| set message lookup translation base path |cmdcomplete_info()| get current cmdline completion info +|complete_match()| get completion and trigger info |diff()| diff two Lists of strings |filecopy()| copy a file {from} to {to} |foreach()| apply function to List items @@ -41750,6 +41751,7 @@ Options: ~ 'eventignorewin' autocommand events that are ignored in a window 'findfunc' Vim function to obtain the results for a |:find| command +'isexpand' defines triggers for completion 'lhistory' Size of the location list stack |quickfix-stack|. 'messagesopt' configure |:messages| and |hit-enter| prompt 'pummaxwidth' maximum width for the completion popup menu diff --git a/runtime/optwin.vim b/runtime/optwin.vim index c5e77afd78..941a63c40f 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -1,7 +1,7 @@ " These commands create the option window. " " Maintainer: The Vim Project -" Last Change: 2025 Apr 07 +" Last Change: 2025 Apr 24 " Former Maintainer: Bram Moolenaar " If there already is an option window, jump to that one. @@ -1254,6 +1254,8 @@ call AddOption("isfname", gettext("specifies the characters in a file name" call OptionG("isf", &isf) call AddOption("isident", gettext("specifies the characters in an identifier")) call OptionG("isi", &isi) +call AddOption("isexpand", gettext("defines trigger strings for complete_match()")) +call append("$", "\t" .. s:local_to_buffer) call AddOption("iskeyword", gettext("specifies the characters in a keyword")) call append("$", "\t" .. s:local_to_buffer) call OptionL("isk") diff --git a/src/buffer.c b/src/buffer.c index 0624f9dced..697efa30cf 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2494,6 +2494,7 @@ free_buf_options( clear_string_option(&buf->b_p_cinw); clear_string_option(&buf->b_p_cot); clear_string_option(&buf->b_p_cpt); + clear_string_option(&buf->b_p_ise); #ifdef FEAT_COMPL_FUNC clear_string_option(&buf->b_p_cfu); free_callback(&buf->b_cfu_cb); diff --git a/src/evalfunc.c b/src/evalfunc.c index 39f6aa9abf..3b13cf0d2b 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2104,6 +2104,8 @@ static funcentry_T global_functions[] = ret_number_bool, f_complete_check}, {"complete_info", 0, 1, FEARG_1, arg1_list_string, ret_dict_any, f_complete_info}, + {"complete_match", 0, 2, 0, NULL, + ret_list_any, f_complete_match}, {"confirm", 1, 4, FEARG_1, arg4_string_string_number_string, ret_number, f_confirm}, {"copy", 1, 1, FEARG_1, NULL, diff --git a/src/insexpand.c b/src/insexpand.c index ace4f55b57..77c98311d2 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -3550,6 +3550,147 @@ f_complete_check(typval_T *argvars UNUSED, typval_T *rettv) RedrawingDisabled = save_RedrawingDisabled; } +/* + * Add match item to the return list. + * Returns FAIL if out of memory, OK otherwise. + */ + static int +add_match_to_list( + typval_T *rettv, + char_u *str, + int len, + int pos) +{ + list_T *match; + int ret; + + match = list_alloc(); + if (match == NULL) + return FAIL; + + if ((ret = list_append_number(match, pos + 1)) == FAIL + || (ret = list_append_string(match, str, len)) == FAIL + || (ret = list_append_list(rettv->vval.v_list, match)) == FAIL) + { + vim_free(match); + return FAIL; + } + + return OK; +} + +/* + * "complete_match()" function + */ + void +f_complete_match(typval_T *argvars, typval_T *rettv) +{ + linenr_T lnum; + colnr_T col; + char_u *line = NULL; + char_u *ise = NULL; + regmatch_T regmatch; + char_u *before_cursor = NULL; + char_u *cur_end = NULL; + char_u *trig = NULL; + int bytepos = 0; + char_u part[MAXPATHL]; + int ret; + + if (rettv_list_alloc(rettv) == FAIL) + return; + + ise = curbuf->b_p_ise[0] != NUL ? curbuf->b_p_ise : p_ise; + + if (argvars[0].v_type == VAR_UNKNOWN) + { + lnum = curwin->w_cursor.lnum; + col = curwin->w_cursor.col; + } + else if (argvars[1].v_type == VAR_UNKNOWN) + { + emsg(_(e_invalid_argument)); + return; + } + else + { + lnum = (linenr_T)tv_get_number(&argvars[0]); + col = (colnr_T)tv_get_number(&argvars[1]); + if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) + { + semsg(_(e_invalid_line_number_nr), lnum); + return; + } + if (col < 1 || col > ml_get_buf_len(curbuf, lnum)) + { + semsg(_(e_invalid_column_number_nr), col + 1); + return; + } + } + + line = ml_get_buf(curbuf, lnum, FALSE); + if (line == NULL) + return; + + before_cursor = vim_strnsave(line, col); + if (before_cursor == NULL) + return; + + if (ise == NULL || *ise == NUL) + { + regmatch.regprog = vim_regcomp((char_u *)"\\k\\+$", RE_MAGIC); + if (regmatch.regprog != NULL) + { + if (vim_regexec_nl(®match, before_cursor, (colnr_T)0)) + { + bytepos = (int)(regmatch.startp[0] - before_cursor); + trig = vim_strnsave(regmatch.startp[0], + regmatch.endp[0] - regmatch.startp[0]); + if (trig == NULL) + { + vim_free(before_cursor); + return; + } + + ret = add_match_to_list(rettv, trig, -1, bytepos); + vim_free(trig); + if (ret == FAIL) + { + vim_free(trig); + vim_regfree(regmatch.regprog); + return; + } + } + vim_regfree(regmatch.regprog); + } + } + else + { + char_u *p = ise; + cur_end = before_cursor + (int)STRLEN(before_cursor); + + while (*p != NUL) + { + int len = copy_option_part(&p, part, MAXPATHL, ","); + + if (len > 0 && len <= col) + { + if (STRNCMP(cur_end - len, part, len) == 0) + { + bytepos = col - len; + if (add_match_to_list(rettv, part, len, bytepos) == FAIL) + { + vim_free(before_cursor); + return; + } + } + } + } + } + + vim_free(before_cursor); +} + /* * Return Insert completion mode name string */ diff --git a/src/option.c b/src/option.c index cfdeb44e10..ab9ee66cf3 100644 --- a/src/option.c +++ b/src/option.c @@ -6400,6 +6400,9 @@ unset_global_local_option(char_u *name, void *from) clear_string_option(&buf->b_p_cot); buf->b_cot_flags = 0; break; + case PV_ISE: + clear_string_option(&buf->b_p_ise); + break; case PV_DICT: clear_string_option(&buf->b_p_dict); break; @@ -6518,6 +6521,7 @@ get_varp_scope(struct vimoption *p, int scope) case PV_INC: return (char_u *)&(curbuf->b_p_inc); #endif case PV_COT: return (char_u *)&(curbuf->b_p_cot); + case PV_ISE: return (char_u *)&(curbuf->b_p_ise); case PV_DICT: return (char_u *)&(curbuf->b_p_dict); case PV_TSR: return (char_u *)&(curbuf->b_p_tsr); #ifdef FEAT_COMPL_FUNC @@ -6600,6 +6604,8 @@ get_varp(struct vimoption *p) #endif case PV_COT: return *curbuf->b_p_cot != NUL ? (char_u *)&(curbuf->b_p_cot) : p->var; + case PV_ISE: return *curbuf->b_p_ise != NUL + ? (char_u *)&(curbuf->b_p_ise) : p->var; case PV_DICT: return *curbuf->b_p_dict != NUL ? (char_u *)&(curbuf->b_p_dict) : p->var; case PV_TSR: return *curbuf->b_p_tsr != NUL @@ -7431,6 +7437,7 @@ buf_copy_options(buf_T *buf, int flags) buf->b_cot_flags = 0; buf->b_p_dict = empty_option; buf->b_p_tsr = empty_option; + buf->b_p_ise = empty_option; #ifdef FEAT_COMPL_FUNC buf->b_p_tsrfu = empty_option; #endif diff --git a/src/option.h b/src/option.h index db1030d124..bb1226e44e 100644 --- a/src/option.h +++ b/src/option.h @@ -731,6 +731,7 @@ EXTERN char_u *p_inde; // 'indentexpr' EXTERN char_u *p_indk; // 'indentkeys' #endif EXTERN int p_im; // 'insertmode' +EXTERN char_u *p_ise; // 'isexpand' EXTERN char_u *p_isf; // 'isfname' EXTERN char_u *p_isi; // 'isident' EXTERN char_u *p_isk; // 'iskeyword' @@ -1205,6 +1206,7 @@ enum , BV_INEX #endif , BV_INF + , BV_ISE , BV_ISK #ifdef FEAT_CRYPT , BV_KEY diff --git a/src/optiondefs.h b/src/optiondefs.h index 8ed4ebe781..f035104406 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -90,6 +90,7 @@ # define PV_INEX OPT_BUF(BV_INEX) #endif #define PV_INF OPT_BUF(BV_INF) +#define PV_ISE OPT_BOTH(OPT_BUF(BV_ISE)) #define PV_ISK OPT_BUF(BV_ISK) #ifdef FEAT_CRYPT # define PV_KEY OPT_BUF(BV_KEY) @@ -1458,6 +1459,10 @@ static struct vimoption options[] = {"insertmode", "im", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_im, PV_NONE, did_set_insertmode, NULL, {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, + {"isexpand", "ise", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, + (char_u *)&p_ise, PV_ISE, did_set_isexpand, NULL, + {(char_u *)"", (char_u *)0L} + SCTX_INIT}, {"isfname", "isf", P_STRING|P_VI_DEF|P_COMMA|P_NODUP, (char_u *)&p_isf, PV_NONE, did_set_isopt, NULL, { diff --git a/src/optionstr.c b/src/optionstr.c index 90b8e52ffb..f60957eb23 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -310,6 +310,7 @@ check_buf_options(buf_T *buf) check_string_option(&buf->b_p_cinw); check_string_option(&buf->b_p_cot); check_string_option(&buf->b_p_cpt); + check_string_option(&buf->b_p_ise); #ifdef FEAT_COMPL_FUNC check_string_option(&buf->b_p_cfu); check_string_option(&buf->b_p_ofu); @@ -2864,6 +2865,48 @@ did_set_imactivatekey(optset_T *args UNUSED) } #endif +/* + * The 'isexpand' option is changed. + */ + char * +did_set_isexpand(optset_T *args) +{ + char_u *ise = p_ise; + char_u *p; + int last_was_comma = FALSE; + + if (args->os_flags & OPT_LOCAL) + ise = curbuf->b_p_ise; + + for (p = ise; *p != NUL;) + { + if (*p == '\\' && p[1] == ',') + { + p += 2; + last_was_comma = FALSE; + continue; + } + + if (*p == ',') + { + if (last_was_comma) + return e_invalid_argument; + last_was_comma = TRUE; + p++; + continue; + } + + last_was_comma = FALSE; + MB_PTR_ADV(p); + } + + if (last_was_comma) + return e_invalid_argument; + + return NULL; +} + + /* * The 'iskeyword' option is changed. */ diff --git a/src/proto/insexpand.pro b/src/proto/insexpand.pro index 8529b7b6c1..e9ff62661b 100644 --- a/src/proto/insexpand.pro +++ b/src/proto/insexpand.pro @@ -67,4 +67,5 @@ void ins_compl_check_keys(int frequency, int in_compl_func); int ins_complete(int c, int enable_pum); void free_insexpand_stuff(void); int ins_compl_cancel(void); +void f_complete_match(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro index dc1fb0a10c..4c4ec3e47c 100644 --- a/src/proto/optionstr.pro +++ b/src/proto/optionstr.pro @@ -101,6 +101,7 @@ char *did_set_highlight(optset_T *args); int expand_set_highlight(optexpand_T *args, int *numMatches, char_u ***matches); char *did_set_iconstring(optset_T *args); char *did_set_imactivatekey(optset_T *args); +char *did_set_isexpand(optset_T *args); char *did_set_iskeyword(optset_T *args); char *did_set_isopt(optset_T *args); char *did_set_jumpoptions(optset_T *args); diff --git a/src/structs.h b/src/structs.h index b5c898d163..45e1b189eb 100644 --- a/src/structs.h +++ b/src/structs.h @@ -3302,6 +3302,7 @@ struct file_buffer char_u *b_p_fo; // 'formatoptions' char_u *b_p_flp; // 'formatlistpat' int b_p_inf; // 'infercase' + char_u *b_p_ise; // 'isexpand' local value char_u *b_p_isk; // 'iskeyword' #ifdef FEAT_FIND_ID char_u *b_p_def; // 'define' local value diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim index a0876290f3..3d798e9f86 100644 --- a/src/testdir/gen_opt_test.vim +++ b/src/testdir/gen_opt_test.vim @@ -229,6 +229,7 @@ let test_values = { \ 'imactivatekey': [['', 'S-space'], ['xxx']], \ 'isfname': [['', '@', '@,48-52'], ['xxx', '@48']], \ 'isident': [['', '@', '@,48-52'], ['xxx', '@48']], + \ 'isexpand': [['', '.,->', '/,/*,\\,'], [',,', '\\,,']], \ 'iskeyword': [['', '@', '@,48-52'], ['xxx', '@48']], \ 'isprint': [['', '@', '@,48-52'], ['xxx', '@48']], \ 'jumpoptions': [['', 'stack'], ['xxx']], diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index b03132f7ed..73565a56e2 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -4328,4 +4328,86 @@ func Test_nearest_cpt_option() delfunc PrintMenuWords endfunc +func Test_complete_match() + set isexpand=.,/,->,abc,/*,_ + func TestComplete() + let res = complete_match() + if res->len() == 0 + return + endif + let [startcol, expandchar] = res[0] + + if startcol >= 0 + let line = getline('.') + + let items = [] + if expandchar == '/*' + let items = ['/** */'] + elseif expandchar =~ '^/' + let items = ['/*! */', '// TODO:', '// fixme:'] + elseif expandchar =~ '^\.' && startcol < 4 + let items = ['length()', 'push()', 'pop()', 'slice()'] + elseif expandchar =~ '^\.' && startcol > 4 + let items = ['map()', 'filter()', 'reduce()'] + elseif expandchar =~ '^\abc' + let items = ['def', 'ghk'] + elseif expandchar =~ '^\->' + let items = ['free()', 'xfree()'] + else + let items = ['test1', 'test2', 'test3'] + endif + + call complete(expandchar =~ '^/' ? startcol : startcol + strlen(expandchar), items) + endif + endfunc + + new + inoremap call TestComplete() + + call feedkeys("S/*\\", 'tx') + call assert_equal('/** */', getline('.')) + + call feedkeys("S/\\\", 'tx') + call assert_equal('// TODO:', getline('.')) + + call feedkeys("Swp.\\\", 'tx') + call assert_equal('wp.push()', getline('.')) + + call feedkeys("Swp.property.\\\", 'tx') + call assert_equal('wp.property.filter()', getline('.')) + + call feedkeys("Sp->\\\", 'tx') + call assert_equal('p->xfree()', getline('.')) + + call feedkeys("Swp->property.\\", 'tx') + call assert_equal('wp->property.map()', getline('.')) + + call feedkeys("Sabc\\", 'tx') + call assert_equal('abcdef', getline('.')) + + call feedkeys("S_\\", 'tx') + call assert_equal('_test1', getline('.')) + + set ise& + call feedkeys("Sabc \:let g:result=complete_match()\", 'tx') + call assert_equal([[1, 'abc']], g:result) + + call assert_fails('call complete_match(99, 0)', 'E966:') + call assert_fails('call complete_match(1, 99)', 'E964:') + call assert_fails('call complete_match(1)', 'E474:') + + set ise=你好,好 + call feedkeys("S你好 \:let g:result=complete_match()\", 'tx') + call assert_equal([[1, '你好'], [4, '好']], g:result) + + set ise=\\,,-> + call feedkeys("Sabc, \:let g:result=complete_match()\", 'tx') + call assert_equal([[4, ',']], g:result) + + bw! + unlet g:result + set isexpand& + delfunc TestComplete +endfunc + " vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/src/version.c b/src/version.c index 417088bfa2..8d881242f6 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1341, /**/ 1340, /**/