Re: Vim9 script: first steps
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 On 05-Jan-2020 01:22 +0100, Prabir Shrestha wrote: > -1 for }. That is the most absurd syntax I have seen in any > language that only uses it for closing. > > So I went and re-read the poll > https://github.com/vim/vim/issues/3573. And here is what I can > think of reading it again in Jan 2020. > > Can we get more info on what does make vim-script faster mean? > > Screen Shot 2020-01-04 at 3.53.13 PM.png > > Screen Shot 2020-01-04 at 4.04.27 PM.png > > Screen Shot 2020-01-04 at 4.05.36 PM.png > > > > Second comment there says about syntax highlighting. So making > vimscript faster here won't help much because > [tree-sitter](https://tree-sitter.github.io/tree-sitter/) will be > lot faster than vimscript, which means syntax highlighting in > neovim will also be more accurate and faster then vim. > > > Instead of picking up non real world examples to demonstrate perf > gains can we pick some proper goals. > > Here are some of the examples I can think of: > > * Faster fuzzy finder. Currently there is 0 plugins that is fast in > pure vimscript. I would like to see an example of FuzzyFinder in > vim9 that is fast as https://github.com/liuchengxu/vim-clap and > https://github.com/junegunn/fzf.vim. Few requirements here: > Searching large number of nested directories and files, > highlighting matches. Some of these I elaborated in this comment > https://github.com/vim/vim/issues/3573#issuecomment-433730939. > > * vim9 syntax highlighting vs neovim tree-sitter syntax > highlighting. We should count speed as well as accuracy. > > * Fuzzy search for auto complete popup menu. > > > I still think WASM is the way to go and not vimscript 9. This way I > can code in what ever language suits me and just ship the bytecode. > > > For example: will vimscript 9 support generics/async,await/pattern > matching/threading or greenthreads/immutability? This list will > keep going on. Making it fast is just one issue it solves. A > language gets attractive not just for perf but many other features > that come around it. > > > Here is a new WASM runtime since I last mentioned which claims to > be 15x faster then other c wasm runtimes. > https://github.com/wasm3/wasm3. > > > As a plugin author I can then code in any languages I want that > suits the needed. For example a python dev might write in python, a > JS dev might right in Javascript or Typescript if they need typing. > And they can still write in go/rust/zig or even c if they need > performance. And most languages these days already support > compiling to WASM. I agree; most performance issues I encounter are in syntax highlighting with large, often deeply nested structures (like big XML or JSON files). Poor Vimscript performance hardly is an issue for the kind of plugins that I write; and it's always been possible to use a language binding and reimplement the core parts, or call out to an external program (now even easier with the jobs feature). If WASM is the future (and you present enticing arguments here), deprecating the many existing language bindings in favor of WASM as the single go-forward integration would indeed contribute to a simplified code base, avoid fragmented plugin requirements, and therefore reduce compatibility issues in the diverse user base. Still, if Bram has ideas about eliminating some inefficiencies of Vimscript, so that Vimscript writers can easily opt-in (ideally, in a backwards-compatible way and without rewriting entire functions or plugins), why not? Vim, with its great backwards compatibility and platform support, has been a pleasure to use and extend for many many years; I'll happily let Bram indulge in such pet projects (and the accompanying bike shedding about syntax details :-) if that's what keeps him happy and committed to the project! - -- regards, ingo - -- -- Ingo Karkat -- /^-- /^-- /^-- /^-- /^-- http://ingo-karkat.de/ -- -- https://www.vim.org/account/profile.php?user_id=9713 -- -BEGIN PGP SIGNATURE- Version: GnuPG v2 iQEcBAEBCAAGBQJeEa+8AAoJEA7ziXlAzQ/vX3wH/35PUWts94SNz8IGT2PCG24V Cs7x14Zj4774qjL6ZWi+rn/7pdzUAzTqapsBoLdBz8qZM3bjV/J0ydwg8D8xSYzo tCS3LwHL6wGOYpYmg8KuB7+joAkn5TCfOH69f5aXwAje6fL0g91aigYGRmR35Bze IX0sQwfLesH/zArL1qk7G8pqjrRmmSpG63zyABOeYaTPbKB6rwJ/Dy9vsRdjDAEM Y/vzqnC6aGHCjGhD/kVzlBaFZTV4YD2TxDdHSXRd+47j5LRr0J4QKLYJj91wgzCE je5vZn1OTETlAUXzI9+B1u12/XVYEFba4PFQr5EfAY81cZXoF0aWhJ6rwPj1Xj8= =nFRe -END PGP SIGNATURE- -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/719ee6c3-
Re: Vim9 script: first steps
Prabir Shrestha wrote: > -1 for }. That is the most absurd syntax I have seen in any language that > only uses it for closing. OK, it appears nobody likes it. The whole idea of experimenting is to try out alternatives. > So I went and re-read the poll https://github.com/vim/vim/issues/3573. And > here is what I can think of reading it again in Jan 2020. > > Can we get more info on what does make vim-script faster mean? > > [image: Screen Shot 2020-01-04 at 3.53.13 PM.png] > > [image: Screen Shot 2020-01-04 at 4.04.27 PM.png] > > [image: Screen Shot 2020-01-04 at 4.05.36 PM.png] > > > > Second comment there says about syntax highlighting. So making vimscript > faster here won't help much because [tree-sitter]( > https://tree-sitter.github.io/tree-sitter/) will be lot faster than > vimscript, which means syntax highlighting in neovim will also be more > accurate and faster then vim. As I mentioned before, using an external tool is the main alternative. With channel support and text properties the pieces are already available today. > Instead of picking up non real world examples to demonstrate perf gains can > we pick some proper goals. > > Here are some of the examples I can think of: > > * Faster fuzzy finder. Currently there is 0 plugins that is fast in pure > vimscript. I would like to see an example of FuzzyFinder in vim9 that is > fast as https://github.com/liuchengxu/vim-clap and > https://github.com/junegunn/fzf.vim. Few requirements here: Searching large > number of nested directories and files, highlighting matches. Some of these > I elaborated in this comment > https://github.com/vim/vim/issues/3573#issuecomment-433730939. It's impossible to measure the speed of a whole plugin without implementing 99% of the compiling and execution. We'll have to start with simple examples to check if we are going in the right direction. Feel free to come up with some part that needs to be fast and is simple enough we could implement that part of the compilation/execution. > * vim9 syntax highlighting vs neovim tree-sitter syntax highlighting. We > should count speed as well as accuracy. As mentioned above, you can already do that. With Vim9 script the part inside Vim will be faster. By how much is hard to predict. > * Fuzzy search for auto complete popup menu. > > > I still think WASM is the way to go and not vimscript 9. This way I can > code in what ever language suits me and just ship the bytecode. I already explained that using an external tool allows you to do this. > For example: will vimscript 9 support generics/async,await/pattern > matching/threading or greenthreads/immutability? This list will keep going > on. Making it fast is just one issue it solves. A language gets attractive > not just for perf but many other features that come around it. We can add some more in Vim9, but it's not what plugin authors have been asking for. > Here is a new WASM runtime since I last mentioned which claims to be 15x > faster then other c wasm runtimes. https://github.com/wasm3/wasm3. I'm sure other languages like C and Go will be even faster. > As a plugin author I can then code in any languages I want that suits the > needed. For example a python dev might write in python, a JS dev might > right in Javascript or Typescript if they need typing. And they can still > write in go/rust/zig or even c if they need performance. And most languages > these days already support compiling to WASM. The point I made was that you can use any language you like, just run it as an external tool and communicate with Vim. I don't see how integrating any language interface inside Vim would work better. We do have enough evidence that the exising ones are not popular, adding another one is unlikely going to change that. -- "When I die, I want a tombstone that says "GAME OVER" - Ton Richters /// Bram Moolenaar -- b...@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/// -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/202001051308.005D8hBj011359%40masaka.moolenaar.net.
Re: Vim9 script: first steps
Ingo Karkat wrote: > I agree; most performance issues I encounter are in syntax > highlighting with large, often deeply nested structures (like big XML > or JSON files). Poor Vimscript performance hardly is an issue for the > kind of plugins that I write; and it's always been possible to use a > language binding and reimplement the core parts, or call out to an > external program (now even easier with the jobs feature). If WASM is > the future (and you present enticing arguments here), deprecating the > many existing language bindings in favor of WASM as the single > go-forward integration would indeed contribute to a simplified code > base, avoid fragmented plugin requirements, and therefore reduce > compatibility issues in the diverse user base. I don't think WASM helps at all with syntax highlighting. The good old Vim syntax highlighting depends on regexp patterns. I have already optimized the speed of that, I don't think it can be improved much more. The main alternative now is to use an external parser or language server and communicate with it. Such as the govim plugin does. You an now use text properties to highlight the text. Perhaps tree sitter can be used. It's still new, makes some promises, but we would need to see how it can integrate with Vim. > Still, if Bram has ideas about eliminating some inefficiencies of > Vimscript, so that Vimscript writers can easily opt-in (ideally, in a > backwards-compatible way and without rewriting entire functions or > plugins), why not? Vim, with its great backwards compatibility and > platform support, has been a pleasure to use and extend for many many > years; I'll happily let Bram indulge in such pet projects (and the > accompanying bike shedding about syntax details :-) if that's what > keeps him happy and committed to the project! -- [Another hideous roar.] BEDEVERE: That's it! ARTHUR: What? BEDEVERE: It's The Legendary Black Beast of Arrggghhh! "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- b...@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/// -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/202001051308.005D8hR2011347%40masaka.moolenaar.net.
Patch 8.2.0087
Patch 8.2.0087 Problem:Crash in command line expansion when out of memory. Solution: Check for NULL pointer. Also make ExpandGeneric() static. (Dominique Pelle, closes #5437) Files: src/cmdexpand.c, src/proto/cmdexpand.pro *** ../vim-8.2.0086/src/cmdexpand.c 2019-12-29 13:56:28.692861883 +0100 --- src/cmdexpand.c 2020-01-05 14:33:14.587845144 +0100 *** *** 16,21 --- 16,24 static intcmd_showtail; // Only show path tail in lists ? static void set_expand_context(expand_T *xp); + static int ExpandGeneric(expand_T *xp, regmatch_T *regmatch, + int *num_file, char_u ***file, + char_u *((*func)(expand_T *, int)), int escaped); static intExpandFromContext(expand_T *xp, char_u *, int *, char_u ***, int); static intexpand_showtail(expand_T *xp); static intexpand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int flagsarg); *** *** 2214,2220 * * Returns OK when no problems encountered, FAIL for error (out of memory). */ ! int ExpandGeneric( expand_T *xp, regmatch_T*regmatch, --- 2217,2223 * * Returns OK when no problems encountered, FAIL for error (out of memory). */ ! static int ExpandGeneric( expand_T *xp, regmatch_T*regmatch, *** *** 2250,2255 --- 2253,2265 str = vim_strsave_escaped(str, (char_u *)" \t\\."); else str = vim_strsave(str); + if (str == NULL) + { + FreeWild(count, *file); + *num_file = 0; + *file = NULL; + return FAIL; + } (*file)[count] = str; # ifdef FEAT_MENU if (func == get_menu_names && str != NULL) *** *** 2268,2280 { if (count == 0) return OK; - *num_file = count; *file = ALLOC_MULT(char_u *, count); if (*file == NULL) { ! *file = (char_u **)""; return FAIL; } count = 0; } } --- 2278,2291 { if (count == 0) return OK; *file = ALLOC_MULT(char_u *, count); if (*file == NULL) { ! *num_file = 0; ! *file = NULL; return FAIL; } + *num_file = count; count = 0; } } *** *** 2297,2303 // they don't show up when getting normal highlight names by ID. reset_expand_highlight(); #endif - return OK; } --- 2308,2313 *** ../vim-8.2.0086/src/proto/cmdexpand.pro 2019-12-12 12:55:16.0 +0100 --- src/proto/cmdexpand.pro 2020-01-05 14:33:34.119769957 +0100 *** *** 8,14 char_u *addstar(char_u *fname, int len, int context); void set_cmd_context(expand_T *xp, char_u *str, int len, int col, int use_ccline); int expand_cmdline(expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches); - int ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)), int escaped); void globpath(char_u *path, char_u *file, garray_T *ga, int expand_options); void f_getcompletion(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ --- 8,13 *** ../vim-8.2.0086/src/version.c 2020-01-04 19:00:07.573654631 +0100 --- src/version.c 2020-01-05 14:35:25.047342281 +0100 *** *** 744,745 --- 744,747 { /* Add new patch number below this line */ + /**/ + 87, /**/ -- VOICE OVER: As the horrendous Black Beast lunged forward, escape for Arthur and his knights seemed hopeless, when, suddenly ... the animator suffered a fatal heart attack. ANIMATOR: Agh! VOICE OVER: The cartoon peril was no more ... The Quest for Holy Grail could continue. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- b...@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/// -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion o
Re: Vim9 script: first steps
Hi Bram, thanks for sharing. Looks really promising. Regarding https://github.com/brammool/vim9#3-better-vim-script, I have a few ideas for your consideration: * Execution often relies on user configuration (ignorecase, magic, etc.) and there is common boilerplate required in many scripts to set/restore cpo. Could we say that when `scriptversion` is `vim9`, we always execute as if `set cpo&vim` ? * Line continuation. I know this is probably hard to change, but could we look at a line-continuation scheme that's more familiar ? As we don't have line termination, Perhaps something more like python's e.g. if a line ends with an unbalanced parenthesis (or a ``), then assume the next line is a continuation? I think the `` syntax is unfamiliar to a lot of people. * Scoped functions or lambdas containing ex-commands (or better, def function bodies). When combined with try/finally, this would allow constructs that take a "block" of code, such as "WithCurrentBuffer( buf, { => block of code/commands, maybe split across lines } )" or something like this when working with external tools `SendMessageToTool( message, then = { => some block of ex commands } ). This can currently be done with Funcref, but I think that you have to do 'function ...' and then 'delfiunc' as all functions are currently global. Maybe the new scoping rules could be extended to allow this. I already mentioned elsewhere that the other barrier to entry for vim scripting is tooling and debugging. Hopefully with a these changes we can consider how to: * extract the parser so that an external tool can parse and do code comprehension, go-to, refactor, etc., think Vim Language Server (there is one, but it's not canonical) * provide a interface to a debug adapter to allow debugging of vimscript executing in a Vim instance (i.e. Vim Debug Adapter) * provide better source/line information for stack traces (so that we can reliably jump to location of assertions e.g. test failures using cnext). I saw a recent patch which improves sourcing_lineno and uses a proper stack. I was planning to work on a patch to store source/line info when debugging is enabled, but might hold off while vim 9 shakes down, as this is likely required for the above debugger interface (assuming that's a goal). Just a few ideas to throw in to the mix! Thanks again, Ben On Thursday, January 2, 2020 at 7:44:10 PM UTC, Bram Moolenaar wrote: > > > I have created a repository for the Vim9 script experiments: > https://github.com/brammool/vim9 > > I did another measurement for a more realistic example, re-indenting a > large number of lines. In old Vim script it would be: > > let totallen = 0 > for i in range(1, 10) > call setline(i, '' .. getline(i)) > let totallen += len(getline(i)) > endfor > > The timing differences are much smaller than for the computational > example, but Vim9 script is clearly the fastest: > > Vim old: 0.853752 > Python:0.304584 > Lua: 0.286573 > Vim new: 0.190276 > > Compared to legacy Vim script it is a 4 times faster. > > If you want to look at the instructions that are used internally, the > ":disassemble" command shows what's the compilation result. For > example, this function: > > def VimNew(): number > let totallen = 0 > for i in range(1, 10) > setline(i, '' .. getline(i)) > totallen += len(getline(i)) > } > return totallen > enddef > > Results in this: > > let totallen = 0 >0 STORE 0 in $0 > > for i in range(1, 10) >1 STORE -1 in $1 >2 PUSHNR 1 >3 PUSHNR 10 >4 BCALL range(argc 2) >5 FOR $1 -> 21 >6 STORE $2 > > setline(i, '' .. getline(i)) >7 LOAD $2 >8 PUSHS "" >9 LOAD $2 > 10 BCALL getline(argc 1) > 11 CONCAT > 12 BCALL setline(argc 2) > 13 DROP > > totallen += len(getline(i)) > 14 LOAD $0 > 15 LOAD $2 > 16 BCALL getline(argc 1) > 17 BCALL len(argc 1) > 18 ADDNR > 19 STORE $0 > > } > 20 JUMP -> 5 > 21 DROP > > return totallen > 22 LOAD $0 > 23 RETURN > > > Obviously there is still an awful lot of work to be done. Fortunately, > the numbers show it's worth it. > > -- > The Law of VIM: > For each member b of the possible behaviour space B of program P, there > exists > a finite time t before which at least one user u in the total user space U > of > program P will request b becomes a member of the allowed behaviour space > B' > (B' <= B). > In other words: Sooner or later everyone wants everything as an option. > -- Vince Negri > > /// Bram Moolenaar -- b...@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
Re: Vim9 script: first steps
On So, 05 Jan 2020, Bram Moolenaar wrote: > Perhaps tree sitter can be used. It's still new, makes some promises, > but we would need to see how it can integrate with Vim. We could have a look at the Neovim implementation. It has been included there as well (and as far as I remember, @bfredl mentioned that his work can also be included here). Best, Christian -- Die Politik ist das Paradies zungenfertiger Schwätzer. -- George Bernard Shaw -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/20200105164651.GR9787%40256bit.org.
Re: Vim9 script: first steps
Ben Jackson wrote: > Hi Bram, thanks for sharing. Looks really promising. > > Regarding https://github.com/brammool/vim9#3-better-vim-script, I have a > few ideas for your consideration: > > * Execution often relies on user configuration (ignorecase, magic, etc.) > and there is common boilerplate required in many scripts to set/restore > cpo. Could we say that when `scriptversion` is `vim9`, we always execute as > if `set cpo&vim` ? For :def functions those will be parsed as if 'nocompatible' is set. For 'ignorecase' and 'magic' we can ignore those for the =~ and !~ operators. What else? Not sure yet what will happen at the script level. No changes are needed for speed. If needed the file can be put inside :def/:enddef and then calling that function. Not ideal, but at least it's possible. > * Line continuation. I know this is probably hard to change, but could we > look at a line-continuation scheme that's more familiar ? As we don't have > line termination, Perhaps something more like python's e.g. if a line ends > with an unbalanced parenthesis (or a ``), then assume > the next line is a continuation? I think the `` syntax > is unfamiliar to a lot of people. It will be difficult to implement, and we'll still need the old way of line continuation in some places. Putting the backslash at the end of the line isn't nice anyway, too easy to make mistakes, we should probably not add it. Mixing the two is probably worse. If we can have some statements continue on the next line without a backslash remains to be seen. > * Scoped functions or lambdas containing ex-commands (or better, def > function bodies). When combined with try/finally, this would allow > constructs that take a "block" of code, such as "WithCurrentBuffer( buf, { > => block of code/commands, maybe split across lines } )" or something like > this when working with external tools `SendMessageToTool( message, then = { > => some block of ex commands } ). This can currently be done with Funcref, > but I think that you have to do 'function ...' and then 'delfiunc' as all > functions are currently global. Maybe the new scoping rules could be > extended to allow this. That a function declared locally in a function becomes a global function is indeed unexpected. We can at least make them local inside a :def function, unless prefixed with g:, just like with variables. Defining a function and creating a funcref in one step would also be useful. Not sure about the syntax. TypeScript does something like this: let ref = function(arg: type): rettype { ... body }; Perhaps we can do: let ref = def(arg: type): rettype ... body enddef > I already mentioned elsewhere that the other barrier to entry for vim > scripting is tooling and debugging. Hopefully with a these changes we can > consider how to: > > * extract the parser so that an external tool can parse and do code > comprehension, go-to, refactor, etc., think Vim Language Server (there is > one, but it's not canonical) It's a lot easier to make an independent parser. Trying to share a parser will make things very complicated. > * provide a interface to a debug adapter to allow debugging of vimscript > executing in a Vim instance (i.e. Vim Debug Adapter) Sure. > * provide better source/line information for stack traces (so that we can > reliably jump to location of assertions e.g. test failures using cnext). I > saw a recent patch which improves sourcing_lineno and uses a proper stack. > I was planning to work on a patch to store source/line info when debugging > is enabled, but might hold off while vim 9 shakes down, as this is likely > required for the above debugger interface (assuming that's a goal). Yes, I started improving the execution stack. Currently it only tracks a sequence of function calls, it does not continue with a :source command or executing autocommands, and it's a string without file/line info. This can be greatly improved. -- ROBIN: (warily) And if you get a question wrong? ARTHUR: You are cast into the Gorge of Eternal Peril. ROBIN: Oh ... wacho! "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- b...@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/// -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.
Re: Vim9 script: first steps
Christian wrote: > On So, 05 Jan 2020, Bram Moolenaar wrote: > > > Perhaps tree sitter can be used. It's still new, makes some promises, > > but we would need to see how it can integrate with Vim. > > We could have a look at the Neovim implementation. It has been included > there as well (and as far as I remember, @bfredl mentioned that his work > can also be included here). I believe it's still under construction. I haven't yet been able to find documentation, only some Lua interface (which looks complicated). -- Sorry, no fortune today. /// Bram Moolenaar -- b...@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/// -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/202001051855.005Itqwx012931%40masaka.moolenaar.net.
Patch 8.2.0088
Patch 8.2.0088 Problem:Insufficient tests for tags; bug in using extra tag field when using an ex command to position the cursor. Solution: Fix the bug, add more tests. (Yegappan Lakshmanan, closes #5439) Files: runtime/doc/tagsrch.txt, src/tag.c, src/testdir/test_ins_complete.vim, src/testdir/test_tagfunc.vim, src/testdir/test_tagjump.vim, src/testdir/test_taglist.vim *** ../vim-8.2.0087/runtime/doc/tagsrch.txt 2019-12-12 12:49:06.0 +0100 --- runtime/doc/tagsrch.txt 2020-01-05 20:28:54.700971203 +0100 *** *** 344,354 A static tag is a tag that is defined for a specific file. In a C program this could be a static function. ! In Vi jumping to a tag sets the current search pattern. This means that ! the "n" command after jumping to a tag does not search for the same pattern ! that it did before jumping to the tag. Vim does not do this as we consider it ! to be a bug. You can still find the tag search pattern in the search history. ! If you really want the old Vi behavior, set the 't' flag in 'cpoptions'. *tag-binary-search* Vim uses binary searching in the tags file to find the desired tag quickly --- 344,354 A static tag is a tag that is defined for a specific file. In a C program this could be a static function. ! In Vi jumping to a tag sets the current search pattern. This means that the ! "n" command after jumping to a tag does not search for the same pattern that ! it did before jumping to the tag. Vim does not do this as we consider it to ! be a bug. If you really want the old Vi behavior, set the 't' flag in ! 'cpoptions'. *tag-binary-search* Vim uses binary searching in the tags file to find the desired tag quickly *** *** 426,433 In Vi the ":tag" command sets the last search pattern when the tag is searched for. In Vim this is not done, the previous search pattern is still remembered, ! unless the 't' flag is present in 'cpoptions'. The search pattern is always ! put in the search history, so you can modify it if searching fails. *emacs-tags* *emacs_tags* *E430* Emacs style tag files are only supported if Vim was compiled with the --- 426,432 In Vi the ":tag" command sets the last search pattern when the tag is searched for. In Vim this is not done, the previous search pattern is still remembered, ! unless the 't' flag is present in 'cpoptions'. *emacs-tags* *emacs_tags* *E430* Emacs style tag files are only supported if Vim was compiled with the *** ../vim-8.2.0087/src/tag.c 2020-01-02 14:02:12.316159489 +0100 --- src/tag.c 2020-01-05 20:28:54.700971203 +0100 *** *** 3808,3813 --- 3808,3814 find_extra(char_u **pp) { char_u*str = *pp; + char_ufirst_char = **pp; // Repeat for addresses separated with ';' for (;;) *** *** 3817,3823 else if (*str == '/' || *str == '?') { str = skip_regexp(str + 1, *str, FALSE, NULL); ! if (*str != **pp) str = NULL; else ++str; --- 3818,3824 else if (*str == '/' || *str == '?') { str = skip_regexp(str + 1, *str, FALSE, NULL); ! if (*str != first_char) str = NULL; else ++str; *** *** 3837,3842 --- 3838,3844 || !(VIM_ISDIGIT(str[1]) || str[1] == '/' || str[1] == '?')) break; ++str; // skip ';' + first_char = *str; } if (str != NULL && STRNCMP(str, ";\"", 2) == 0) *** ../vim-8.2.0087/src/testdir/test_ins_complete.vim 2020-01-04 14:32:35.522717984 +0100 --- src/testdir/test_ins_complete.vim 2020-01-05 20:28:54.700971203 +0100 *** *** 432,434 --- 432,462 call StopVimInTerminal(buf) call delete('Xpreviewscript') endfunc + + " Test for inserting the tag search pattern in insert mode + func Test_ins_compl_tag_sft() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo\t/^int first() {}$/", + \ "second\tXfoo\t/^int second() {}$/", + \ "third\tXfoo\t/^int third() {}$/"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int second() {} + int third() {} + [CODE] + call writefile(code, 'Xfoo') + + enew + set showfulltag + exe "normal isec" + call assert_equal('int second() {}', getline(1)) + set noshowfulltag + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe! + endfunc *** ../vim-8.2.0087/src/testdir/test_tagfunc.vim2019-04-28 17:48:10.0 +0200 --- src/testdir/test_tagfunc.vim2020-01-05 20:2
Re: Vim9 script: first steps
> > > * provide a interface to a debug adapter to allow debugging of vimscript > > executing in a Vim instance (i.e. Vim Debug Adapter) > Sure. +1 for this. This is always the first function I write in a plugin. It would be good to either support chrome devtools debugg protocol or language server debug protocol. https://code.visualstudio.com/blogs/2018/08/07/debug-adapter-protocol-website But I'm not in hurry to have this. function! asyncomplete#log(...) abort if !empty(g:asyncomplete_log_file) call writefile([json_encode(a:000)], g:asyncomplete_log_file, 'a') endif endfunction * Scoped functions or lambdas containing ex-commands (or better, def > function bodies). When combined with try/finally, this would allow > constructs that take a "block" of code, such as "WithCurrentBuffer( buf, { > => block of code/commands, maybe split across lines } )" or something like > this when working with external tools `SendMessageToTool( message, then = { > => some block of ex commands } ). This can currently be done with Funcref, > but I think that you have to do 'function ...' and then 'delfiunc' as all > functions are currently global. Maybe the new scoping rules could be > extended to allow this. This was was something I mentioned before in a different post about vim9. It would really be good to allow multiple lines in lambda or functions.Frankly this is one of the biggest pain point I have with vimscript currently when dealing with async code. call job_start({ \ 'out_cb': {job, data-> \ if data != '' \ echom data \ endif \ } \ }) call job_start({ \ 'out_cb': function(job, data) abort \ if data != '' \ echom data \ endif \ endfunction \ }) I don't think WASM helps at all with syntax highlighting. The good old > Vim syntax highlighting depends on regexp patterns. I have already > optimized the speed of that, I don't think it can be improved much more. > The main alternative now is to use an external parser or language server > and communicate with it. Such as the govim plugin does. You an now use > text properties to highlight the text. I was hoping for vim to support WASM + WASM threads, so we can do most of the expensive functions in a thread. The biggest problem with having external jobs is that how do the users get the external binary that works in their OS. Languages such as rust and go having a single static binary has made it easy but this still suffers from compilation in some OS and the IT department allowing the random binary. Or might be what we need is "vim --server --script=server.vim" which can read and write to stdio/stdout/stderr or sockets. This way we can do heavy lifting in vimscript in a different process. https://github.com/prabirshrestha/vim-lsp/issues/633 - Semantic highlight slows down editing In vim-lsp we implemented semantic highlighting if langserver supports it using text_props, but then the protocol currently returns the entire document highlighting which we need to compute in vimscript, making it very slow. For now we have disabled this feature by default. The only way I can think of improving this is by using python threads or different process. FUNCTIONS SORTED ON SELF TIME count total (s) self (s) function 10004 2.192760 lsp#utils#base64_decode() 10004 2.202340 1.375972 87_add_highlight() 10004 3.162274 0.504508 87_tokens_to_hl_info() 30024 0.465006 87_octets_to_number() 10005 0.351520 0.286610 lsp#capabilities#has_semantic_highlight() 100053 0.251802 87_get_textprop_name() 1 5.561511 0.196170 lsp#ui#vim#semantic#handle_semantic() 10005 0.574658 0.169267 lsp#ui#vim#semantic#get_scopes() 20011 0.118792 lsp#get_server_capabilities() > Basically in strict mode it would still use a:name as the variable name > but > > it is no longer a dictionary. This way all new vimscript is 100% > compatible > > with old vimscript < 9 > I don't see that. If a: is no longer available as a dictionary it won't > be 100% compatible. There are other subtle assumptions, e.g. about how > error messages are handled. It will work like "abort" was present. This is why it is an explicit opt in using " use strict. By default it treats a:0 as a dictionary but if "use strict is turned on, it treats a:0 as a variable and not a dict. On Sunday, January 5, 2020 at 10:56:03 AM UTC-8, Bram Moolenaar wrote: > > > Ben Jackson wrote: > > > Hi Bram, thanks for sharing. Looks really promising. > > > > Regarding https://github.com/brammool/vim9#3-better-vim-script, I have > a > > few ideas for your consideration: > > > > * Execution often relies on user configuration (ignorecase, magic, etc.) > > and there is common boilerplate required in many scripts to set/restore > > cpo. Could we say that when `scriptversion` is `vim9`, we always execute > as > > if `set cpo&vim` ? > > For
Patch 8.2.0089
Patch 8.2.0089 Problem:Crash when running out of memory in :setfiletype completion. Solution: Do not allocate memory. (Dominique Pelle, closes #5438) Files: src/cmdexpand.c *** ../vim-8.2.0088/src/cmdexpand.c 2020-01-05 14:38:37.110600924 +0100 --- src/cmdexpand.c 2020-01-05 22:04:19.952724414 +0100 *** *** 2633,2648 ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); if (ga_grow(ga, num_p) == OK) ! { for (i = 0; i < num_p; ++i) { ! ((char_u **)ga->ga_data)[ga->ga_len] = ! vim_strnsave(p[i], (int)STRLEN(p[i])); ++ga->ga_len; } ! } ! ! FreeWild(num_p, p); } } } --- 2633,2645 ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); if (ga_grow(ga, num_p) == OK) ! // take over the pointers and put them in "ga" for (i = 0; i < num_p; ++i) { ! ((char_u **)ga->ga_data)[ga->ga_len] = p[i]; ++ga->ga_len; } ! vim_free(p); } } } *** ../vim-8.2.0088/src/version.c 2020-01-05 20:35:39.967830421 +0100 --- src/version.c 2020-01-05 22:05:34.976425656 +0100 *** *** 744,745 --- 744,747 { /* Add new patch number below this line */ + /**/ + 89, /**/ -- Permission is granted to read this message out aloud on Kings Cross Road, London, under the condition that the orator is properly dressed. /// Bram Moolenaar -- b...@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/// -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/202001052107.005L7Iht007470%40masaka.moolenaar.net.
Patch 8.2.0090
Patch 8.2.0090 Problem:Generated files show up in git status. Solution: Ignore a few more files. Files: .gitignore *** ../vim-8.2.0089/.gitignore 2019-11-13 22:00:49.0 +0100 --- .gitignore 2020-01-05 18:54:37.356263441 +0100 *** *** 8,13 --- 8,14 src/objects/.dirstamp src/objects src/tags + src/types.vim # We do need src/auto/configure. src/auto/config.cache *** *** 86,91 --- 87,93 # Generated by "make install" runtime/doc/tags + runtime/doc/doctags # Generated by "make shadow". The directory names could be anything but we # restrict them to shadow (the default) or shadow-* *** ../vim-8.2.0089/src/version.c 2020-01-05 22:05:46.448380159 +0100 --- src/version.c 2020-01-05 22:10:10.983342886 +0100 *** *** 744,745 --- 744,747 { /* Add new patch number below this line */ + /**/ + 90, /**/ -- BRIDGEKEEPER: What is your favorite colour? LAUNCELOT:Blue. BRIDGEKEEPER: Right. Off you go. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- b...@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/// -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/202001052111.005LBNXF008485%40masaka.moolenaar.net.
Re: Vim9 script: first steps
> On 5 Jan 2020, at 18:55, Bram Moolenaar wrote: > > > Ben Jackson wrote: > >> Hi Bram, thanks for sharing. Looks really promising. >> >> Regarding https://github.com/brammool/vim9#3-better-vim-script, I have a >> few ideas for your consideration: >> >> * Execution often relies on user configuration (ignorecase, magic, etc.) >> and there is common boilerplate required in many scripts to set/restore >> cpo. Could we say that when `scriptversion` is `vim9`, we always execute as >> if `set cpo&vim` ? > > For :def functions those will be parsed as if 'nocompatible' is set. > > For 'ignorecase' and 'magic' we can ignore those for the =~ and !~ > operators. What else? The “usual" expression operators behave differently (when not suffixed with # or ?) depending on `ignorecase`, right. As in: if x == “CaseSensitiveMatch?” Depends on ignorecase. Examples from :help expr4: "abc" ==# "Abc" evaluates to 0 "abc" ==? "Abc" evaluates to 1 "abc" == "Abc"evaluates to 1 if 'ignorecase' is set, 0 otherwise I think this is one of those things you just have to know (like using === in javascirpt). Would be fewer accidental bugs if `==` worked consistently I guess. > > Not sure yet what will happen at the script level. No changes are > needed for speed. If needed the file can be put inside :def/:enddef > and then calling that function. Not ideal, but at least it's possible. I guess the javascript idiom here is to have an anonymous function that’s immediately called: ( def ( args ) : return type Code enddef )() But that’s hardly art. > > >> * Line continuation. I know this is probably hard to change, but could we >> look at a line-continuation scheme that's more familiar ? As we don't have >> line termination, Perhaps something more like python's e.g. if a line ends >> with an unbalanced parenthesis (or a ``), then assume >> the next line is a continuation? I think the `` syntax >> is unfamiliar to a lot of people. > > It will be difficult to implement, and we'll still need the old way of > line continuation in some places. Putting the backslash at the end of > the line isn't nice anyway, too easy to make mistakes, we should > probably not add it. Mixing the two is probably worse. > If we can have some statements continue on the next line without a > backslash remains to be seen. Sure. I figured this would be difficult. > >> * Scoped functions or lambdas containing ex-commands (or better, def >> function bodies). When combined with try/finally, this would allow >> constructs that take a "block" of code, such as "WithCurrentBuffer( buf, { >> => block of code/commands, maybe split across lines } )" or something like >> this when working with external tools `SendMessageToTool( message, then = { >> => some block of ex commands } ). This can currently be done with Funcref, >> but I think that you have to do 'function ...' and then 'delfiunc' as all >> functions are currently global. Maybe the new scoping rules could be >> extended to allow this. > > That a function declared locally in a function becomes a global function > is indeed unexpected. We can at least make them local inside a :def > function, unless prefixed with g:, just like with variables. > > Defining a function and creating a funcref in one step would also be > useful. Not sure about the syntax. TypeScript does something like > this: > let ref = function(arg: type): rettype { ... body }; > > Perhaps we can do: > let ref = def(arg: type): rettype > ... body > enddef > I personally like the python approach: a def inside a function is a local variable of function type. As in: let myFunc = function( … ) { … body } Would be written simply as def myFunc( … ): … body In vimscript we could do the same, having a nested ‘def’ always declare a local Funcref by name, but have a ‘real’ name that’s hidden from the user (like a lambda). In the above example, that would create a local variable ‘myFunc’ which is a Funcref to an (unnamed?) function with ( … ) args and … body. Again, not sure how practical that is, but it _feels_ smiler to how lambdas currently work. >> I already mentioned elsewhere that the other barrier to entry for vim >> scripting is tooling and debugging. Hopefully with a these changes we can >> consider how to: >> >> * extract the parser so that an external tool can parse and do code >> comprehension, go-to, refactor, etc., think Vim Language Server (there is >> one, but it's not canonical) > > It's a lot easier to make an independent parser. Trying to share a > parser will make things very complicated. Fair enough. > >> * provide a interface to a debug adapter to allow debugging of vimscript >> executing in a Vim instance (i.e. Vim Debug Adapter) > > Sure. Woo \o/. Debugging vimscript with vimspector would be very kickass. I’m more than willing to put in hard graft to make this happen. > >> * provide better source/line inform
Re: Vim9 script: first steps
Ben Jackson wrote: > >> Hi Bram, thanks for sharing. Looks really promising. > >> > >> Regarding https://github.com/brammool/vim9#3-better-vim-script, I have a > >> few ideas for your consideration: > >> > >> * Execution often relies on user configuration (ignorecase, magic, etc.) > >> and there is common boilerplate required in many scripts to set/restore > >> cpo. Could we say that when `scriptversion` is `vim9`, we always execute > >> as > >> if `set cpo&vim` ? > > > > For :def functions those will be parsed as if 'nocompatible' is set. > > > > For 'ignorecase' and 'magic' we can ignore those for the =~ and !~ > > operators. What else? > > The “usual" expression operators behave differently (when not suffixed > with # or ?) depending on `ignorecase`, right. As in: if x == > “CaseSensitiveMatch?” Depends on ignorecase. > > Examples from :help expr4: > > "abc" ==# "Abc" evaluates to 0 > "abc" ==? "Abc" evaluates to 1 > "abc" == "Abc" evaluates to 1 if 'ignorecase' is set, 0 otherwise > > I think this is one of those things you just have to know (like using > === in javascirpt). Would be fewer accidental bugs if `==` worked > consistently I guess. I have already made it work like that, 'ignorecase' is not used. > > Not sure yet what will happen at the script level. No changes are > > needed for speed. If needed the file can be put inside :def/:enddef > > and then calling that function. Not ideal, but at least it's possible. > > I guess the javascript idiom here is to have an anonymous function that’s > immediately called: > > ( def ( args ) : return type > Code > enddef )() > > But that’s hardly art. I like to take the good parts of JavaScript, not the weird parts :-). It's very easy to miss the "()" at the end, especially if the function takes up most of the file. > >> * Scoped functions or lambdas containing ex-commands (or better, def > >> function bodies). When combined with try/finally, this would allow > >> constructs that take a "block" of code, such as "WithCurrentBuffer( buf, { > >> => block of code/commands, maybe split across lines } )" or something like > >> this when working with external tools `SendMessageToTool( message, then = > >> { > >> => some block of ex commands } ). This can currently be done with Funcref, > >> but I think that you have to do 'function ...' and then 'delfiunc' as all > >> functions are currently global. Maybe the new scoping rules could be > >> extended to allow this. > > > > That a function declared locally in a function becomes a global function > > is indeed unexpected. We can at least make them local inside a :def > > function, unless prefixed with g:, just like with variables. > > > > Defining a function and creating a funcref in one step would also be > > useful. Not sure about the syntax. TypeScript does something like > > this: > > let ref = function(arg: type): rettype { ... body }; > > > > Perhaps we can do: > > let ref = def(arg: type): rettype > > ... body > >enddef > > > > I personally like the python approach: a def inside a function is a local > variable of function type. As in: > > let myFunc = function( … ) { … body } > > Would be written simply as > > def myFunc( … ): > … body > > In vimscript we could do the same, having a nested ‘def’ always > declare a local Funcref by name, but have a ‘real’ name that’s hidden > from the user (like a lambda). In the above example, that would create > a local variable ‘myFunc’ which is a Funcref to an (unnamed?) function > with ( … ) args and … body. Again, not sure how practical that is, > but it _feels_ smiler to how lambdas currently work. It can also made to work so that the function is defined normally, and when using that name without () it will be a funcref, as if using "function('FuncName')". Then it also works for global functions, with "g:" prepended. > >> * provide a interface to a debug adapter to allow debugging of vimscript > >> executing in a Vim instance (i.e. Vim Debug Adapter) > > > > Sure. > > Woo \o/. Debugging vimscript with vimspector would be very kickass. > I’m more than willing to put in hard graft to make this happen. It's not really related to Vim9 script, could be an independend project. -- BRIDGEKEEPER: What is your favorite colour? GAWAIN: Blue ... No yelloww! "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- b...@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/// -- -- 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 thi
:ppop command doesn't work
Hi all, While developing new tests for the tag functionality, I realized that the :ppop command which is supposed to pop the preview window tag stack doesn't work. I am not sure whether this worked in the past. Does anyone use the :ppop command? - Yegappan -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/CAAW7x7nab9ynWXAGVi12iT15xpNxkLnKZRcBjrWfADOFVms1Lw%40mail.gmail.com.
Re: :ppop command doesn't work
Hi, On Mon, Jan 6, 2020 at 10:45 AM Yegappan Lakshmanan wrote: > > Hi all, > > While developing new tests for the tag functionality, I realized that the > :ppop command which is supposed to pop the preview window tag stack > doesn't work. I am not sure whether this worked in the past. Does anyone > use the :ppop command? > Trying to add more tests for the preview tag functionality, I see that several other features also doesn't work with the preview tag stack. The preview tag stack feature needs to be revisited. - Yegappan -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/CAAW7x7%3Djj5P4nUswDFitowAg-mRZ6YaixA-s6_NoBDFX1YkhXw%40mail.gmail.com.