To: vim_dev@googlegroups.com Subject: Patch 8.2.2239 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2239 Problem: Vim9: concatenating lines with backslash is inconvenient. Solution: Support concatenating lines starting with '|', useful for :autocmd, :command, etc. (closes #6702) Files: runtime/doc/vim9.txt, src/scriptfile.c, src/vim9script.c, src/proto/vim9script.pro, src/vim9compile.c, src/proto/vim9compile.pro, src/userfunc.c, src/structs.h, src/testdir/test_vim9_cmd.vim *** ../vim-8.2.2238/runtime/doc/vim9.txt 2020-12-26 17:43:03.284516767 +0100 --- runtime/doc/vim9.txt 2020-12-28 20:51:45.975623984 +0100 *************** *** 6,12 **** THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE ! Vim9 script commands and expressions. *Vim9* Most expression help is in |eval.txt|. This file is about the new syntax and features in Vim9 script. --- 6,12 ---- THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE ! Vim9 script commands and expressions. *Vim9* *vim9* Most expression help is in |eval.txt|. This file is about the new syntax and features in Vim9 script. *************** *** 113,123 **** To improve readability there must be a space between a command and the # that starts a comment: > ! var = value # comment ! var = value# error! ! In legacy script # is also used for the alternate file name. In Vim9 script ! you need to use %% instead. Instead of ## use %%% (stands for all arguments). Vim9 functions ~ --- 113,124 ---- To improve readability there must be a space between a command and the # that starts a comment: > ! var name = value # comment ! var name = value# error! ! In legacy Vim script # is also used for the alternate file name. In Vim9 ! script you need to use %% instead. Instead of ## use %%% (stands for all ! arguments). Vim9 functions ~ *************** *** 209,221 **** something you don't have to worry about the old name still hanging around. If you do want to keep items, use: > ! vimscript noclear You want to use this in scripts that use a `finish` command to bail out at some point when loaded again. E.g. when a buffer local option is set: > ! vimscript noclear setlocal completefunc=SomeFunc ! if exists('*SomeFunc') | finish | endif def g:SomeFunc() .... --- 210,222 ---- something you don't have to worry about the old name still hanging around. If you do want to keep items, use: > ! vim9script noclear You want to use this in scripts that use a `finish` command to bail out at some point when loaded again. E.g. when a buffer local option is set: > ! vim9script noclear setlocal completefunc=SomeFunc ! if exists('*g:SomeFunc') | finish | endif def g:SomeFunc() .... *************** *** 385,393 **** This does not work: > filter(list, (k, v) => v > 0) ! This also does not work: filter(list, (k, v) => v > 0) Additionally, a lambda can contain statements in {}: > var Lambda = (arg) => { --- 386,398 ---- This does not work: > filter(list, (k, v) => v > 0) ! This also does not work: > filter(list, (k, v) => v > 0) + But you can use a backslash to concatenate the lines before parsing: > + filter(list, (k, + \ v) + \ => v > 0) Additionally, a lambda can contain statements in {}: > var Lambda = (arg) => { *************** *** 404,411 **** Automatic line continuation ~ In many cases it is obvious that an expression continues on the next line. In ! those cases there is no need to prefix the line with a backslash ! |line-continuation|. For example, when a list spans multiple lines: > var mylist = [ 'one', 'two', --- 409,416 ---- Automatic line continuation ~ In many cases it is obvious that an expression continues on the next line. In ! those cases there is no need to prefix the line with a backslash (see ! |line-continuation|). For example, when a list spans multiple lines: > var mylist = [ 'one', 'two', *************** *** 442,447 **** --- 447,458 ---- var result = MyDict .member + For commands that have an argument that is a list of commands, the | character + at the start of the line indicates line continuation: > + autocmd BufNewFile *.match if condition + | echo 'match' + | endif + < *E1050* To make it possible for the operator at the start of the line to be recognized, it is required to put a colon before a range. This will add *************** *** 941,947 **** Namespace ~ ! *:vim9script* *:vim9* To recognize a file that can be imported the `vim9script` statement must appear as the first statement in the file. It tells Vim to interpret the script in its own namespace, instead of the global namespace. If a file --- 952,958 ---- Namespace ~ ! *vim9-namespace* To recognize a file that can be imported the `vim9script` statement must appear as the first statement in the file. It tells Vim to interpret the script in its own namespace, instead of the global namespace. If a file *** ../vim-8.2.2238/src/scriptfile.c 2020-12-28 18:25:56.800886000 +0100 --- src/scriptfile.c 2020-12-28 20:34:26.384424228 +0100 *************** *** 1739,1744 **** --- 1739,1748 ---- struct source_cookie *sp = (struct source_cookie *)cookie; char_u *line; char_u *p; + int do_vim9_all = in_vim9script() + && options == GETLINE_CONCAT_ALL; + int do_vim9_cont = do_vim9_all + || options == GETLINE_CONCAT_CONTDEF; #ifdef FEAT_EVAL // If breakpoints have been added/deleted need to check for it. *************** *** 1785,1801 **** // backslash. We always need to read the next line, keep it in // sp->nextline. /* Also check for a comment in between continuation lines: "\ */ ! // Also check for a Vim9 comment and empty line. sp->nextline = get_one_sourceline(sp); if (sp->nextline != NULL && (*(p = skipwhite(sp->nextline)) == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' ') ! #ifdef FEAT_EVAL ! || (in_vim9script() ! && options == GETLINE_CONCAT_ALL ! && (*p == NUL || vim9_comment_start(p))) ! #endif ! )) { garray_T ga; --- 1789,1803 ---- // backslash. We always need to read the next line, keep it in // sp->nextline. /* Also check for a comment in between continuation lines: "\ */ ! // Also check for a Vim9 comment, empty line, line starting with '|', ! // but not "||". sp->nextline = get_one_sourceline(sp); if (sp->nextline != NULL && (*(p = skipwhite(sp->nextline)) == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' ') ! || (do_vim9_all && (*p == NUL ! || vim9_comment_start(p))) ! || (do_vim9_cont && p[0] == '|' && p[1] != '|'))) { garray_T ga; *************** *** 1803,1808 **** --- 1805,1815 ---- ga_concat(&ga, line); if (*p == '\\') ga_concat(&ga, p + 1); + else if (*p == '|') + { + ga_concat(&ga, (char_u *)" "); + ga_concat(&ga, p); + } for (;;) { vim_free(sp->nextline); *************** *** 1810,1816 **** if (sp->nextline == NULL) break; p = skipwhite(sp->nextline); ! if (*p == '\\') { // Adjust the growsize to the current length to speed up // concatenating many lines. --- 1817,1823 ---- if (sp->nextline == NULL) break; p = skipwhite(sp->nextline); ! if (*p == '\\' || (do_vim9_cont && p[0] == '|' && p[1] != '|')) { // Adjust the growsize to the current length to speed up // concatenating many lines. *************** *** 1821,1835 **** else ga.ga_growsize = ga.ga_len; } ! ga_concat(&ga, p + 1); } else if (!(p[0] == '"' && p[1] == '\\' && p[2] == ' ') ! #ifdef FEAT_EVAL ! && !(in_vim9script() ! && options == GETLINE_CONCAT_ALL ! && (*p == NUL || vim9_comment_start(p))) ! #endif ! ) break; /* drop a # comment or "\ comment line */ } --- 1828,1843 ---- else ga.ga_growsize = ga.ga_len; } ! if (*p == '\\') ! ga_concat(&ga, p + 1); ! else ! { ! ga_concat(&ga, (char_u *)" "); ! ga_concat(&ga, p); ! } } else if (!(p[0] == '"' && p[1] == '\\' && p[2] == ' ') ! && !(do_vim9_all && (*p == NUL || vim9_comment_start(p)))) break; /* drop a # comment or "\ comment line */ } *** ../vim-8.2.2238/src/vim9script.c 2020-12-28 18:25:56.796886014 +0100 --- src/vim9script.c 2020-12-28 18:50:17.024136775 +0100 *************** *** 103,108 **** --- 103,117 ---- return OK; } + /* + * Return TRUE if "p" points at a "#". Does not check for white space. + */ + int + vim9_comment_start(char_u *p) + { + return p[0] == '#'; + } + #if defined(FEAT_EVAL) || defined(PROTO) /* *** ../vim-8.2.2238/src/proto/vim9script.pro 2020-12-27 13:39:44.659044653 +0100 --- src/proto/vim9script.pro 2020-12-28 18:51:46.999832981 +0100 *************** *** 2,7 **** --- 2,8 ---- int in_vim9script(void); void ex_vim9script(exarg_T *eap); int not_in_vim9(exarg_T *eap); + int vim9_comment_start(char_u *p); void ex_export(exarg_T *eap); void free_imports_and_script_vars(int sid); void mark_imports_for_reload(int sid); *** ../vim-8.2.2238/src/vim9compile.c 2020-12-27 14:43:23.493570163 +0100 --- src/vim9compile.c 2020-12-28 18:50:01.620188716 +0100 *************** *** 2165,2179 **** } /* - * Return TRUE if "p" points at a "#". Does not check for white space. - */ - int - vim9_comment_start(char_u *p) - { - return p[0] == '#'; - } - - /* * Return a pointer to the next line that isn't empty or only contains a * comment. Skips over white space. * Returns NULL if there is none. --- 2165,2170 ---- *** ../vim-8.2.2238/src/proto/vim9compile.pro 2020-12-22 17:35:50.043978116 +0100 --- src/proto/vim9compile.pro 2020-12-28 18:51:53.979809385 +0100 *************** *** 5,11 **** int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx); imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx); imported_T *find_imported_in_script(char_u *name, size_t len, int sid); - int vim9_comment_start(char_u *p); char_u *peek_next_line_from_context(cctx_T *cctx); char_u *next_line_from_context(cctx_T *cctx, int skip_comment); char_u *to_name_end(char_u *arg, int use_namespace); --- 5,10 ---- *************** *** 15,21 **** int assignment_len(char_u *p, int *heredoc); void vim9_declare_error(char_u *name); int check_vim9_unlet(char_u *name); ! int compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx); void set_function_type(ufunc_T *ufunc); void delete_instr(isn_T *isn); void unlink_def_function(ufunc_T *ufunc); --- 14,20 ---- int assignment_len(char_u *p, int *heredoc); void vim9_declare_error(char_u *name); int check_vim9_unlet(char_u *name); ! int compile_def_function(ufunc_T *ufunc, int check_return_type, cctx_T *outer_cctx); void set_function_type(ufunc_T *ufunc); void delete_instr(isn_T *isn); void unlink_def_function(ufunc_T *ufunc); *** ../vim-8.2.2238/src/userfunc.c 2020-12-27 14:43:23.493570163 +0100 --- src/userfunc.c 2020-12-28 19:54:47.420670958 +0100 *************** *** 2960,2966 **** static int func_nr = 0; // number for nameless function int paren; hashitem_T *hi; ! getline_opt_T getline_options = GETLINE_CONCAT_CONT; linenr_T sourcing_lnum_off; linenr_T sourcing_lnum_top; int is_heredoc = FALSE; --- 2960,2966 ---- static int func_nr = 0; // number for nameless function int paren; hashitem_T *hi; ! getline_opt_T getline_options; linenr_T sourcing_lnum_off; linenr_T sourcing_lnum_top; int is_heredoc = FALSE; *************** *** 3291,3296 **** --- 3291,3298 ---- indent = 2; nesting = 0; nesting_def[nesting] = (eap->cmdidx == CMD_def); + getline_options = eap->cmdidx == CMD_def + ? GETLINE_CONCAT_CONTDEF : GETLINE_CONCAT_CONT; for (;;) { if (KeyTyped) *************** *** 3365,3371 **** { VIM_CLEAR(skip_until); VIM_CLEAR(heredoc_trimmed); ! getline_options = GETLINE_CONCAT_CONT; is_heredoc = FALSE; } } --- 3367,3374 ---- { VIM_CLEAR(skip_until); VIM_CLEAR(heredoc_trimmed); ! getline_options = eap->cmdidx == CMD_def ! ? GETLINE_CONCAT_CONTDEF : GETLINE_CONCAT_CONT; is_heredoc = FALSE; } } *** ../vim-8.2.2238/src/structs.h 2020-12-28 18:25:56.800886000 +0100 --- src/structs.h 2020-12-28 19:56:12.644458247 +0100 *************** *** 1565,1571 **** // type of getline() last argument typedef enum { GETLINE_NONE, // do not concatenate any lines ! GETLINE_CONCAT_CONT, // concatenate continuation lines GETLINE_CONCAT_ALL // concatenate continuation and Vim9 # comment lines } getline_opt_T; --- 1565,1572 ---- // type of getline() last argument typedef enum { GETLINE_NONE, // do not concatenate any lines ! GETLINE_CONCAT_CONT, // concatenate continuation lines in Vim9 script ! GETLINE_CONCAT_CONTDEF, // concatenate continuation lines always GETLINE_CONCAT_ALL // concatenate continuation and Vim9 # comment lines } getline_opt_T; *** ../vim-8.2.2238/src/testdir/test_vim9_cmd.vim 2020-12-27 18:03:18.688859822 +0100 --- src/testdir/test_vim9_cmd.vim 2020-12-28 20:47:37.825408286 +0100 *************** *** 548,560 **** --- 548,580 ---- bwipe! au BufNewFile Xfile g:readFile = 1 + | g:readExtra = 2 g:readFile = 0 + g:readExtra = 0 edit Xfile assert_equal(1, g:readFile) + assert_equal(2, g:readExtra) bwipe! g:readFile = 0 noautocmd edit Xfile assert_equal(0, g:readFile) + au! BufNewFile + + au BufNewFile Xfile g:readFile = 1 + | g:readExtra = 2 + | g:readMore = 3 + g:readFile = 0 + g:readExtra = 0 + g:readMore = 0 + edit Xfile + assert_equal(1, g:readFile) + assert_equal(2, g:readExtra) + assert_equal(3, g:readMore) + bwipe! + au! BufNewFile + unlet g:readFile + unlet g:readExtra + unlet g:readMore noswapfile edit XnoSwap assert_equal(0, &l:swapfile) *** ../vim-8.2.2238/src/version.c 2020-12-28 18:25:56.800886000 +0100 --- src/version.c 2020-12-28 18:46:20.952929347 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2239, /**/ -- A day without sunshine is like, well, night. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///