From 26113e5ae3c4762ab718d5f006afa71f67e6f459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernesto=20Els=C3=A4=C3=9Fer?= Date: Fri, 1 Nov 2024 23:17:03 +0100 Subject: [PATCH 001/106] runtime(doc): Include netrw-gp in TOC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes: #7627 Signed-off-by: Ernesto Elsäßer Signed-off-by: Christian Brabandt --- runtime/doc/pi_netrw.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index 18f9c28b0b..dc95a54057 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -1,4 +1,4 @@ -*pi_netrw.txt* For Vim version 9.1. Last change: 2024 Oct 31 +*pi_netrw.txt* For Vim version 9.1. Last change: 2024 Nov 01 ------------------------------------------------ NETRW REFERENCE MANUAL by Charles E. Campbell @@ -54,9 +54,10 @@ Copyright: Copyright (C) 2017 Charles E Campbell *netrw-copyright* Browsing With A Horizontally Split Window...........|netrw-o| Browsing With A New Tab.............................|netrw-t| Browsing With A Vertically Split Window.............|netrw-v| - Change File Permission..............................|netrw-gp| - Change Listing Style.(thin wide long tree)..........|netrw-i| + Change Listing Style (thin wide long tree)..........|netrw-i| Changing To A Bookmarked Directory..................|netrw-gb| + Quick hide/unhide of dot-files......................|netrw-gh| + Changing local-only File Permission.................|netrw-gp| Changing To A Predecessor Directory.................|netrw-u| Changing To A Successor Directory...................|netrw-U| Customizing Browsing With A Special Handler.........|netrw-x| From 84b5b1c660beb2f9e27de70687e41d39a023ae81 Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Sat, 2 Nov 2024 15:44:43 +0100 Subject: [PATCH 002/106] patch 9.1.0826: filetype: sway files are not recognized Problem: filetype: sway files are not recognized Solution: detect '*.sw' files as sway filetype, include a filetype plugin (Riley Bruins) References: https://github.com/FuelLabs/sway. Comments taken from their syntax documentation. File extension taken from the same documentation/GitHub's own recognition of these file types closes: #15973 Signed-off-by: Riley Bruins Signed-off-by: Christian Brabandt --- .github/MAINTAINERS | 1 + runtime/filetype.vim | 3 +++ runtime/ftplugin/sway.vim | 15 +++++++++++++++ src/testdir/test_filetype.vim | 1 + src/version.c | 2 ++ 5 files changed, 22 insertions(+) create mode 100644 runtime/ftplugin/sway.vim diff --git a/.github/MAINTAINERS b/.github/MAINTAINERS index e24fbc4c8c..ea342ef7a0 100644 --- a/.github/MAINTAINERS +++ b/.github/MAINTAINERS @@ -263,6 +263,7 @@ runtime/ftplugin/squirrel.vim @ribru17 runtime/ftplugin/ssa.vim @ObserverOfTime runtime/ftplugin/sshdconfig.vim @jiangyinzuo runtime/ftplugin/svelte.vim @igorlfs +runtime/ftplugin/sway.vim @ribru17 runtime/ftplugin/swayconfig.vim @jamespeapen runtime/ftplugin/systemverilog.vim @Kocha runtime/ftplugin/swig.vim @jmarrec diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 7b0014d764..36461f69f8 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -2430,6 +2430,9 @@ au BufNewFile,BufRead *.sml setf sml " Sratus VOS command macro au BufNewFile,BufRead *.cm setf voscm +" Sway (programming language) +au BufNewFile,BufRead *.sw setf sway + " Swift au BufNewFile,BufRead *.swift,*.swiftinterface setf swift au BufNewFile,BufRead *.swift.gyb setf swiftgyb diff --git a/runtime/ftplugin/sway.vim b/runtime/ftplugin/sway.vim new file mode 100644 index 0000000000..35970b257c --- /dev/null +++ b/runtime/ftplugin/sway.vim @@ -0,0 +1,15 @@ +" Vim filetype plugin +" Language: Sway +" Maintainer: Riley Bruins +" Last Change: 2024 Nov 01 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl commentstring=//\ %s +" From Rust comments +setl comments=s0:/*!,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,:// + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 777f908fcb..050ff5f391 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -729,6 +729,7 @@ def s:GetFilenameChecks(): dict> svelte: ['file.svelte'], svg: ['file.svg'], svn: ['svn-commitfile.tmp', 'svn-commit-file.tmp', 'svn-commit.tmp'], + sway: ['file.sw'], swayconfig: ['/home/user/.sway/config', '/home/user/.config/sway/config', '/etc/sway/config', '/etc/xdg/sway/config'], swift: ['file.swift', 'file.swiftinterface'], swiftgyb: ['file.swift.gyb'], diff --git a/src/version.c b/src/version.c index 891327afdd..493de72f68 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 */ +/**/ + 826, /**/ 825, /**/ From a95d6a3d641dd065cccb1e76863dd3450ee5ce04 Mon Sep 17 00:00:00 2001 From: "S. B. Tam" Date: Sat, 2 Nov 2024 15:48:54 +0100 Subject: [PATCH 003/106] runtime(doc): remove stray sentence in pi_netrw.txt closes: #15971 Signed-off-by: S. B. Tam Signed-off-by: Christian Brabandt --- runtime/doc/pi_netrw.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index dc95a54057..6b4c5e06d4 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -1,4 +1,4 @@ -*pi_netrw.txt* For Vim version 9.1. Last change: 2024 Nov 01 +*pi_netrw.txt* For Vim version 9.1. Last change: 2024 Nov 02 ------------------------------------------------ NETRW REFERENCE MANUAL by Charles E. Campbell @@ -1542,7 +1542,7 @@ OPENING FILES AND LAUNCHING APPS *netrw-gx* *:Open* *:Launch* {{ Netrw determines which special handler by the following method: * if |g:netrw_browsex_viewer| exists, then it will be used to attempt to - view files. Examples of useful settings (place into your <.vimrc>): + view files. If the viewer you wish to use does not support handling of a remote URL directory, set |g:netrw_browsex_support_remote| to 0. * otherwise: From f1d83c4c71dce0edefc9a94b2dfa3ca1c343f837 Mon Sep 17 00:00:00 2001 From: Aliaksei Budavei <0x000c70@gmail.com> Date: Sat, 2 Nov 2024 15:51:14 +0100 Subject: [PATCH 004/106] patch 9.1.0827: CI: tests can be improved Problem: CI: tests can be improved Solution: collect failed indent tests, raise timeout for search() functions when using ASAN/Valgrind (Aliaksei Budavei) ASan-instrumented Vim builds tend to run slower (x2) than non-instrumented Vim builds and occasionally make indent tests fail when "search*()" functions time out and give up further execution. Reference: https://github.com/google/sanitizers/wiki/AddressSanitizer closes: #15974 Co-authored-by: Christian Brabandt Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com> Signed-off-by: Christian Brabandt --- .cirrus.yml | 3 ++- .github/actions/{screendump => test_artifacts}/action.yml | 5 +++-- .github/workflows/ci.yml | 6 +++--- Filelist | 2 +- src/testdir/runtest.vim | 5 +++++ src/testdir/shared.vim | 8 ++++++++ src/version.c | 2 ++ 7 files changed, 24 insertions(+), 7 deletions(-) rename .github/actions/{screendump => test_artifacts}/action.yml (86%) diff --git a/.cirrus.yml b/.cirrus.yml index ec897b809d..e81ed84d75 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -22,9 +22,10 @@ freebsd_task: - chown -R cirrus:cirrus . - sudo -u cirrus make test on_failure: - screendump_artifacts: + test_artifacts: name: "Cirrus-CI-freebsd-failed-tests" path: | + runtime/indent/testdir/*.fail runtime/syntax/testdir/failed/* src/testdir/failed/* type: application/octet-stream diff --git a/.github/actions/screendump/action.yml b/.github/actions/test_artifacts/action.yml similarity index 86% rename from .github/actions/screendump/action.yml rename to .github/actions/test_artifacts/action.yml index 5cbc8200c0..44738c505e 100644 --- a/.github/actions/screendump/action.yml +++ b/.github/actions/test_artifacts/action.yml @@ -1,5 +1,5 @@ -name: 'screendump' -description: "Upload failed screendump tests" +name: 'test_artifacts' +description: "Upload failed test artifacts" runs: using: "composite" steps: @@ -12,6 +12,7 @@ runs: # A file, directory or wildcard pattern that describes what # to upload. path: | + ${{ github.workspace }}/runtime/indent/testdir/*.fail ${{ github.workspace }}/runtime/syntax/testdir/failed/* ${{ github.workspace }}/src/testdir/failed/* # The desired behavior if no files are found using the diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df1041851d..19edd13eac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -272,7 +272,7 @@ jobs: do_test make ${SHADOWOPT} ${TEST} - if: ${{ !cancelled() }} - uses: ./.github/actions/screendump + uses: ./.github/actions/test_artifacts - name: Vim tags if: contains(matrix.extra, 'vimtags') @@ -394,7 +394,7 @@ jobs: make ${TEST} - if: ${{ !cancelled() }} - uses: ./.github/actions/screendump + uses: ./.github/actions/test_artifacts windows: runs-on: windows-2022 @@ -704,7 +704,7 @@ jobs: ) - if: ${{ !cancelled() }} - uses: ./.github/actions/screendump + uses: ./.github/actions/test_artifacts - name: Generate gcov files if: matrix.coverage diff --git a/Filelist b/Filelist index 803de2ae0e..9b06173811 100644 --- a/Filelist +++ b/Filelist @@ -10,8 +10,8 @@ SRC_ALL = \ .github/ISSUE_TEMPLATE/feature_request.md \ .github/workflows/ci.yml \ .github/workflows/codeql-analysis.yml \ - .github/actions/screendump/action.yml \ .github/workflows/coverity.yml \ + .github/actions/test_artifacts/action.yml \ .github/dependabot.yml \ .gitignore \ .hgignore \ diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index ded31975b8..9bb500e265 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -247,6 +247,11 @@ func RunTheTest(test) let g:timeout_start = localtime() endif + if ValgrindOrAsan() + let g:vim_indent = {"searchpair_timeout": 1024} + let g:python_indent = {"searchpair_timeout": 1024} + endif + " Avoid stopping at the "hit enter" prompt set nomore diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim index 1edf65ac88..a9b422c30e 100644 --- a/src/testdir/shared.vim +++ b/src/testdir/shared.vim @@ -318,6 +318,14 @@ func RunningWithValgrind() return GetVimCommand() =~ '\' endfunc +func RunningAsan() + return exists("$ASAN_OPTIONS") +endfunc + +func ValgrindOrAsan() + return RunningWithValgrind() || RunningAsan() +endfun + " Get the command to run Vim, with --clean instead of "-u NONE". func GetVimCommandClean() let cmd = GetVimCommand() diff --git a/src/version.c b/src/version.c index 493de72f68..4aa4ab7ed2 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 */ +/**/ + 827, /**/ 826, /**/ From 8d4477ef220e5af0b9b1a6e4fc38570a063403e4 Mon Sep 17 00:00:00 2001 From: John Marriott Date: Sat, 2 Nov 2024 15:59:01 +0100 Subject: [PATCH 005/106] patch 9.1.0828: string_T struct could be used more often Problem: string_T struct could be used more often Solution: Refactor code and make use of string_T struct for key-value pairs, reformat overlong lines (John Marriott) closes: #15975 Signed-off-by: John Marriott Signed-off-by: Christian Brabandt --- src/autocmd.c | 21 ++++++++++++--------- src/ex_docmd.c | 10 ++++++---- src/highlight.c | 44 ++++++++++++++++++++++++++------------------ src/misc2.c | 13 ++++++++----- src/regexp.c | 6 +++--- src/structs.h | 7 +++---- src/syntax.c | 2 +- src/usercmd.c | 26 +++++++++++++++----------- src/version.c | 2 ++ 9 files changed, 76 insertions(+), 55 deletions(-) diff --git a/src/autocmd.c b/src/autocmd.c index 00f41bddd9..330db42303 100644 --- a/src/autocmd.c +++ b/src/autocmd.c @@ -707,8 +707,8 @@ event_name2nr(char_u *start, char_u **end) ; target.key = 0; - target.value = (char *)start; - target.length = (size_t)(p - start); + target.value.string = start; + target.value.length = (size_t)(p - start); // special cases: // BufNewFile and BufRead are searched for ALOT (especially at startup) @@ -752,7 +752,7 @@ event_nr2name(event_T event) for (i = cache_last_index; cache_tab[i] >= 0; ) { if ((event_T)event_tab[cache_tab[i]].key == event) - return (char_u *)event_tab[cache_tab[i]].value; + return event_tab[cache_tab[i]].value.string; if (i == 0) i = ARRAY_LENGTH(cache_tab) - 1; @@ -780,7 +780,8 @@ event_nr2name(event_T event) } } - return (i == (int)ARRAY_LENGTH(event_tab)) ? (char_u *)"Unknown" : (char_u *)event_tab[i].value; + return (i == (int)ARRAY_LENGTH(event_tab)) ? (char_u *)"Unknown" : + event_tab[i].value.string; } /* @@ -2880,7 +2881,7 @@ get_event_name(expand_T *xp UNUSED, int idx) if (i < 0 || i >= (int)ARRAY_LENGTH(event_tab)) return NULL; - return (char_u *)event_tab[i].value; + return event_tab[i].value.string; } /* @@ -2893,7 +2894,7 @@ get_event_name_no_group(expand_T *xp UNUSED, int idx) if (idx < 0 || idx >= (int)ARRAY_LENGTH(event_tab)) return NULL; - return (char_u *)event_tab[idx].value; + return event_tab[idx].value.string; } @@ -3365,9 +3366,11 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv) keyvalue_T *entry; target.key = 0; - target.value = (char *)name; - target.length = (int)STRLEN(target.value); - entry = (keyvalue_T *)bsearch(&target, &event_tab, ARRAY_LENGTH(event_tab), sizeof(event_tab[0]), cmp_keyvalue_value_ni); + target.value.string = name; + target.value.length = STRLEN(target.value.string); + entry = (keyvalue_T *)bsearch(&target, &event_tab, + ARRAY_LENGTH(event_tab), sizeof(event_tab[0]), + cmp_keyvalue_value_ni); if (entry == NULL) { semsg(_(e_no_such_event_str), name); diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 807b470d8b..d60e34473c 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -9530,14 +9530,16 @@ find_cmdline_var(char_u *src, size_t *usedlen) case '<': target.key = 0; - target.value = (char *)src + 1; // skip over '<' - target.length = 0; // not used, see cmp_keyvalue_value_n() + target.value.string = src + 1; // skip over '<' + target.value.length = 0; // not used, see cmp_keyvalue_value_n() - entry = (keyvalue_T *)bsearch(&target, &spec_str_tab, ARRAY_LENGTH(spec_str_tab), sizeof(spec_str_tab[0]), cmp_keyvalue_value_n); + entry = (keyvalue_T *)bsearch(&target, &spec_str_tab, + ARRAY_LENGTH(spec_str_tab), sizeof(spec_str_tab[0]), + cmp_keyvalue_value_n); if (entry == NULL) return -1; - *usedlen = entry->length + 1; + *usedlen = entry->value.length + 1; return entry->key; default: diff --git a/src/highlight.c b/src/highlight.c index d3ea2d2016..1a4c76d943 100644 --- a/src/highlight.c +++ b/src/highlight.c @@ -869,11 +869,13 @@ highlight_set_termgui_attr(int idx, char_u *key, char_u *arg, int init) attr = 0; off = 0; target.key = 0; - target.length = 0; // not used, see cmp_keyvalue_value_ni() + target.value.length = 0; // not used, see cmp_keyvalue_value_ni() while (arg[off] != NUL) { - target.value = (char *)arg + off; - entry = (keyvalue_T *)bsearch(&target, &highlight_tab, ARRAY_LENGTH(highlight_tab), sizeof(highlight_tab[0]), cmp_keyvalue_value_ni); + target.value.string = arg + off; + entry = (keyvalue_T *)bsearch(&target, &highlight_tab, + ARRAY_LENGTH(highlight_tab), sizeof(highlight_tab[0]), + cmp_keyvalue_value_ni); if (entry == NULL) { semsg(_(e_illegal_value_str), arg); @@ -881,7 +883,7 @@ highlight_set_termgui_attr(int idx, char_u *key, char_u *arg, int init) } attr |= entry->key; - off += entry->length; + off += entry->value.length; if (arg[off] == ',') // another one follows ++off; } @@ -1214,9 +1216,11 @@ highlight_set_cterm_color( keyvalue_T *entry; target.key = 0; - target.value = (char *)arg; - target.length = 0; // not used, see cmp_keyvalue_value_i() - entry = (keyvalue_T *)bsearch(&target, &color_name_tab, ARRAY_LENGTH(color_name_tab), sizeof(color_name_tab[0]), cmp_keyvalue_value_i); + target.value.string = arg; + target.value.length = 0; // not used, see cmp_keyvalue_value_i() + entry = (keyvalue_T *)bsearch(&target, &color_name_tab, + ARRAY_LENGTH(color_name_tab), sizeof(color_name_tab[0]), + cmp_keyvalue_value_i); if (entry == NULL) { semsg(_(e_color_name_or_number_not_recognized_str), key_start); @@ -2541,9 +2545,10 @@ gui_get_color_cmn(char_u *name) return color; target.key = 0; - target.value = (char *)name; - target.length = 0; // not used, see cmp_keyvalue_value_i() - entry = (keyvalue_T *)bsearch(&target, &rgb_tab, ARRAY_LENGTH(rgb_tab), sizeof(rgb_tab[0]), cmp_keyvalue_value_i); + target.value.string = name; + target.value.length = 0; // not used, see cmp_keyvalue_value_i() + entry = (keyvalue_T *)bsearch(&target, &rgb_tab, ARRAY_LENGTH(rgb_tab), + sizeof(rgb_tab[0]), cmp_keyvalue_value_i); if (entry != NULL) return gui_adjust_rgb((guicolor_T)entry->key); @@ -3139,8 +3144,8 @@ highlight_list_arg( STRCPY(buf + buflen, (char_u *)","); ++buflen; } - STRCPY(buf + buflen, (char_u *)highlight_index_tab[i]->value); - buflen += highlight_index_tab[i]->length; + STRCPY(buf + buflen, highlight_index_tab[i]->value.string); + buflen += highlight_index_tab[i]->value.length; iarg &= ~highlight_index_tab[i]->key; // don't want "inverse"/"reverse" } } @@ -4236,8 +4241,10 @@ highlight_get_attr_dict(int hlattr) { if (hlattr & highlight_index_tab[i]->key) { - dict_add_bool(dict, highlight_index_tab[i]->value, VVAL_TRUE); - hlattr &= ~highlight_index_tab[i]->key; // don't want "inverse"/"reverse" + dict_add_bool(dict, (char *)highlight_index_tab[i]->value.string, + VVAL_TRUE); + // don't want "inverse"/"reverse" + hlattr &= ~highlight_index_tab[i]->key; } } @@ -4478,14 +4485,15 @@ hldict_attr_to_str( p = attr_str; for (i = 0; i < (int)ARRAY_LENGTH(highlight_tab); ++i) { - if (dict_get_bool(attrdict, highlight_tab[i].value, VVAL_FALSE) == VVAL_TRUE) + if (dict_get_bool(attrdict, (char *)highlight_tab[i].value.string, + VVAL_FALSE) == VVAL_TRUE) { if (p != attr_str && (size_t)(p - attr_str + 2) < len) STRCPY(p, (char_u *)","); - if (p - attr_str + highlight_tab[i].length + 1 < len) + if (p - attr_str + highlight_tab[i].value.length + 1 < len) { - STRCPY(p, highlight_tab[i].value); - p += highlight_tab[i].length; + STRCPY(p, highlight_tab[i].value.string); + p += highlight_tab[i].value.length; } } } diff --git a/src/misc2.c b/src/misc2.c index 31feebfe49..dc0d83f5aa 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -3077,7 +3077,7 @@ cmp_keyvalue_value(const void *a, const void *b) keyvalue_T *kv1 = (keyvalue_T *)a; keyvalue_T *kv2 = (keyvalue_T *)b; - return STRCMP(kv1->value, kv2->value); + return STRCMP(kv1->value.string, kv2->value.string); } // compare two keyvalue_T structs by value with length @@ -3087,7 +3087,8 @@ cmp_keyvalue_value_n(const void *a, const void *b) keyvalue_T *kv1 = (keyvalue_T *)a; keyvalue_T *kv2 = (keyvalue_T *)b; - return STRNCMP(kv1->value, kv2->value, MAX(kv1->length, kv2->length)); + return STRNCMP(kv1->value.string, kv2->value.string, MAX(kv1->value.length, + kv2->value.length)); } // compare two keyvalue_T structs by case insensitive value @@ -3097,17 +3098,19 @@ cmp_keyvalue_value_i(const void *a, const void *b) keyvalue_T *kv1 = (keyvalue_T *)a; keyvalue_T *kv2 = (keyvalue_T *)b; - return STRICMP(kv1->value, kv2->value); + return STRICMP(kv1->value.string, kv2->value.string); } // compare two keyvalue_T structs by case insensitive ASCII value -// with length +// with value.length int cmp_keyvalue_value_ni(const void *a, const void *b) { keyvalue_T *kv1 = (keyvalue_T *)a; keyvalue_T *kv2 = (keyvalue_T *)b; - return vim_strnicmp_asc(kv1->value, kv2->value, MAX(kv1->length, kv2->length)); + return vim_strnicmp_asc((char *)kv1->value.string, + (char *)kv2->value.string, MAX(kv1->value.length, + kv2->value.length)); } diff --git a/src/regexp.c b/src/regexp.c index b020a43e83..ea6079b008 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -265,8 +265,8 @@ get_char_class(char_u **pp) static keyvalue_T *last_entry = NULL; target.key = 0; - target.value = (char *)*pp + 2; - target.length = 0; // not used, see cmp_keyvalue_value_n() + target.value.string = *pp + 2; + target.value.length = 0; // not used, see cmp_keyvalue_value_n() if (last_entry != NULL && cmp_keyvalue_value_n(&target, last_entry) == 0) entry = last_entry; @@ -277,7 +277,7 @@ get_char_class(char_u **pp) if (entry != NULL) { last_entry = entry; - *pp += entry->length + 2; + *pp += entry->value.length + 2; return entry->key; } } diff --git a/src/structs.h b/src/structs.h index d11279645d..33367f099a 100644 --- a/src/structs.h +++ b/src/structs.h @@ -5087,13 +5087,12 @@ typedef struct { // Return the length of a string literal #define STRLEN_LITERAL(s) (sizeof(s) - 1) -// Store a key/value pair +// Store a key/value (string) pair typedef struct { int key; // the key - char *value; // the value string - size_t length; // length of the value string + string_T value; // the value } keyvalue_T; #define KEYVALUE_ENTRY(k, v) \ - {(k), (v), STRLEN_LITERAL(v)} + {(k), {((char_u *)v), STRLEN_LITERAL(v)}} diff --git a/src/syntax.c b/src/syntax.c index eec57999d7..6940aa124f 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -4066,7 +4066,7 @@ syn_list_flags(keyvalue_T *nlist, int nr_entries, int flags, int attr) for (i = 0; i < nr_entries; ++i) if (flags & nlist[i].key) { - msg_puts_attr(nlist[i].value, attr); + msg_puts_attr((char *)nlist[i].value.string, attr); msg_putchar(' '); } } diff --git a/src/usercmd.c b/src/usercmd.c index 43409ae227..c0d1bdb690 100644 --- a/src/usercmd.c +++ b/src/usercmd.c @@ -465,7 +465,7 @@ get_user_cmd_complete(expand_T *xp UNUSED, int idx) { if (idx < 0 || idx >= (int)ARRAY_LENGTH(command_complete_tab)) return NULL; - return (char_u *)command_complete_tab[idx].value; + return command_complete_tab[idx].value.string; } /* @@ -494,7 +494,7 @@ cmdcomplete_type_to_str(int expand) kv = get_commandtype(expand); - return (kv == NULL) ? NULL : (char_u *)kv->value; + return (kv == NULL) ? NULL : kv->value.string; } /* @@ -514,8 +514,8 @@ cmdcomplete_str_to_type(char_u *complete_str) return EXPAND_USER_LIST; target.key = 0; - target.value = (char *)complete_str; - target.length = 0; // not used, see cmp_keyvalue_value() + target.value.string = complete_str; + target.value.length = 0; // not used, see cmp_keyvalue_value() if (last_entry != NULL && cmp_keyvalue_value(&target, last_entry) == 0) entry = last_entry; @@ -670,8 +670,8 @@ uc_list(char_u *name, size_t name_len) entry = get_commandtype(cmd->uc_compl); if (entry != NULL) { - STRCPY(IObuff + len, entry->value); - len += entry->length; + STRCPY(IObuff + len, entry->value.string); + len += entry->value.length; #ifdef FEAT_EVAL if (p_verbose > 0 && cmd->uc_compl_arg != NULL) { @@ -826,8 +826,8 @@ parse_compl_arg( } target.key = 0; - target.value = (char *)value; - target.length = valend; + target.value.string = value; + target.value.length = valend; if (last_entry != NULL && cmp_keyvalue_value_n(&target, last_entry) == 0) entry = last_entry; @@ -1637,15 +1637,19 @@ produce_cmdmods(char_u *buf, cmdmod_T *cmod, int quote) // the modifiers that are simple flags for (i = 0; i < (int)ARRAY_LENGTH(mod_entry_tab); ++i) if (cmod->cmod_flags & mod_entry_tab[i].key) - buflen += add_cmd_modifier(buf, buflen, mod_entry_tab[i].value, mod_entry_tab[i].length, &multi_mods); + buflen += add_cmd_modifier(buf, buflen, + (char *)mod_entry_tab[i].value.string, + mod_entry_tab[i].value.length, &multi_mods); // :silent if (cmod->cmod_flags & CMOD_SILENT) { if (cmod->cmod_flags & CMOD_ERRSILENT) - buflen += add_cmd_modifier(buf, buflen, "silent!", STRLEN_LITERAL("silent!"), &multi_mods); + buflen += add_cmd_modifier(buf, buflen, "silent!", + STRLEN_LITERAL("silent!"), &multi_mods); else - buflen += add_cmd_modifier(buf, buflen, "silent", STRLEN_LITERAL("silent"), &multi_mods); + buflen += add_cmd_modifier(buf, buflen, "silent", + STRLEN_LITERAL("silent"), &multi_mods); } // :verbose diff --git a/src/version.c b/src/version.c index 4aa4ab7ed2..2e8948545a 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 */ +/**/ + 828, /**/ 827, /**/ From 8ce738de3fd7192fa6274730594305cde780074c Mon Sep 17 00:00:00 2001 From: Luca Saccarola Date: Sat, 2 Nov 2024 16:22:45 +0100 Subject: [PATCH 006/106] patch 9.1.0829: Vim source code uses a mix of tabs and spaces Problem: Vim source code uses a mix of tabs and spaces Solution: Expand tabs in sound.c, this is an experiment (Luca Saccarola) closes: #15969 Signed-off-by: Luca Saccarola Signed-off-by: Christian Brabandt --- src/sound.c | 264 +++++++++++++++++++++++++------------------------- src/version.c | 2 + 2 files changed, 134 insertions(+), 132 deletions(-) diff --git a/src/sound.c b/src/sound.c index abe412ca90..04a16513f5 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1,6 +1,6 @@ -/* vi:set ts=8 sts=4 sw=4 noet: +/* vi:set ts=8 sts=4 sw=4 et: * - * VIM - Vi IMproved by Bram Moolenaar + * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. @@ -15,17 +15,17 @@ #if defined(FEAT_SOUND) || defined(PROTO) -static long sound_id = 0; +static long sound_id = 0; // soundcb_T is typedef'ed in proto/sound.pro struct soundcb_S { - callback_T snd_callback; + callback_T snd_callback; #ifdef MSWIN - MCIDEVICEID snd_device_id; - long snd_id; + MCIDEVICEID snd_device_id; + long snd_id; #endif - soundcb_T *snd_next; + soundcb_T *snd_next; }; static soundcb_T *first_callback = NULL; @@ -43,27 +43,27 @@ has_any_sound_callback(void) static soundcb_T * get_sound_callback(typval_T *arg) { - callback_T callback; - soundcb_T *soundcb; + callback_T callback; + soundcb_T *soundcb; if (arg->v_type == VAR_UNKNOWN) - return NULL; + return NULL; callback = get_callback(arg); if (callback.cb_name == NULL) - return NULL; + return NULL; soundcb = ALLOC_ONE(soundcb_T); if (soundcb == NULL) { - free_callback(&callback); - return NULL; + free_callback(&callback); + return NULL; } soundcb->snd_next = first_callback; first_callback = soundcb; set_callback(&soundcb->snd_callback, &callback); if (callback.cb_free_name) - vim_free(callback.cb_name); + vim_free(callback.cb_name); return soundcb; } @@ -73,8 +73,8 @@ get_sound_callback(typval_T *arg) void call_sound_callback(soundcb_T *soundcb, long snd_id, int result) { - typval_T argv[3]; - typval_T rettv; + typval_T argv[3]; + typval_T rettv; argv[0].v_type = VAR_NUMBER; argv[0].vval.v_number = snd_id; @@ -92,20 +92,20 @@ call_sound_callback(soundcb_T *soundcb, long snd_id, int result) void delete_sound_callback(soundcb_T *soundcb) { - soundcb_T *p; - soundcb_T *prev = NULL; + soundcb_T *p; + soundcb_T *prev = NULL; for (p = first_callback; p != NULL; prev = p, p = p->snd_next) - if (p == soundcb) - { - if (prev == NULL) - first_callback = p->snd_next; - else - prev->snd_next = p->snd_next; - free_callback(&p->snd_callback); - vim_free(p); - break; - } + if (p == soundcb) + { + if (prev == NULL) + first_callback = p->snd_next; + else + prev->snd_next = p->snd_next; + free_callback(&p->snd_callback); + vim_free(p); + break; + } } #if defined(HAVE_CANBERRA) || defined(PROTO) @@ -121,10 +121,10 @@ static ca_context *context = NULL; typedef struct soundcb_queue_S soundcb_queue_T; struct soundcb_queue_S { - soundcb_queue_T *scb_next; - uint32_t scb_id; // ID of the sound - int scb_result; // CA_ value - soundcb_T *scb_callback; // function to call + soundcb_queue_T *scb_next; + uint32_t scb_id; // ID of the sound + int scb_result; // CA_ value + soundcb_T *scb_callback; // function to call }; // Queue of callbacks to invoke from the main loop. @@ -137,24 +137,24 @@ static soundcb_queue_T *callback_queue = NULL; */ static void sound_callback( - ca_context *c UNUSED, - uint32_t id, - int error_code, - void *userdata) + ca_context *c UNUSED, + uint32_t id, + int error_code, + void *userdata) { - soundcb_T *soundcb = (soundcb_T *)userdata; + soundcb_T *soundcb = (soundcb_T *)userdata; soundcb_queue_T *scb; scb = ALLOC_ONE(soundcb_queue_T); if (scb == NULL) - return; + return; scb->scb_next = callback_queue; callback_queue = scb; scb->scb_id = id; scb->scb_result = error_code == CA_SUCCESS ? 0 - : error_code == CA_ERROR_CANCELED - || error_code == CA_ERROR_DESTROYED - ? 1 : 2; + : error_code == CA_ERROR_CANCELED + || error_code == CA_ERROR_DESTROYED + ? 1 : 2; scb->scb_callback = soundcb; } @@ -177,13 +177,13 @@ invoke_sound_callback(void) while (callback_queue != NULL) { - scb = callback_queue; - callback_queue = scb->scb_next; + scb = callback_queue; + callback_queue = scb->scb_next; - call_sound_callback(scb->scb_callback, scb->scb_id, scb->scb_result); + call_sound_callback(scb->scb_callback, scb->scb_id, scb->scb_result); - delete_sound_callback(scb->scb_callback); - vim_free(scb); + delete_sound_callback(scb->scb_callback); + vim_free(scb); } redraw_after_callback(TRUE, FALSE); } @@ -192,47 +192,47 @@ invoke_sound_callback(void) sound_play_common(typval_T *argvars, typval_T *rettv, int playfile) { if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) - return; + return; if (context == NULL) - ca_context_create(&context); + ca_context_create(&context); if (context == NULL) - return; + return; - soundcb_T *soundcb = get_sound_callback(&argvars[1]); - int res = CA_ERROR_INVALID; + soundcb_T *soundcb = get_sound_callback(&argvars[1]); + int res = CA_ERROR_INVALID; ++sound_id; if (soundcb == NULL) { - res = ca_context_play(context, sound_id, - playfile ? CA_PROP_MEDIA_FILENAME : CA_PROP_EVENT_ID, - tv_get_string(&argvars[0]), - CA_PROP_CANBERRA_CACHE_CONTROL, "volatile", - NULL); + res = ca_context_play(context, sound_id, + playfile ? CA_PROP_MEDIA_FILENAME : CA_PROP_EVENT_ID, + tv_get_string(&argvars[0]), + CA_PROP_CANBERRA_CACHE_CONTROL, "volatile", + NULL); } else { - static ca_proplist *proplist = NULL; - - ca_proplist_create(&proplist); - if (proplist != NULL) - { - if (playfile) - ca_proplist_sets(proplist, CA_PROP_MEDIA_FILENAME, - (char *)tv_get_string(&argvars[0])); - else - ca_proplist_sets(proplist, CA_PROP_EVENT_ID, - (char *)tv_get_string(&argvars[0])); - ca_proplist_sets(proplist, CA_PROP_CANBERRA_CACHE_CONTROL, - "volatile"); - res = ca_context_play_full(context, sound_id, proplist, - sound_callback, soundcb); - if (res != CA_SUCCESS) - delete_sound_callback(soundcb); - - ca_proplist_destroy(proplist); - } + static ca_proplist *proplist = NULL; + + ca_proplist_create(&proplist); + if (proplist != NULL) + { + if (playfile) + ca_proplist_sets(proplist, CA_PROP_MEDIA_FILENAME, + (char *)tv_get_string(&argvars[0])); + else + ca_proplist_sets(proplist, CA_PROP_EVENT_ID, + (char *)tv_get_string(&argvars[0])); + ca_proplist_sets(proplist, CA_PROP_CANBERRA_CACHE_CONTROL, + "volatile"); + res = ca_context_play_full(context, sound_id, proplist, + sound_callback, soundcb); + if (res != CA_SUCCESS) + delete_sound_callback(soundcb); + + ca_proplist_destroy(proplist); + } } rettv->vval.v_number = res == CA_SUCCESS ? sound_id : 0; } @@ -259,10 +259,10 @@ f_sound_playfile(typval_T *argvars, typval_T *rettv) f_sound_stop(typval_T *argvars, typval_T *rettv UNUSED) { if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) - return; + return; if (context != NULL) - ca_context_cancel(context, tv_get_number(&argvars[0])); + ca_context_cancel(context, tv_get_number(&argvars[0])); } /* @@ -272,7 +272,7 @@ f_sound_stop(typval_T *argvars, typval_T *rettv UNUSED) f_sound_clear(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { if (context == NULL) - return; + return; ca_context_destroy(context); context = NULL; } @@ -284,17 +284,17 @@ sound_free(void) soundcb_queue_T *scb; if (context != NULL) - ca_context_destroy(context); + ca_context_destroy(context); while (first_callback != NULL) - delete_sound_callback(first_callback); + delete_sound_callback(first_callback); while (callback_queue != NULL) { - scb = callback_queue; - callback_queue = scb->scb_next; - delete_sound_callback(scb->scb_callback); - vim_free(scb); + scb = callback_queue; + callback_queue = scb->scb_next; + delete_sound_callback(scb->scb_callback); + vim_free(scb); } } # endif @@ -310,29 +310,29 @@ static HWND g_hWndSound = NULL; static LRESULT CALLBACK sound_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - soundcb_T *p; + soundcb_T *p; switch (message) { - case MM_MCINOTIFY: - for (p = first_callback; p != NULL; p = p->snd_next) - if (p->snd_device_id == (MCIDEVICEID) lParam) - { - char buf[32]; + case MM_MCINOTIFY: + for (p = first_callback; p != NULL; p = p->snd_next) + if (p->snd_device_id == (MCIDEVICEID) lParam) + { + char buf[32]; - vim_snprintf(buf, sizeof(buf), "close sound%06ld", - p->snd_id); - mciSendStringA(buf, NULL, 0, 0); + vim_snprintf(buf, sizeof(buf), "close sound%06ld", + p->snd_id); + mciSendStringA(buf, NULL, 0, 0); - long result = wParam == MCI_NOTIFY_SUCCESSFUL ? 0 - : wParam == MCI_NOTIFY_ABORTED ? 1 : 2; - call_sound_callback(p, p->snd_id, result); + long result = wParam == MCI_NOTIFY_SUCCESSFUL ? 0 + : wParam == MCI_NOTIFY_ABORTED ? 1 : 2; + call_sound_callback(p, p->snd_id, result); - delete_sound_callback(p); - redraw_after_callback(TRUE, FALSE); + delete_sound_callback(p); + redraw_after_callback(TRUE, FALSE); - } - break; + } + break; } return DefWindowProc(hwnd, message, wParam, lParam); @@ -343,12 +343,12 @@ sound_window(void) { if (g_hWndSound == NULL) { - LPCSTR clazz = "VimSound"; - WNDCLASS wndclass = { - 0, sound_wndproc, 0, 0, g_hinst, NULL, 0, 0, NULL, clazz }; - RegisterClass(&wndclass); - g_hWndSound = CreateWindow(clazz, NULL, 0, 0, 0, 0, 0, - HWND_MESSAGE, NULL, g_hinst, NULL); + LPCSTR clazz = "VimSound"; + WNDCLASS wndclass = { + 0, sound_wndproc, 0, 0, g_hinst, NULL, 0, 0, NULL, clazz }; + RegisterClass(&wndclass); + g_hWndSound = CreateWindow(clazz, NULL, 0, 0, 0, 0, 0, + HWND_MESSAGE, NULL, g_hinst, NULL); } return g_hWndSound; @@ -357,33 +357,33 @@ sound_window(void) void f_sound_playevent(typval_T *argvars, typval_T *rettv) { - WCHAR *wp; + WCHAR *wp; if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) - return; + return; wp = enc_to_utf16(tv_get_string(&argvars[0]), NULL); if (wp == NULL) - return; + return; if (PlaySoundW(wp, NULL, SND_ASYNC | SND_ALIAS)) - rettv->vval.v_number = ++sound_id; + rettv->vval.v_number = ++sound_id; free(wp); } void f_sound_playfile(typval_T *argvars, typval_T *rettv) { - long newid = sound_id + 1; - size_t len; - char_u *p, *filename; - WCHAR *wp; - soundcb_T *soundcb; - char buf[32]; - MCIERROR err; + long newid = sound_id + 1; + size_t len; + char_u *p, *filename; + WCHAR *wp; + soundcb_T *soundcb; + char buf[32]; + MCIERROR err; if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) - return; + return; filename = tv_get_string(&argvars[0]); @@ -391,24 +391,24 @@ f_sound_playfile(typval_T *argvars, typval_T *rettv) p = alloc(len); if (p == NULL) { - return; + return; } vim_snprintf((char *)p, len, "open \"%s\" alias sound%06ld", filename, newid); wp = enc_to_utf16((char_u *)p, NULL); free(p); if (wp == NULL) - return; + return; err = mciSendStringW(wp, NULL, 0, sound_window()); free(wp); if (err != 0) - return; + return; vim_snprintf(buf, sizeof(buf), "play sound%06ld notify", newid); err = mciSendStringA(buf, NULL, 0, sound_window()); if (err != 0) - goto failure; + goto failure; sound_id = newid; rettv->vval.v_number = sound_id; @@ -416,9 +416,9 @@ f_sound_playfile(typval_T *argvars, typval_T *rettv) soundcb = get_sound_callback(&argvars[1]); if (soundcb != NULL) { - vim_snprintf(buf, sizeof(buf), "sound%06ld", newid); - soundcb->snd_id = newid; - soundcb->snd_device_id = mciGetDeviceID(buf); + vim_snprintf(buf, sizeof(buf), "sound%06ld", newid); + soundcb->snd_id = newid; + soundcb->snd_device_id = mciGetDeviceID(buf); } return; @@ -434,7 +434,7 @@ f_sound_stop(typval_T *argvars, typval_T *rettv UNUSED) char buf[32]; if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) - return; + return; id = tv_get_number(&argvars[0]); vim_snprintf(buf, sizeof(buf), "stop sound%06ld", id); @@ -455,7 +455,7 @@ sound_free(void) CloseWindow(g_hWndSound); while (first_callback != NULL) - delete_sound_callback(first_callback); + delete_sound_callback(first_callback); } # endif @@ -466,7 +466,7 @@ sound_free(void) sound_play_common(typval_T *argvars, typval_T *rettv, bool playfile) { if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) - return; + return; char_u *sound_name = tv_get_string(&argvars[0]); soundcb_T *soundcb = get_sound_callback(&argvars[1]); @@ -476,7 +476,7 @@ sound_play_common(typval_T *argvars, typval_T *rettv, bool playfile) bool play_success = sound_mch_play(sound_name, sound_id, soundcb, playfile); if (!play_success && soundcb) { - delete_sound_callback(soundcb); + delete_sound_callback(soundcb); } rettv->vval.v_number = play_success ? sound_id : 0; } @@ -497,7 +497,7 @@ f_sound_playfile(typval_T *argvars, typval_T *rettv) f_sound_stop(typval_T *argvars, typval_T *rettv UNUSED) { if (in_vim9script() && check_for_number_arg(argvars, 0) == FAIL) - return; + return; sound_mch_stop(tv_get_number(&argvars[0])); } @@ -513,7 +513,7 @@ sound_free(void) { sound_mch_free(); while (first_callback != NULL) - delete_sound_callback(first_callback); + delete_sound_callback(first_callback); } #endif diff --git a/src/version.c b/src/version.c index 2e8948545a..27d5bc6dde 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 */ +/**/ + 829, /**/ 828, /**/ From 88542445871d882b2a0e79410774797a73fe9e60 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sat, 2 Nov 2024 16:29:55 +0100 Subject: [PATCH 007/106] git: ignore reformatting commit for git-blame (after v9.1.0829) See: https://git-scm.com/docs/git-config#Documentation/git-config.txt-blameignoreRevsFile Enable this using the following command in your copy: git config blame.ignoreRevsFile .git-blame-ignore-revs Github should pick it up automatically Signed-off-by: Christian Brabandt --- .git-blame-ignore-revs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..f859027d68 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,9 @@ +# When making commits that are strictly formatting/style changes, add the +# commit hash here, so git blame can ignore the change. See docs for more details: +# +# https://git-scm.com/docs/git-config#Documentation/git-config.txt-blameignoreRevsFile +# +# Run this command to always ignore formatting commits in git blame +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# +8ce738de3fd7192fa6274730594305cde780074c # expand tabs to spaces in sound.c From d181bafd0bb53f3caaf15a95a329a31d8208206b Mon Sep 17 00:00:00 2001 From: Yinzuo Jiang Date: Sat, 2 Nov 2024 16:34:40 +0100 Subject: [PATCH 008/106] runtime(typst): synchronize updates from the upstream typst.vim 2 commits included from the upstream: - https://github.com/kaarmu/typst.vim/commit/2a4a0e0662f2f882403af7200b4249c564a621ab - https://github.com/kaarmu/typst.vim/commit/50e89f481102d5c9ef6990b9f8086c0c7d64bff6 Signed-off-by: Yinzuo Jiang Signed-off-by: Gregory Anders Signed-off-by: Christian Brabandt --- runtime/autoload/typst.vim | 5 ++++- runtime/syntax/typst.vim | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/runtime/autoload/typst.vim b/runtime/autoload/typst.vim index baf765a30b..6d097dd922 100644 --- a/runtime/autoload/typst.vim +++ b/runtime/autoload/typst.vim @@ -1,6 +1,6 @@ " Language: Typst " Maintainer: Gregory Anders -" Last Change: 2024 Oct 21 +" Last Change: 2024 Nov 02 " Based on: https://github.com/kaarmu/typst.vim function! typst#indentexpr() abort @@ -18,6 +18,9 @@ function! typst#indentexpr() abort " Use last indent for block comments if l:synname == 'typstCommentBlock' return l:ind + " do not change the indents of bullet lists + elseif l:synname == 'typstMarkupBulletList' + return indent(a:lnum) endif if l:pline =~ '\v[{[(]\s*$' diff --git a/runtime/syntax/typst.vim b/runtime/syntax/typst.vim index 82fdadb3d5..dae1424780 100644 --- a/runtime/syntax/typst.vim +++ b/runtime/syntax/typst.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Typst " Maintainer: Gregory Anders -" Last Change: 2024-07-14 +" Last Change: 2024 Nov 02 " Based on: https://github.com/kaarmu/typst.vim if exists('b:current_syntax') @@ -18,8 +18,8 @@ syntax cluster typstCommon " Common > Comment {{{2 syntax cluster typstComment \ contains=typstCommentBlock,typstCommentLine -syntax match typstCommentBlock - \ #/\*\%(\_.\{-}\)\*/# +syntax region typstCommentBlock + \ start="/\*" end="\*/" keepend \ contains=typstCommentTodo,@Spell syntax match typstCommentLine \ #//.*# From bc10be7a4060748ed1876ab91cf53a2a8701ac13 Mon Sep 17 00:00:00 2001 From: glepnir Date: Sat, 2 Nov 2024 16:45:01 +0100 Subject: [PATCH 009/106] patch 9.1.0830: using wrong highlight group for spaces for popupmenu Problem: using wrong highlight group for spaces for popupmenu Solution: use original attribute instead of combined attributed (glepnir) closes: #15978 Signed-off-by: glepnir Signed-off-by: Christian Brabandt --- src/popupmenu.c | 4 ++-- src/testdir/dumps/Test_pum_highlights_17.dump | 20 +++++++++++++++++ src/testdir/test_popup.vim | 22 +++++++++++++++++-- src/version.c | 2 ++ 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 src/testdir/dumps/Test_pum_highlights_17.dump diff --git a/src/popupmenu.c b/src/popupmenu.c index 4d77c666a5..be8016f627 100644 --- a/src/popupmenu.c +++ b/src/popupmenu.c @@ -839,11 +839,11 @@ pum_redraw(void) #ifdef FEAT_RIGHTLEFT if (pum_rl) screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ', - ' ', attr); + ' ', orig_attr); else #endif screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ', - attr); + orig_attr); if (pum_scrollbar > 0) { #ifdef FEAT_RIGHTLEFT diff --git a/src/testdir/dumps/Test_pum_highlights_17.dump b/src/testdir/dumps/Test_pum_highlights_17.dump new file mode 100644 index 0000000000..2439c4c10c --- /dev/null +++ b/src/testdir/dumps/Test_pum_highlights_17.dump @@ -0,0 +1,20 @@ +|a+0&#ffffff0|w|o|r|d|1> @68 +|a+0#ff404010#e0e0e08|w|o|r|d|1| +0#0000001&@8| +0#4040ff13#ffffff0@59 +|你*0#ff404010#ffd7ff255|好| +0#0000001&@10| +0#4040ff13#ffffff0@59 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |2| +0#0000000&@26 diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index 3c748a4a52..6b807c8c3e 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -1507,10 +1507,18 @@ endfunc func Test_pum_user_abbr_hlgroup() CheckScreendump let lines =<< trim END - func CompleteFunc( findstart, base ) + let s:var = 0 + func CompleteFunc(findstart, base) if a:findstart return 0 endif + if s:var == 1 + return { + \ 'words': [ + \ { 'word': 'aword1', 'abbr_hlgroup': 'StrikeFake' }, + \ { 'word': '你好', 'abbr_hlgroup': 'StrikeFake' }, + \]} + endif return { \ 'words': [ \ { 'word': 'aword1', 'menu': 'extra text 1', 'kind': 'W', 'abbr_hlgroup': 'StrikeFake' }, @@ -1518,6 +1526,9 @@ func Test_pum_user_abbr_hlgroup() \ { 'word': '你好', 'menu': 'extra text 3', 'kind': 'W', 'abbr_hlgroup': 'StrikeFake' }, \]} endfunc + func ChangeVar() + let s:var = 1 + endfunc set completeopt=menu set completefunc=CompleteFunc @@ -1545,13 +1556,20 @@ func Test_pum_user_abbr_hlgroup() call VerifyScreenDump(buf, 'Test_pum_highlights_14', {}) call term_sendkeys(buf, "\\") + call TermWait(buf) + call term_sendkeys(buf, ":call ChangeVar()\") + call TermWait(buf) + call term_sendkeys(buf, "S\\") + call VerifyScreenDump(buf, 'Test_pum_highlights_17', {}) + call term_sendkeys(buf, "\\") + call StopVimInTerminal(buf) endfunc func Test_pum_user_kind_hlgroup() CheckScreendump let lines =<< trim END - func CompleteFunc( findstart, base ) + func CompleteFunc(findstart, base) if a:findstart return 0 endif diff --git a/src/version.c b/src/version.c index 27d5bc6dde..74660c6876 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 */ +/**/ + 830, /**/ 829, /**/ From 29ce4190767b12314770b6da4768a24c19cd8a38 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sat, 2 Nov 2024 16:49:57 +0100 Subject: [PATCH 010/106] Filelist: ignore .git-blame-ignore-revs Signed-off-by: Christian Brabandt --- Filelist | 1 + 1 file changed, 1 insertion(+) diff --git a/Filelist b/Filelist index 9b06173811..25e3362e27 100644 --- a/Filelist +++ b/Filelist @@ -5,6 +5,7 @@ SRC_ALL = \ .cirrus.yml \ .gitattributes \ + .git-blame-ignore-revs \ .github/MAINTAINERS \ .github/ISSUE_TEMPLATE/bug_report.yml \ .github/ISSUE_TEMPLATE/feature_request.md \ From b3ec5643cd496b59eefd3ce6854b99aea72abd0c Mon Sep 17 00:00:00 2001 From: lagygoill Date: Sat, 2 Nov 2024 17:58:01 +0100 Subject: [PATCH 011/106] runtime(doc): include a TOC Vim9 plugin closes: #10446 See :h help-TOC Signed-off-by: lagygoill Signed-off-by: Christian Brabandt --- runtime/doc/helphelp.txt | 57 +- runtime/doc/tags | 2 + runtime/doc/version9.txt | 3 +- .../dist/opt/helptoc/autoload/helptoc.vim | 940 ++++++++++++++++++ .../pack/dist/opt/helptoc/plugin/helptoc.vim | 5 + 5 files changed, 1005 insertions(+), 2 deletions(-) create mode 100644 runtime/pack/dist/opt/helptoc/autoload/helptoc.vim create mode 100644 runtime/pack/dist/opt/helptoc/plugin/helptoc.vim diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index 40039e3916..86c4775fdd 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -1,4 +1,4 @@ -*helphelp.txt* For Vim version 9.1. Last change: 2024 Apr 10 +*helphelp.txt* For Vim version 9.1. Last change: 2024 Nov 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -246,6 +246,61 @@ command: > To rebuild the help tags in the runtime directory (requires write permission there): > :helptags $VIMRUNTIME/doc +< + *help-TOC* *help-toc-install* + +If you want to access an interactive table of contents, from any position in +the file, you can use the helptoc plugin. Load the plugin with: > + + packadd helptoc + +Then you can use the `:HelpToc` command to open a popup menu. +The latter supports the following normal commands: > + + key | effect + ----+--------------------------------------------------------- + j | select next entry + k | select previous entry + J | same as j, and jump to corresponding line in main buffer + K | same as k, and jump to corresponding line in main buffer + c | select nearest entry from cursor position in main buffer + g | select first entry + G | select last entry + H | collapse one level + L | expand one level + p | print current entry on command-line + + P | same as p but automatically, whenever selection changes + | press multiple times to toggle feature on/off + + q | quit menu + z | redraw menu with current entry at center + + | increase width of popup menu + - | decrease width of popup menu + ? | show/hide a help window + + | scroll down half a page + | scroll up half a page + | scroll down a whole page + | scroll up a whole page + | select first entry + | select last entry + +The plugin can also provide a table of contents in man pages, markdown files, +and terminal buffers. In the latter, the entries will be the past executed +shell commands. To find those, the following regex is used: > + + ^\w\+@\w\+:\f\+\$\s + +This is meant to match a default bash prompt. If it doesn't match your prompt, +you can change the regex with the `shell_prompt` key from the `g:helptoc` +dictionary variable: > + + let g:helptoc = {'shell_prompt': 'regex matching your shell prompt'} + +Tip: After inserting a pattern to look for with the `/` command, if you press + instead of , you can then get more context for each remaining entry +by pressing `J` or `K`. ============================================================================== 2. Translated help files *help-translated* diff --git a/runtime/doc/tags b/runtime/doc/tags index 9091976e37..1ae1ff61e9 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -8062,11 +8062,13 @@ hasmapto() builtin.txt /*hasmapto()* hebrew hebrew.txt /*hebrew* hebrew.txt hebrew.txt /*hebrew.txt* help helphelp.txt /*help* +help-TOC helphelp.txt /*help-TOC* help-buffer-options helphelp.txt /*help-buffer-options* help-context help.txt /*help-context* help-curwin tips.txt /*help-curwin* help-summary usr_02.txt /*help-summary* help-tags tags 1 +help-toc-install helphelp.txt /*help-toc-install* help-translated helphelp.txt /*help-translated* help-writing helphelp.txt /*help-writing* help-xterm-window helphelp.txt /*help-xterm-window* diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 2a3846669d..66f98e10e6 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2024 Oct 27 +*version9.txt* For Vim version 9.1. Last change: 2024 Nov 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41602,6 +41602,7 @@ Changed~ selection in the quickfix list with the "u" action. - the putty terminal is detected using an |TermResponse| autocommand in |defaults.vim| and Vim switches to a dark background +- the |help-TOC| package is included to ease navigating the documentation. *added-9.2* Added ~ diff --git a/runtime/pack/dist/opt/helptoc/autoload/helptoc.vim b/runtime/pack/dist/opt/helptoc/autoload/helptoc.vim new file mode 100644 index 0000000000..087da798e9 --- /dev/null +++ b/runtime/pack/dist/opt/helptoc/autoload/helptoc.vim @@ -0,0 +1,940 @@ +vim9script noclear + +# Config {{{1 + +const SHELL_PROMPT: string = g: + ->get('helptoc', {}) + ->get('shell_prompt', '^\w\+@\w\+:\f\+\$\s') + +# Init {{{1 + +const HELP_TEXT: list =<< trim END + normal commands in help window + ────────────────────────────── + ? hide this help window + scroll down one line + scroll up one line + + normal commands in TOC menu + ─────────────────────────── + j select next entry + k select previous entry + J same as j, and jump to corresponding line in main buffer + K same as k, and jump to corresponding line in main buffer + c select nearest entry from cursor position in main buffer + g select first entry + G select last entry + H collapse one level + L expand one level + p print selected entry on command-line + + P same as p but automatically, whenever selection changes + press multiple times to toggle feature on/off + + q quit menu + z redraw menu with selected entry at center + + increase width of popup menu + - decrease width of popup menu + / look for given text with fuzzy algorithm + ? show help window + + scroll down half a page + scroll up half a page + scroll down a whole page + scroll up a whole page + select first entry + select last entry + + title meaning + ───────────── + example: 12/34 (5/6) + broken down: + + 12 index of selected entry + 34 index of last entry + 5 index of deepest level currently visible + 6 index of maximum possible level + + tip + ─── + after inserting a pattern to look for with the / command, + if you press instead of , you can then get + more context for each remaining entry by pressing J or K +END + +const MATCH_ENTRY: dict> = { + help: {}, + + man: { + 1: (line: string, _): bool => line =~ '^\S', + 2: (line: string, _): bool => line =~ '^\%( \{3\}\)\=\S', + 3: (line: string, _): bool => line =~ '^\s\+\(\%(+\|-\)\S\+,\s\+\)*\%(+\|-\)\S\+', + }, + + markdown: { + 1: (line: string, nextline: string): bool => + (line =~ '^#[^#]' || nextline =~ '^=\+$') && line =~ '\w', + 2: (line: string, nextline: string): bool => + (line =~ '^##[^#]' || nextline =~ '^-\+$') && line =~ '\w', + 3: (line: string, _): bool => line =~ '^###[^#]', + 4: (line: string, _): bool => line =~ '^####[^#]', + 5: (line: string, _): bool => line =~ '^#####[^#]', + 6: (line: string, _): bool => line =~ '^######[^#]', + }, + + terminal: { + 1: (line: string, _): bool => line =~ SHELL_PROMPT, + } +} + +const HELP_RULERS: dict = { + '=': '^=\{40,}$', + '-': '^-\{40,}', +} +const HELP_RULER: string = HELP_RULERS->values()->join('\|') + +# the regex is copied from the help syntax plugin +const HELP_TAG: string = '\*[#-)!+-~]\+\*\%(\s\|$\)\@=' + +# Adapted from `$VIMRUNTIME/syntax/help.vim`.{{{ +# +# The original regex is: +# +# ^[-A-Z .][-A-Z0-9 .()_]*\ze\(\s\+\*\|$\) +# +# Allowing a space or a hyphen at the start can give false positives, and is +# useless, so we don't allow them. +#}}} +const HELP_HEADLINE: string = '^\C[A-Z.][-A-Z0-9 .()_]*\%(\s\+\*+\@!\|$\)' +# ^--^ +# To prevent some false positives under `:help feature-list`. + +var lvls: dict +def InitHelpLvls() + lvls = { + '*01.1*': 0, + '1.': 0, + '1.2': 0, + '1.2.3': 0, + 'header ~': 0, + HEADLINE: 0, + tag: 0, + } +enddef + +const AUGROUP: string = 'HelpToc' +var fuzzy_entries: list> +var help_winid: number +var print_entry: bool +var selected_entry_match: number + +# Interface {{{1 +export def Open() #{{{2 + var type: string = GetType() + if !MATCH_ENTRY->has_key(type) + return + endif + if type == 'terminal' && win_gettype() == 'popup' + # trying to deal with a popup menu on top of a popup terminal seems + # too tricky for now + echomsg 'does not work in a popup window; only in a regular window' + return + endif + + # invalidate the cache if the buffer's contents has changed + if exists('b:toc') && &filetype != 'man' + if b:toc.changedtick != b:changedtick + # in a terminal buffer, `b:changedtick` does not change + || type == 'terminal' && line('$') > b:toc.linecount + unlet! b:toc + endif + endif + + if !exists('b:toc') + SetToc() + endif + + var winpos: list = winnr()->win_screenpos() + var height: number = winheight(0) - 2 + var width: number = winwidth(0) + b:toc.width = b:toc.width ?? width / 3 + # the popup needs enough space to display the help message in its title + if b:toc.width < 30 + b:toc.width = 30 + endif + # Is `popup_menu()` OK with a list of dictionaries?{{{ + # + # Yes, see `:help popup_create-arguments`. + # Although, it expects dictionaries with the keys `text` and `props`. + # But we use dictionaries with the keys `text` and `lnum`. + # IOW, we abuse the feature which lets us use text properties in a popup. + #}}} + var winid: number = GetTocEntries() + ->popup_menu({ + line: winpos[0], + col: winpos[1] + width - 1, + pos: 'topright', + scrollbar: false, + highlight: type == 'terminal' ? 'Terminal' : 'Normal', + border: [], + borderchars: ['─', '│', '─', '│', '┌', '┐', '┘', '└'], + minheight: height, + maxheight: height, + minwidth: b:toc.width, + maxwidth: b:toc.width, + filter: Filter, + callback: Callback, + }) + Win_execute(winid, [$'ownsyntax {&filetype}', '&l:conceallevel = 3']) + # In a help file, we might reduce some noisy tags to a trailing asterisk. + # Hide those. + if type == 'help' + matchadd('Conceal', '\*$', 0, -1, {window: winid}) + endif + SelectNearestEntryFromCursor(winid) + + # can't set the title before jumping to the relevant line, otherwise the + # indicator in the title might be wrong + SetTitle(winid) +enddef +#}}}1 +# Core {{{1 +def SetToc() #{{{2 + var toc: dict = {entries: []} + var type: string = GetType() + toc.changedtick = b:changedtick + if !toc->has_key('width') + toc.width = 0 + endif + # We cache the toc in `b:toc` to get better performance.{{{ + # + # Without caching, when we press `H`, `L`, `H`, `L`, ... quickly for a few + # seconds, there is some lag if we then try to move with `j` and `k`. + # This can only be perceived in big man pages like with `:Man ffmpeg-all`. + #}}} + b:toc = toc + + if type == 'help' + SetTocHelp() + return + endif + + if type == 'terminal' + b:toc.linecount = line('$') + endif + + var curline: string = getline(1) + var nextline: string + var lvl_and_test: list> = MATCH_ENTRY + ->get(type, {}) + ->items() + ->sort((l: list, ll: list): number => l[0]->str2nr() - ll[0]->str2nr()) + + for lnum: number in range(1, line('$')) + nextline = getline(lnum + 1) + for [lvl: string, IsEntry: func: bool] in lvl_and_test + if IsEntry(curline, nextline) + b:toc.entries->add({ + lnum: lnum, + lvl: lvl->str2nr(), + text: curline, + }) + break + endif + endfor + curline = nextline + endfor + + InitMaxAndCurLvl() +enddef + +def SetTocHelp() #{{{2 + var main_ruler: string + for line: string in getline(1, '$') + if line =~ HELP_RULER + main_ruler = line =~ '=' ? HELP_RULERS['='] : HELP_RULERS['-'] + break + endif + endfor + + var prevline: string + var curline: string = getline(1) + var nextline: string + var in_list: bool + var last_numbered_entry: number + InitHelpLvls() + for lnum: number in range(1, line('$')) + nextline = getline(lnum + 1) + + if main_ruler != '' && curline =~ main_ruler + last_numbered_entry = 0 + # The information gathered in `lvls` might not be applicable to all + # the main sections of a help file. Let's reset it whenever we find + # a ruler. + InitHelpLvls() + endif + + # Do not assume that a list ends on an empty line. + # See the list at `:help gdb` for a counter-example. + if in_list + && curline !~ '^\d\+.\s' + && curline !~ '^\s*$' + && curline !~ '^[< \t]' + in_list = false + endif + + if prevline =~ '^\d\+\.\s' + && curline !~ '^\s*$' + && curline !~ $'^\s*{HELP_TAG}' + in_list = true + endif + + # 1. + if prevline =~ '^\d\+\.\s' + # let's assume that the start of a main entry is always followed by an + # empty line, or a line starting with a tag + && (curline =~ '^>\=\s*$' || curline =~ $'^\s*{HELP_TAG}') + # ignore a numbered line in a list + && !in_list + var current_numbered_entry: number = prevline + ->matchstr('^\d\+\ze\.\s') + ->str2nr() + if current_numbered_entry > last_numbered_entry + AddEntryInTocHelp('1.', lnum - 1, prevline) + last_numbered_entry = prevline + ->matchstr('^\d\+\ze\.\s') + ->str2nr() + endif + endif + + # 1.2 + if curline =~ '^\d\+\.\d\+\s' + if curline =~ $'\%({HELP_TAG}\s*\|\~\)$' + || (prevline =~ $'^\s*{HELP_TAG}' || nextline =~ $'^\s*{HELP_TAG}') + || (prevline =~ HELP_RULER || nextline =~ HELP_RULER) + || (prevline =~ '^\s*$' && nextline =~ '^\s*$') + AddEntryInTocHelp('1.2', lnum, curline) + endif + # 1.2.3 + elseif curline =~ '^\s\=\d\+\.\d\+\.\d\+\s' + AddEntryInTocHelp('1.2.3', lnum, curline) + endif + + # HEADLINE + if curline =~ HELP_HEADLINE + && curline !~ '^CTRL-' + && prevline->IsSpecialHelpLine() + && (nextline->IsSpecialHelpLine() || nextline =~ '^\s*(\|^\t\|^N[oO][tT][eE]:') + AddEntryInTocHelp('HEADLINE', lnum, curline) + endif + + # header ~ + if curline =~ '\~$' + && curline =~ '\w' + && curline !~ '^[ \t<]\|\t\|---+---\|^NOTE:' + && curline !~ '^\d\+\.\%(\d\+\%(\.\d\+\)\=\)\=\s' + && prevline !~ $'^\s*{HELP_TAG}' + && prevline !~ '\~$' + && nextline !~ '\~$' + AddEntryInTocHelp('header ~', lnum, curline) + endif + + # *some_tag* + if curline =~ HELP_TAG + AddEntryInTocHelp('tag', lnum, curline) + endif + + # In the Vim user manual, a main section is a special case.{{{ + # + # It's not a simple numbered section: + # + # 01.1 + # + # It's used as a tag: + # + # *01.1* Two manuals + # ^ ^ + #}}} + if prevline =~ main_ruler && curline =~ '^\*\d\+\.\d\+\*' + AddEntryInTocHelp('*01.1*', lnum, curline) + endif + + [prevline, curline] = [curline, nextline] + endfor + + # let's ignore the tag on the first line (not really interesting) + if b:toc.entries->get(0, {})->get('lnum') == 1 + b:toc.entries->remove(0) + endif + + # let's also ignore anything before the first `1.` line + var i: number = b:toc.entries + ->copy() + ->map((_, entry: dict) => entry.text) + ->match('^\s*1\.\s') + if i > 0 + b:toc.entries->remove(0, i - 1) + endif + + InitMaxAndCurLvl() + + # set level of tag entries to the deepest level + var has_tag: bool = b:toc.entries + ->copy() + ->map((_, entry: dict) => entry.text) + ->match(HELP_TAG) >= 0 + if has_tag + ++b:toc.maxlvl + endif + b:toc.entries + ->map((_, entry: dict) => entry.lvl == 0 + ? entry->extend({lvl: b:toc.maxlvl}) + : entry) + + # fix indentation + var min_lvl: number = b:toc.entries + ->copy() + ->map((_, entry: dict) => entry.lvl) + ->min() + for entry: dict in b:toc.entries + entry.text = entry.text + ->substitute('^\s*', () => repeat(' ', (entry.lvl - min_lvl) * 3), '') + endfor +enddef + +def AddEntryInTocHelp(type: string, lnum: number, line: string) #{{{2 + # don't add a duplicate entry + if lnum == b:toc.entries->get(-1, {})->get('lnum') + # For a numbered line containing a tag, *do* add an entry. + # But only for its numbered prefix, not for its tag. + # The former is the line's most meaningful representation. + if b:toc.entries->get(-1, {})->get('type') == 'tag' + b:toc.entries->remove(-1) + else + return + endif + endif + + var text: string = line + if type == 'tag' + var tags: list + text->substitute(HELP_TAG, () => !!tags->add(submatch(0)), 'g') + text = tags + # we ignore errors and warnings because those are meaningless in + # a TOC where no context is available + ->filter((_, tag: string) => tag !~ '\*[EW]\d\+\*') + ->join() + if text !~ HELP_TAG + return + endif + endif + + var maxlvl: number = lvls->values()->max() + if type == 'tag' + lvls[type] = 0 + elseif type == '1.2' + lvls[type] = lvls[type] ?? lvls->get('1.', maxlvl) + 1 + elseif type == '1.2.3' + lvls[type] = lvls[type] ?? lvls->get('1.2', maxlvl) + 1 + else + lvls[type] = lvls[type] ?? maxlvl + 1 + endif + + # Ignore noisy tags.{{{ + # + # 14. Linking groups *:hi-link* *:highlight-link* *E412* *E413* + # ^----------------------------------------^ + # ^\s*\d\+\.\%(\d\+\.\=\)*\s\+.\{-}\zs\*.* + # --- + # + # We don't use conceal because then, `matchfuzzypos()` could match concealed + # characters, which would be confusing. + #}}} + # MAKING YOUR OWN SYNTAX FILES *mysyntaxfile* + # ^------------^ + # ^\s*[A-Z].\{-}\*\zs.* + # + var after_HEADLINE: string = '^\s*[A-Z].\{-}\*\zs.*' + # 14. Linking groups *:hi-link* *:highlight-link* *E412* *E413* + # ^----------------------------------------^ + # ^\s*\d\+\.\%(\d\+\.\=\)*\s\+.\{-}\*\zs.* + var after_numbered: string = '^\s*\d\+\.\%(\d\+\.\=\)*\s\+.\{-}\*\zs.*' + # 01.3 Using the Vim tutor *tutor* *vimtutor* + # ^----------------^ + var after_numbered_tutor: string = '^\*\d\+\.\%(\d\+\.\=\)*.\{-}\t\*\zs.*' + var noisy_tags: string = $'{after_HEADLINE}\|{after_numbered}\|{after_numbered_tutor}' + text = text->substitute(noisy_tags, '', '') + # We don't remove the trailing asterisk, because the help syntax plugin + # might need it to highlight some headlines. + + b:toc.entries->add({ + lnum: lnum, + lvl: lvls[type], + text: text, + type: type, + }) +enddef + +def InitMaxAndCurLvl() #{{{2 + b:toc.maxlvl = b:toc.entries + ->copy() + ->map((_, entry: dict) => entry.lvl) + ->max() + b:toc.curlvl = b:toc.maxlvl +enddef + +def Popup_settext(winid: number, entries: list>) #{{{2 + var text: list + # When we fuzzy search the toc, the dictionaries in `entries` contain a + # `props` key, to highlight each matched character individually. + # We don't want to process those dictionaries further. + # The processing should already have been done by the caller. + if entries->get(0, {})->has_key('props') + text = entries + else + text = entries + ->copy() + ->map((_, entry: dict): string => entry.text) + endif + popup_settext(winid, text) + SetTitle(winid) + redraw +enddef + +def SetTitle(winid: number) #{{{2 + var curlnum: number + var lastlnum: number = line('$', winid) + var is_empty: bool = lastlnum == 1 + && winid->winbufnr()->getbufoneline(1) == '' + if is_empty + [curlnum, lastlnum] = [0, 0] + else + curlnum = line('.', winid) + endif + var newtitle: string = printf(' %*d/%d (%d/%d)', + len(lastlnum), curlnum, + lastlnum, + b:toc.curlvl, + b:toc.maxlvl, + ) + + var width: number = winid->popup_getoptions().minwidth + newtitle = printf('%s%*s', + newtitle, + width - newtitle->strlen(), + 'press ? for help ') + + popup_setoptions(winid, {title: newtitle}) +enddef + +def SelectNearestEntryFromCursor(winid: number) #{{{2 + var lnum: number = line('.') + var firstline: number = b:toc.entries + ->copy() + ->filter((_, line: dict): bool => line.lvl <= b:toc.curlvl && line.lnum <= lnum) + ->len() + if firstline == 0 + return + endif + Win_execute(winid, $'normal! {firstline}Gzz') +enddef + +def Filter(winid: number, key: string): bool #{{{2 + # support various normal commands for moving/scrolling + if [ + 'j', 'J', 'k', 'K', "\", "\", "\", "\", + "\", "\", + "\", "\", + 'g', 'G', "\", "\", + 'z' + ]->index(key) >= 0 + var scroll_cmd: string = { + J: 'j', + K: 'k', + g: '1G', + "\": '1G', + "\": 'G', + z: 'zz' + }->get(key, key) + + var old_lnum: number = line('.', winid) + Win_execute(winid, $'normal! {scroll_cmd}') + var new_lnum: number = line('.', winid) + + if print_entry + PrintEntry(winid) + endif + + # wrap around the edges + if new_lnum == old_lnum + scroll_cmd = { + j: '1G', + J: '1G', + k: 'G', + K: 'G', + "\": '1G', + "\": 'G', + "\": '1G', + "\": 'G', + }->get(key, '') + if !scroll_cmd->empty() + Win_execute(winid, $'normal! {scroll_cmd}') + endif + endif + + # move the cursor to the corresponding line in the main buffer + if key == 'J' || key == 'K' + var lnum: number = GetBufLnum(winid) + execute $'normal! 0{lnum}zt' + # install a match in the regular buffer to highlight the position of + # the entry in the latter + MatchDelete() + selected_entry_match = matchaddpos('IncSearch', [lnum], 0, -1) + endif + SetTitle(winid) + + return true + + elseif key == 'c' + SelectNearestEntryFromCursor(winid) + return true + + # when we press `p`, print the selected line (useful when it's truncated) + elseif key == 'p' + PrintEntry(winid) + return true + + # same thing, but automatically + elseif key == 'P' + print_entry = !print_entry + if print_entry + PrintEntry(winid) + else + echo '' + endif + return true + + elseif key == 'q' + popup_close(winid, -1) + return true + + elseif key == '?' + ToggleHelp(winid) + return true + + # scroll help window + elseif key == "\" || key == "\" + var scroll_cmd: string = {"\": 'j', "\": 'k'}->get(key, key) + if scroll_cmd == 'j' && line('.', help_winid) == line('$', help_winid) + scroll_cmd = '1G' + elseif scroll_cmd == 'k' && line('.', help_winid) == 1 + scroll_cmd = 'G' + endif + Win_execute(help_winid, $'normal! {scroll_cmd}') + return true + + # increase/decrease the popup's width + elseif key == '+' || key == '-' + var width: number = winid->popup_getoptions().minwidth + if key == '-' && width == 1 + || key == '+' && winid->popup_getpos().col == 1 + return true + endif + width = width + (key == '+' ? 1 : -1) + # remember the last width if we close and re-open the TOC later + b:toc.width = width + popup_setoptions(winid, {minwidth: width, maxwidth: width}) + return true + + elseif key == 'H' && b:toc.curlvl > 1 + || key == 'L' && b:toc.curlvl < b:toc.maxlvl + CollapseOrExpand(winid, key) + return true + + elseif key == '/' + # This is probably what the user expect if they've started a first fuzzy + # search, press Escape, then start a new one. + DisplayNonFuzzyToc(winid) + + [{ + group: AUGROUP, + event: 'CmdlineChanged', + pattern: '@', + cmd: $'FuzzySearch({winid})', + replace: true, + }, { + group: AUGROUP, + event: 'CmdlineLeave', + pattern: '@', + cmd: 'TearDown()', + replace: true, + }]->autocmd_add() + + # Need to evaluate `winid` right now with an `eval`'ed and `execute()`'ed heredoc because:{{{ + # + # - the mappings can only access the script-local namespace + # - `winid` is in the function namespace; not in the script-local one + #}}} + var input_mappings: list =<< trim eval END + cnoremap Filter({winid}, 'j') + cnoremap Filter({winid}, 'k') + cnoremap Filter({winid}, 'j') + cnoremap Filter({winid}, 'k') + END + input_mappings->execute() + + var look_for: string + try + popup_setoptions(winid, {mapping: true}) + look_for = input('look for: ', '', $'custom,{Complete->string()}') | redraw | echo '' + catch /Vim:Interrupt/ + TearDown() + finally + popup_setoptions(winid, {mapping: false}) + endtry + return look_for == '' ? true : popup_filter_menu(winid, "\") + endif + + return popup_filter_menu(winid, key) +enddef + +def FuzzySearch(winid: number) #{{{2 + var look_for: string = getcmdline() + if look_for == '' + DisplayNonFuzzyToc(winid) + return + endif + + # We match against *all* entries; not just the currently visible ones. + # Rationale: If we use a (fuzzy) search, we're probably lost. We don't know + # where the info is. + var matches: list> = b:toc.entries + ->copy() + ->matchfuzzypos(look_for, {key: 'text'}) + + fuzzy_entries = matches->get(0, [])->copy() + var pos: list> = matches->get(1, []) + + var text: list> + if !has('textprop') + text = matches->get(0, []) + else + var buf: number = winid->winbufnr() + if prop_type_get('help-fuzzy-toc', {bufnr: buf}) == {} + prop_type_add('help-fuzzy-toc', { + bufnr: buf, + combine: false, + highlight: 'IncSearch', + }) + endif + text = matches + ->get(0, []) + ->map((i: number, match: dict) => ({ + text: match.text, + props: pos[i]->copy()->map((_, col: number) => ({ + col: col + 1, + length: 1, + type: 'help-fuzzy-toc', + }))})) + endif + Win_execute(winid, 'normal! 1Gzt') + Popup_settext(winid, text) +enddef + +def DisplayNonFuzzyToc(winid: number) #{{{2 + fuzzy_entries = null_list + Popup_settext(winid, GetTocEntries()) +enddef + +def PrintEntry(winid: number) #{{{2 + echo GetTocEntries()[line('.', winid) - 1]['text'] +enddef + +def CollapseOrExpand(winid: number, key: string) #{{{2 + # Must be saved before we reset the popup contents, so we can + # automatically select the least unexpected entry in the updated popup. + var buf_lnum: number = GetBufLnum(winid) + + # find the nearest lower level for which the contents of the TOC changes + if key == 'H' + while b:toc.curlvl > 1 + var old: list> = GetTocEntries() + --b:toc.curlvl + var new: list> = GetTocEntries() + # In `:help`, there are only entries in levels 3. + # We don't want to collapse to level 2, nor 1. + # It would clear the TOC which is confusing. + if new->empty() + ++b:toc.curlvl + break + endif + var did_change: bool = new != old + if did_change || b:toc.curlvl == 1 + break + endif + endwhile + # find the nearest upper level for which the contents of the TOC changes + else + while b:toc.curlvl < b:toc.maxlvl + var old: list> = GetTocEntries() + ++b:toc.curlvl + var did_change: bool = GetTocEntries() != old + if did_change || b:toc.curlvl == b:toc.maxlvl + break + endif + endwhile + endif + + # update the popup contents + var toc_entries: list> = GetTocEntries() + Popup_settext(winid, toc_entries) + + # Try to select the same entry; if it's no longer visible, select its + # direct parent. + var toc_lnum: number = 0 + for entry: dict in toc_entries + if entry.lnum > buf_lnum + break + endif + ++toc_lnum + endfor + Win_execute(winid, $'normal! {toc_lnum ?? 1}Gzz') +enddef + +def MatchDelete() #{{{2 + if selected_entry_match == 0 + return + endif + + selected_entry_match->matchdelete() + selected_entry_match = 0 +enddef + +def Callback(winid: number, choice: number) #{{{2 + MatchDelete() + + if help_winid != 0 + help_winid->popup_close() + help_winid = 0 + endif + + if choice == -1 + fuzzy_entries = null_list + return + endif + + var lnum: number = GetTocEntries() + ->get(choice - 1, {}) + ->get('lnum') + + fuzzy_entries = null_list + + if lnum == 0 + return + endif + + cursor(lnum, 1) + normal! zvzt +enddef + +def ToggleHelp(menu_winid: number) #{{{2 + if help_winid == 0 + var height: number = [HELP_TEXT->len(), winheight(0) * 2 / 3]->min() + var longest_line: number = HELP_TEXT + ->copy() + ->map((_, line: string) => line->strcharlen()) + ->max() + var width: number = [longest_line, winwidth(0) * 2 / 3]->min() + var pos: dict = popup_getpos(menu_winid) + var [line: number, col: number] = [pos.line, pos.col] + --col + var zindex: number = popup_getoptions(menu_winid).zindex + ++zindex + help_winid = HELP_TEXT->popup_create({ + line: line, + col: col, + pos: 'topright', + minheight: height, + maxheight: height, + minwidth: width, + maxwidth: width, + border: [], + borderchars: ['─', '│', '─', '│', '┌', '┐', '┘', '└'], + highlight: &buftype == 'terminal' ? 'Terminal' : 'Normal', + scrollbar: false, + zindex: zindex, + }) + + setwinvar(help_winid, '&cursorline', true) + setwinvar(help_winid, '&linebreak', true) + matchadd('Special', '^<\S\+\|^\S\{,2} \@=', 0, -1, {window: help_winid}) + matchadd('Number', '\d\+', 0, -1, {window: help_winid}) + for lnum: number in HELP_TEXT->len()->range() + if HELP_TEXT[lnum] =~ '^─\+$' + matchaddpos('Title', [lnum], 0, -1, {window: help_winid}) + endif + endfor + + else + if IsVisible(help_winid) + popup_hide(help_winid) + else + popup_show(help_winid) + endif + endif +enddef + +def Win_execute(winid: number, cmd: any) #{{{2 +# wrapper around `win_execute()` to enforce a redraw, which might be necessary +# whenever we change the cursor position + win_execute(winid, cmd) + redraw +enddef + +def TearDown() #{{{2 + autocmd_delete([{group: AUGROUP}]) + cunmap + cunmap + cunmap + cunmap +enddef +#}}}1 +# Util {{{1 +def GetType(): string #{{{2 + return &buftype == 'terminal' ? 'terminal' : &filetype +enddef + +def GetTocEntries(): list> #{{{2 + return fuzzy_entries ?? b:toc.entries + ->copy() + ->filter((_, entry: dict): bool => entry.lvl <= b:toc.curlvl) +enddef + +def GetBufLnum(winid: number): number #{{{2 + var toc_lnum: number = line('.', winid) + return GetTocEntries() + ->get(toc_lnum - 1, {}) + ->get('lnum') +enddef + +def IsVisible(win: number): bool #{{{2 + return win->popup_getpos()->get('visible') +enddef + +def IsSpecialHelpLine(line: string): bool #{{{2 + return line =~ '^[<>]\=\s*$' + || line =~ '^\s*\*' + || line =~ HELP_RULER + || line =~ HELP_HEADLINE +enddef + +def Complete(..._): string #{{{2 + return b:toc.entries + ->copy() + ->map((_, entry: dict) => entry.text->trim(' ~')->substitute('*', '', 'g')) + ->filter((_, text: string): bool => text =~ '^[-a-zA-Z0-9_() ]\+$') + ->sort() + ->uniq() + ->join("\n") +enddef + diff --git a/runtime/pack/dist/opt/helptoc/plugin/helptoc.vim b/runtime/pack/dist/opt/helptoc/plugin/helptoc.vim new file mode 100644 index 0000000000..4fb3bc393d --- /dev/null +++ b/runtime/pack/dist/opt/helptoc/plugin/helptoc.vim @@ -0,0 +1,5 @@ +vim9script noclear + +import autoload '../autoload/helptoc.vim' + +command -bar HelpToc helptoc.Open() From 0b8176dff2dada4be1c8d3ca5e1dd1a7a536b4ca Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sat, 2 Nov 2024 18:20:30 +0100 Subject: [PATCH 012/106] Filelist: include helptoc package Signed-off-by: Christian Brabandt --- Filelist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Filelist b/Filelist index 25e3362e27..7d2074a04c 100644 --- a/Filelist +++ b/Filelist @@ -784,6 +784,8 @@ RT_ALL = \ runtime/pack/dist/opt/editorconfig/doc/editorconfig.txt \ runtime/pack/dist/opt/editorconfig/ftdetect/editorconfig.vim \ runtime/pack/dist/opt/editorconfig/plugin/editorconfig.vim \ + runtime/pack/dist/opt/helptoc/autoload/helptoc.vim \ + runtime/pack/dist/opt/helptoc/plugin/helptoc.vim \ runtime/pack/dist/opt/justify/plugin/justify.vim \ runtime/pack/dist/opt/matchit/plugin/matchit.vim \ runtime/pack/dist/opt/matchit/doc/matchit.txt \ From a13f3a4f5de9c150f70298850e34747838904995 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sat, 2 Nov 2024 18:40:10 +0100 Subject: [PATCH 013/106] patch 9.1.0831: 'findexpr' can't be used as lambad or Funcref Problem: 'findexpr' can't be used for lambads (Justin Keyes) Solution: Replace the findexpr option with the findfunc option (Yegappan Lakshmanan) related: #15905 closes: #15976 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- runtime/doc/eval.txt | 9 +- runtime/doc/options.txt | 55 ++-- runtime/doc/quickref.txt | 4 +- runtime/doc/tags | 6 +- runtime/doc/version9.txt | 2 +- src/buffer.c | 3 +- src/cmdexpand.c | 12 +- src/errors.h | 4 +- src/evalbuffer.c | 2 + src/evalvars.c | 4 +- src/ex_docmd.c | 149 ++++++--- src/gc.c | 3 + src/option.c | 40 ++- src/option.h | 4 +- src/optiondefs.h | 9 +- src/optionstr.c | 9 +- src/proto/ex_docmd.pro | 5 +- src/proto/option.pro | 2 +- src/structs.h | 5 +- src/testdir/test_findfile.vim | 497 ++++++++++++++++++++++++------- src/testdir/test_modeline.vim | 2 +- src/testdir/test_options.vim | 2 +- src/testdir/test_vim9_import.vim | 48 ++- src/version.c | 2 + src/vim.h | 5 +- 25 files changed, 628 insertions(+), 255 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 027cf08c5b..6b26475042 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 9.1. Last change: 2024 Oct 28 +*eval.txt* For Vim version 9.1. Last change: 2024 Nov 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2027,10 +2027,6 @@ v:cmdbang Set like v:cmdarg for a file read/write command. When a "!" can only be used in autocommands. For user commands || can be used. - *v:cmdcomplete* *cmdcomplete-variable* -v:cmdcomplete When evaluating 'findexpr': if 'findexpr' is used for cmdline - completion the value is |v:true|, otherwise it is |v:false|. - *v:collate* *collate-variable* v:collate The current locale setting for collation order of the runtime environment. This allows Vim scripts to be aware of the @@ -2228,8 +2224,7 @@ v:fcs_choice What should happen after a |FileChangedShell| event was *v:fname* *fname-variable* v:fname When evaluating 'includeexpr': the file name that was - detected. When evaluating 'findexpr': the argument passed to - the |:find| command. Empty otherwise. + detected. Empty otherwise. *v:fname_in* *fname_in-variable* v:fname_in The name of the input file. Valid while evaluating: diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index e221fe3e29..7a554dbb28 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.1. Last change: 2024 Oct 28 +*options.txt* For Vim version 9.1. Last change: 2024 Nov 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -439,10 +439,11 @@ Note: In the future more global options can be made |global-local|. Using ":setlocal" on a global option might work differently then. *option-value-function* -Some options ('completefunc', 'imactivatefunc', 'imstatusfunc', 'omnifunc', -'operatorfunc', 'quickfixtextfunc', 'tagfunc' and 'thesaurusfunc') are set to -a function name or a function reference or a lambda function. When using a -lambda it will be converted to the name, e.g. "123". Examples: +Some options ('completefunc', 'findfunc', 'imactivatefunc', 'imstatusfunc', +'omnifunc', 'operatorfunc', 'quickfixtextfunc', 'tagfunc' and 'thesaurusfunc') +are set to a function name or a function reference or a lambda function. When +using a lambda it will be converted to the name, e.g. "123". +Examples: > set opfunc=MyOpFunc set opfunc=function('MyOpFunc') @@ -3552,36 +3553,36 @@ A jump table for the options with a short description can be found at |Q_op|. eob EndOfBuffer |hl-EndOfBuffer| lastline NonText |hl-NonText| - *'findexpr'* *'fexpr'* *E1514* -'findexpr' 'fexpr' string (default "") + *'findfunc'* *'ffu'* *E1514* +'findfunc' 'ffu' string (default empty) global or local to buffer |global-local| {not available when compiled without the |+eval| feature} - Expression that is evaluated to obtain the filename(s) for the |:find| + Function that is called to obtain the filename(s) for the |:find| command. When this option is empty, the internal |file-searching| mechanism is used. - While evaluating the expression, the |v:fname| variable is set to the - argument of the |:find| command. + The value can be the name of a function, a |lambda| or a |Funcref|. + See |option-value-function| for more information. - The expression is evaluated only once per |:find| command invocation. - The expression can process all the directories specified in 'path'. + The function is called with two arguments. The first argument is a + |String| and is the |:find| command argument. The second argument is + a |Boolean| and is set to |v:true| when the function is called to get + a List of command-line completion matches for the |:find| command. + The function should return a List of strings. - The expression may be evaluated for command-line completion as well, - in which case the |v:cmdcomplete| variable will be set to |v:true|, - otherwise it will be set to |v:false|. + The function is called only once per |:find| command invocation. + The function can process all the directories specified in 'path'. - If a match is found, the expression should return a |List| containing - one or more file names. If a match is not found, the expression + If a match is found, the function should return a |List| containing + one or more file names. If a match is not found, the function should return an empty List. - If any errors are encountered during the expression evaluation, an + If any errors are encountered during the function invocation, an empty List is used as the return value. - Using a function call without arguments is faster |expr-option-function| - It is not allowed to change text or jump to another window while - evaluating 'findexpr' |textlock|. + executing the 'findfunc' |textlock|. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. @@ -3589,18 +3590,18 @@ A jump table for the options with a short description can be found at |Q_op|. Examples: > " Use glob() - func FindExprGlob() - let pat = v:cmdcomplete ? $'{v:fname}*' : v:fname + func FindFuncGlob(cmdarg, cmdcomplete) + let pat = a:cmdcomplete ? $'{a:cmdarg}*' : a:cmdarg return glob(pat, v:false, v:true) endfunc - set findexpr=FindExprGlob() + set findfunc=FindFuncGlob " Use the 'git ls-files' output - func FindGitFiles() + func FindGitFiles(cmdarg, cmdcomplete) let fnames = systemlist('git ls-files') - return fnames->filter('v:val =~? v:fname') + return fnames->filter('v:val =~? a:cmdarg') endfunc - set findexpr=FindGitFiles() + set findfunc=FindGitFiles < *'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'* 'fixendofline' 'fixeol' boolean (default on) diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 0f7453a9e5..a43d28f1e3 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -1,4 +1,4 @@ -*quickref.txt* For Vim version 9.1. Last change: 2024 Oct 22 +*quickref.txt* For Vim version 9.1. Last change: 2024 Nov 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -707,7 +707,7 @@ Short explanation of each option: *option-list* 'fileignorecase' 'fic' ignore case when using file names 'filetype' 'ft' type of file, used for autocommands 'fillchars' 'fcs' characters to use for displaying special items -'findexpr' 'fexpr' expression to evaluate for |:find| +'findfunc' 'ffu' function to be called for the |:find| command 'fixendofline' 'fixeol' make sure last line in file has 'fkmap' 'fk' obsolete option for Farsi 'foldclose' 'fcl' close a fold when the cursor leaves it diff --git a/runtime/doc/tags b/runtime/doc/tags index 1ae1ff61e9..79d9dafb94 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -267,9 +267,9 @@ $quote eval.txt /*$quote* 'fenc' options.txt /*'fenc'* 'fencs' options.txt /*'fencs'* 'fex' options.txt /*'fex'* -'fexpr' options.txt /*'fexpr'* 'ff' options.txt /*'ff'* 'ffs' options.txt /*'ffs'* +'ffu' options.txt /*'ffu'* 'fic' options.txt /*'fic'* 'fileencoding' options.txt /*'fileencoding'* 'fileencodings' options.txt /*'fileencodings'* @@ -278,7 +278,7 @@ $quote eval.txt /*$quote* 'fileignorecase' options.txt /*'fileignorecase'* 'filetype' options.txt /*'filetype'* 'fillchars' options.txt /*'fillchars'* -'findexpr' options.txt /*'findexpr'* +'findfunc' options.txt /*'findfunc'* 'fixendofline' options.txt /*'fixendofline'* 'fixeol' options.txt /*'fixeol'* 'fk' options.txt /*'fk'* @@ -6510,7 +6510,6 @@ close_cb channel.txt /*close_cb* closure eval.txt /*closure* cmdarg-variable eval.txt /*cmdarg-variable* cmdbang-variable eval.txt /*cmdbang-variable* -cmdcomplete-variable eval.txt /*cmdcomplete-variable* cmdline-arguments vi_diff.txt /*cmdline-arguments* cmdline-changed version5.txt /*cmdline-changed* cmdline-completion cmdline.txt /*cmdline-completion* @@ -10942,7 +10941,6 @@ v:charconvert_from eval.txt /*v:charconvert_from* v:charconvert_to eval.txt /*v:charconvert_to* v:cmdarg eval.txt /*v:cmdarg* v:cmdbang eval.txt /*v:cmdbang* -v:cmdcomplete eval.txt /*v:cmdcomplete* v:collate eval.txt /*v:collate* v:colornames eval.txt /*v:colornames* v:completed_item eval.txt /*v:completed_item* diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 66f98e10e6..5f9250348b 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -41652,7 +41652,7 @@ Options: ~ 'completeitemalign' Order of |complete-items| in Insert mode completion popup -'findexpr' Vim expression to obtain the results for a |:find| +'findfunc' Vim function to obtain the results for a |:find| command 'winfixbuf' Keep buffer focused in a window 'tabclose' Which tab page to focus after closing a tab page diff --git a/src/buffer.c b/src/buffer.c index f1e133095e..3b05f25d7f 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2412,7 +2412,6 @@ free_buf_options( clear_string_option(&buf->b_p_fp); #if defined(FEAT_EVAL) clear_string_option(&buf->b_p_fex); - clear_string_option(&buf->b_p_fexpr); #endif #ifdef FEAT_CRYPT # ifdef FEAT_SODIUM @@ -2485,6 +2484,8 @@ free_buf_options( #ifdef FEAT_EVAL clear_string_option(&buf->b_p_tfu); free_callback(&buf->b_tfu_cb); + clear_string_option(&buf->b_p_ffu); + free_callback(&buf->b_ffu_cb); #endif clear_string_option(&buf->b_p_dict); clear_string_option(&buf->b_p_tsr); diff --git a/src/cmdexpand.c b/src/cmdexpand.c index 3862d69eda..7e5311481b 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -50,7 +50,7 @@ cmdline_fuzzy_completion_supported(expand_T *xp) && xp->xp_context != EXPAND_FILES && xp->xp_context != EXPAND_FILES_IN_PATH && xp->xp_context != EXPAND_FILETYPE - && xp->xp_context != EXPAND_FINDEXPR + && xp->xp_context != EXPAND_FINDFUNC && xp->xp_context != EXPAND_HELP && xp->xp_context != EXPAND_KEYMAP && xp->xp_context != EXPAND_OLD_SETTING @@ -1419,7 +1419,7 @@ addstar( // For help tags the translation is done in find_help_tags(). // For a tag pattern starting with "/" no translation is needed. - if (context == EXPAND_FINDEXPR + if (context == EXPAND_FINDFUNC || context == EXPAND_HELP || context == EXPAND_COLORS || context == EXPAND_COMPILER @@ -2140,7 +2140,7 @@ set_context_by_cmdname( case CMD_sfind: case CMD_tabfind: if (xp->xp_context == EXPAND_FILES) - xp->xp_context = *get_findexpr() != NUL ? EXPAND_FINDEXPR + xp->xp_context = *get_findfunc() != NUL ? EXPAND_FINDFUNC : EXPAND_FILES_IN_PATH; break; case CMD_cd: @@ -2853,10 +2853,10 @@ expand_files_and_dirs( } } - if (xp->xp_context == EXPAND_FINDEXPR) + if (xp->xp_context == EXPAND_FINDFUNC) { #ifdef FEAT_EVAL - ret = expand_findexpr(pat, matches, numMatches); + ret = expand_findfunc(pat, matches, numMatches); #endif } else @@ -3122,7 +3122,7 @@ ExpandFromContext( if (xp->xp_context == EXPAND_FILES || xp->xp_context == EXPAND_DIRECTORIES || xp->xp_context == EXPAND_FILES_IN_PATH - || xp->xp_context == EXPAND_FINDEXPR + || xp->xp_context == EXPAND_FINDFUNC || xp->xp_context == EXPAND_DIRS_IN_CDPATH) return expand_files_and_dirs(xp, pat, matches, numMatches, flags, options); diff --git a/src/errors.h b/src/errors.h index 6c172e09c0..1e59597d96 100644 --- a/src/errors.h +++ b/src/errors.h @@ -3652,5 +3652,5 @@ EXTERN char e_wrong_character_width_for_field_str[] INIT(= N_("E1512: Wrong character width for field \"%s\"")); EXTERN char e_winfixbuf_cannot_go_to_buffer[] INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled")); -EXTERN char e_invalid_return_type_from_findexpr[] - INIT(= N_("E1514: 'findexpr' did not return a List type")); +EXTERN char e_invalid_return_type_from_findfunc[] + INIT(= N_("E1514: 'findfunc' did not return a List type")); diff --git a/src/evalbuffer.c b/src/evalbuffer.c index 6ec734d370..cefd6428f6 100644 --- a/src/evalbuffer.c +++ b/src/evalbuffer.c @@ -45,6 +45,8 @@ set_ref_in_buffers(int copyID) #endif if (!abort) abort = abort || set_ref_in_callback(&bp->b_tfu_cb, copyID); + if (!abort) + abort = abort || set_ref_in_callback(&bp->b_ffu_cb, copyID); if (abort) break; } diff --git a/src/evalvars.c b/src/evalvars.c index 9f03ada09a..038d7ed5a1 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -160,8 +160,7 @@ static struct vimvar {VV_NAME("python3_version", VAR_NUMBER), NULL, VV_RO}, {VV_NAME("t_typealias", VAR_NUMBER), NULL, VV_RO}, {VV_NAME("t_enum", VAR_NUMBER), NULL, VV_RO}, - {VV_NAME("t_enumvalue", VAR_NUMBER), NULL, VV_RO}, - {VV_NAME("cmdcomplete", VAR_BOOL), NULL, VV_RO}, + {VV_NAME("t_enumvalue", VAR_NUMBER), NULL, VV_RO} }; // shorthand @@ -235,7 +234,6 @@ evalvars_init(void) set_vim_var_nr(VV_SEARCHFORWARD, 1L); set_vim_var_nr(VV_HLSEARCH, 1L); set_vim_var_nr(VV_EXITING, VVAL_NULL); - set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE); set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED)); set_vim_var_list(VV_ERRORS, list_alloc()); set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED)); diff --git a/src/ex_docmd.c b/src/ex_docmd.c index d60e34473c..380bd236fd 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -6924,58 +6924,71 @@ ex_wrongmodifier(exarg_T *eap) } #if defined(FEAT_EVAL) || defined(PROTO) -/* - * Evaluate the 'findexpr' expression and return the result. When evaluating - * the expression, v:fname is set to the ":find" command argument. - */ + +// callback function for 'findfunc' +static callback_T ffu_cb; + + static callback_T * +get_findfunc_callback(void) +{ + return *curbuf->b_p_ffu != NUL ? &curbuf->b_ffu_cb : &ffu_cb; +} + static list_T * -eval_findexpr(char_u *pat, int cmdcomplete) +call_findfunc(char_u *pat, int cmdcomplete) { + typval_T args[3]; + callback_T *cb; + typval_T rettv; + int retval; sctx_T saved_sctx = current_sctx; - char_u *findexpr; - char_u *arg; - typval_T tv; - list_T *retlist = NULL; + sctx_T *ctx; + + // Call 'findfunc' to obtain the list of file names. + args[0].v_type = VAR_STRING; + args[0].vval.v_string = pat; + args[1].v_type = VAR_BOOL; + args[1].vval.v_number = cmdcomplete; + args[2].v_type = VAR_UNKNOWN; + + // Lock the text to prevent weird things from happening. Also disallow + // switching to another window, it should not be needed and may end up in + // Insert mode in another buffer. + ++textlock; - findexpr = get_findexpr(); + ctx = get_option_sctx("findfunc"); + if (ctx != NULL) + current_sctx = *ctx; - set_vim_var_string(VV_FNAME, pat, -1); - set_vim_var_nr(VV_CMDCOMPLETE, cmdcomplete ? VVAL_TRUE : VVAL_FALSE); - current_sctx = curbuf->b_p_script_ctx[BV_FEXPR]; + cb = get_findfunc_callback(); + retval = call_callback(cb, -1, &rettv, 2, args); - arg = skipwhite(findexpr); + current_sctx = saved_sctx; - ++textlock; + --textlock; - // Evaluate the expression. If the expression is "FuncName()" call the - // function directly. - if (eval0_simple_funccal(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) - retlist = NULL; - else + list_T *retlist = NULL; + + if (retval == OK) { - if (tv.v_type == VAR_LIST) - retlist = list_copy(tv.vval.v_list, TRUE, TRUE, get_copyID()); + if (rettv.v_type == VAR_LIST) + retlist = list_copy(rettv.vval.v_list, FALSE, FALSE, get_copyID()); else - emsg(_(e_invalid_return_type_from_findexpr)); - clear_tv(&tv); - } - --textlock; - clear_evalarg(&EVALARG_EVALUATE, NULL); + emsg(_(e_invalid_return_type_from_findfunc)); - set_vim_var_string(VV_FNAME, NULL, 0); - set_vim_var_nr(VV_CMDCOMPLETE, VVAL_FALSE); - current_sctx = saved_sctx; + clear_tv(&rettv); + } return retlist; } /* - * Find file names matching "pat" using 'findexpr' and return it in "files". + * Find file names matching "pat" using 'findfunc' and return it in "files". * Used for expanding the :find, :sfind and :tabfind command argument. * Returns OK on success and FAIL otherwise. */ int -expand_findexpr(char_u *pat, char_u ***files, int *numMatches) +expand_findfunc(char_u *pat, char_u ***files, int *numMatches) { list_T *l; int len; @@ -6983,7 +6996,7 @@ expand_findexpr(char_u *pat, char_u ***files, int *numMatches) *numMatches = 0; *files = NULL; - l = eval_findexpr(pat, TRUE); + l = call_findfunc(pat, VVAL_TRUE); if (l == NULL) return FAIL; @@ -7015,11 +7028,11 @@ expand_findexpr(char_u *pat, char_u ***files, int *numMatches) } /* - * Use 'findexpr' to find file 'findarg'. The 'count' argument is used to find + * Use 'findfunc' to find file 'findarg'. The 'count' argument is used to find * the n'th matching file. */ static char_u * -findexpr_find_file(char_u *findarg, int findarg_len, int count) +findfunc_find_file(char_u *findarg, int findarg_len, int count) { list_T *fname_list; char_u *ret_fname = NULL; @@ -7029,7 +7042,7 @@ findexpr_find_file(char_u *findarg, int findarg_len, int count) cc = findarg[findarg_len]; findarg[findarg_len] = NUL; - fname_list = eval_findexpr(findarg, FALSE); + fname_list = call_findfunc(findarg, VVAL_FALSE); fname_count = list_len(fname_list); if (fname_count == 0) @@ -7053,6 +7066,62 @@ findexpr_find_file(char_u *findarg, int findarg_len, int count) return ret_fname; } + +/* + * Process the 'findfunc' option value. + * Returns NULL on success and an error message on failure. + */ + char * +did_set_findfunc(optset_T *args UNUSED) +{ + int retval; + + if (*curbuf->b_p_ffu != NUL) + { + // buffer-local option set + retval = option_set_callback_func(curbuf->b_p_ffu, &curbuf->b_ffu_cb); + } + else + { + // global option set + retval = option_set_callback_func(p_ffu, &ffu_cb); + } + + if (retval == FAIL) + return e_invalid_argument; + + // If the option value starts with or s:, then replace that with + // the script identifier. + char_u **varp = (char_u **)args->os_varp; + char_u *name = get_scriptlocal_funcname(*varp); + if (name != NULL) + { + free_string_option(*varp); + *varp = name; + } + + return NULL; +} + +# if defined(EXITFREE) || defined(PROTO) + void +free_findfunc_option(void) +{ + free_callback(&ffu_cb); +} +# endif + +/* + * Mark the global 'findfunc' callback with "copyID" so that it is not + * garbage collected. + */ + int +set_ref_in_findfunc(int copyID UNUSED) +{ + int abort = FALSE; + abort = set_ref_in_callback(&ffu_cb, copyID); + return abort; +} #endif /* @@ -7105,10 +7174,10 @@ ex_splitview(exarg_T *eap) char_u *file_to_find = NULL; char *search_ctx = NULL; - if (*get_findexpr() != NUL) + if (*get_findfunc() != NUL) { #ifdef FEAT_EVAL - fname = findexpr_find_file(eap->arg, (int)STRLEN(eap->arg), + fname = findfunc_find_file(eap->arg, (int)STRLEN(eap->arg), eap->addr_count > 0 ? eap->line2 : 1); #endif } @@ -7389,10 +7458,10 @@ ex_find(exarg_T *eap) char_u *file_to_find = NULL; char *search_ctx = NULL; - if (*get_findexpr() != NUL) + if (*get_findfunc() != NUL) { #ifdef FEAT_EVAL - fname = findexpr_find_file(eap->arg, (int)STRLEN(eap->arg), + fname = findfunc_find_file(eap->arg, (int)STRLEN(eap->arg), eap->addr_count > 0 ? eap->line2 : 1); #endif } diff --git a/src/gc.c b/src/gc.c index 987ca27e76..54c7444804 100644 --- a/src/gc.c +++ b/src/gc.c @@ -183,6 +183,9 @@ garbage_collect(int testing) // 'imactivatefunc' and 'imstatusfunc' callbacks abort = abort || set_ref_in_im_funcs(copyID); + // 'findfunc' callback + abort = abort || set_ref_in_findfunc(copyID); + #ifdef FEAT_LUA abort = abort || set_ref_in_lua(copyID); #endif diff --git a/src/option.c b/src/option.c index f408fb9dfb..dcb5752e18 100644 --- a/src/option.c +++ b/src/option.c @@ -1014,6 +1014,9 @@ free_all_options(void) } free_operatorfunc_option(); free_tagfunc_option(); +# if defined(FEAT_EVAL) + free_findfunc_option(); +# endif } #endif @@ -6372,8 +6375,8 @@ unset_global_local_option(char_u *name, void *from) clear_string_option(&buf->b_p_fp); break; # ifdef FEAT_EVAL - case PV_FEXPR: - clear_string_option(&buf->b_p_fexpr); + case PV_FFU: + clear_string_option(&buf->b_p_ffu); break; # endif # ifdef FEAT_QUICKFIX @@ -6455,7 +6458,7 @@ get_varp_scope(struct vimoption *p, int scope) { case PV_FP: return (char_u *)&(curbuf->b_p_fp); #ifdef FEAT_EVAL - case PV_FEXPR: return (char_u *)&(curbuf->b_p_fexpr); + case PV_FFU: return (char_u *)&(curbuf->b_p_ffu); #endif #ifdef FEAT_QUICKFIX case PV_EFM: return (char_u *)&(curbuf->b_p_efm); @@ -6568,8 +6571,8 @@ get_varp(struct vimoption *p) case PV_FP: return *curbuf->b_p_fp != NUL ? (char_u *)&(curbuf->b_p_fp) : p->var; #ifdef FEAT_EVAL - case PV_FEXPR: return *curbuf->b_p_fexpr != NUL - ? (char_u *)&curbuf->b_p_fexpr : p->var; + case PV_FFU: return *curbuf->b_p_ffu != NUL + ? (char_u *)&(curbuf->b_p_ffu) : p->var; #endif #ifdef FEAT_QUICKFIX case PV_EFM: return *curbuf->b_p_efm != NUL @@ -6818,15 +6821,15 @@ get_equalprg(void) } /* - * Get the value of 'findexpr', either the buffer-local one or the global one. + * Get the value of 'findfunc', either the buffer-local one or the global one. */ char_u * -get_findexpr(void) +get_findfunc(void) { #ifdef FEAT_EVAL - if (*curbuf->b_p_fexpr == NUL) - return p_fexpr; - return curbuf->b_p_fexpr; + if (*curbuf->b_p_ffu == NUL) + return p_ffu; + return curbuf->b_p_ffu; #else return (char_u *)""; #endif @@ -7361,8 +7364,7 @@ buf_copy_options(buf_T *buf, int flags) #endif buf->b_p_ep = empty_option; #if defined(FEAT_EVAL) - buf->b_p_fexpr = vim_strsave(p_fexpr); - COPY_OPT_SCTX(buf, BV_FEXPR); + buf->b_p_ffu = empty_option; #endif buf->b_p_kp = empty_option; buf->b_p_path = empty_option; @@ -8749,6 +8751,7 @@ option_set_callback_func(char_u *optval UNUSED, callback_T *optcb UNUSED) #ifdef FEAT_EVAL typval_T *tv; callback_T cb; + int funcname = FALSE; if (optval == NULL || *optval == NUL) { @@ -8762,8 +8765,11 @@ option_set_callback_func(char_u *optval UNUSED, callback_T *optcb UNUSED) // Lambda expression or a funcref tv = eval_expr(optval, NULL); else + { // treat everything else as a function name string tv = alloc_string_tv(vim_strsave(optval)); + funcname = TRUE; + } if (tv == NULL) return FAIL; @@ -8780,6 +8786,16 @@ option_set_callback_func(char_u *optval UNUSED, callback_T *optcb UNUSED) vim_free(cb.cb_name); free_tv(tv); + if (in_vim9script() && funcname && (vim_strchr(optval, '.') != NULL)) + { + // When a Vim9 imported function name is used, it is expanded by the + // call to get_callback() above to _funcname. Revert the name to + // back to "import.funcname". + if (optcb->cb_free_name) + vim_free(optcb->cb_name); + optcb->cb_name = vim_strsave(optval); + optcb->cb_free_name = TRUE; + } // when using Vim9 style "import.funcname" it needs to be expanded to // "import#funcname". expand_autload_callback(optcb); diff --git a/src/option.h b/src/option.h index 641514d219..d5f72a1ccd 100644 --- a/src/option.h +++ b/src/option.h @@ -597,7 +597,7 @@ EXTERN int p_fic; // 'fileignorecase' EXTERN char_u *p_ft; // 'filetype' EXTERN char_u *p_fcs; // 'fillchar' #ifdef FEAT_EVAL -EXTERN char_u *p_fexpr; // 'findexpr' +EXTERN char_u *p_ffu; // 'findfunc' #endif EXTERN int p_fixeol; // 'fixendofline' #ifdef FEAT_FOLDING @@ -1171,11 +1171,11 @@ enum , BV_EP , BV_ET , BV_FENC - , BV_FEXPR , BV_FP #ifdef FEAT_EVAL , BV_BEXPR , BV_FEX + , BV_FFU #endif , BV_FF , BV_FLP diff --git a/src/optiondefs.h b/src/optiondefs.h index 96c30e283d..97fc4d4a69 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -54,6 +54,7 @@ #define PV_CPT OPT_BUF(BV_CPT) #define PV_DICT OPT_BOTH(OPT_BUF(BV_DICT)) #define PV_TSR OPT_BOTH(OPT_BUF(BV_TSR)) +#define PV_FFU OPT_BOTH(OPT_BUF(BV_FFU)) #define PV_CSL OPT_BUF(BV_CSL) #ifdef FEAT_COMPL_FUNC # define PV_CFU OPT_BUF(BV_CFU) @@ -74,7 +75,6 @@ #define PV_FP OPT_BOTH(OPT_BUF(BV_FP)) #ifdef FEAT_EVAL # define PV_FEX OPT_BUF(BV_FEX) -# define PV_FEXPR OPT_BOTH(OPT_BUF(BV_FEXPR)) #endif #define PV_FF OPT_BUF(BV_FF) #define PV_FLP OPT_BUF(BV_FLP) @@ -959,9 +959,10 @@ static struct vimoption options[] = {(char_u *)"vert:|,fold:-,eob:~,lastline:@", (char_u *)0L} SCTX_INIT}, - {"findexpr", "fexpr", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_SECURE, -#if defined(FEAT_EVAL) - (char_u *)&p_fexpr, PV_FEXPR, did_set_optexpr, NULL, + {"findfunc", "ffu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC, +#ifdef FEAT_EVAL + (char_u *)&p_ffu, PV_FFU, + did_set_findfunc, NULL, {(char_u *)"", (char_u *)0L} #else (char_u *)NULL, PV_NONE, NULL, NULL, diff --git a/src/optionstr.c b/src/optionstr.c index d82b8e116d..0554c0eb24 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -313,6 +313,7 @@ check_buf_options(buf_T *buf) check_string_option(&buf->b_p_tsrfu); #endif #ifdef FEAT_EVAL + check_string_option(&buf->b_p_ffu); check_string_option(&buf->b_p_tfu); #endif #ifdef FEAT_KEYMAP @@ -324,9 +325,6 @@ check_buf_options(buf_T *buf) check_string_option(&buf->b_p_efm); #endif check_string_option(&buf->b_p_ep); -#ifdef FEAT_EVAL - check_string_option(&buf->b_p_fexpr); -#endif check_string_option(&buf->b_p_path); check_string_option(&buf->b_p_tags); check_string_option(&buf->b_p_tc); @@ -3135,9 +3133,8 @@ expand_set_nrformats(optexpand_T *args, int *numMatches, char_u ***matches) #if defined(FEAT_EVAL) || defined(PROTO) /* * One of the '*expr' options is changed: 'balloonexpr', 'diffexpr', - * 'findexpr', 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr', - * 'indentexpr', 'patchexpr', 'printexpr' and 'charconvert'. - * + * 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr', 'indentexpr', + * 'patchexpr', 'printexpr' and 'charconvert'. */ char * did_set_optexpr(optset_T *args) diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro index d3f1a4ea76..7b837c989e 100644 --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -46,7 +46,10 @@ void tabpage_close_other(tabpage_T *tp, int forceit); void ex_stop(exarg_T *eap); void handle_drop(int filec, char_u **filev, int split, void (*callback)(void *), void *cookie); void handle_any_postponed_drop(void); -int expand_findexpr(char_u *pat, char_u ***files, int *numMatches); +int expand_findfunc(char_u *pat, char_u ***files, int *numMatches); +char *did_set_findfunc(optset_T *args); +void free_findfunc_option(void); +int set_ref_in_findfunc(int copyID); void ex_splitview(exarg_T *eap); void tabpage_new(void); void do_exedit(exarg_T *eap, win_T *old_curwin); diff --git a/src/proto/option.pro b/src/proto/option.pro index fce9199188..83f32aad61 100644 --- a/src/proto/option.pro +++ b/src/proto/option.pro @@ -120,7 +120,7 @@ char_u *get_option_var(int opt_idx); char_u *get_option_fullname(int opt_idx); opt_did_set_cb_T get_option_did_set_cb(int opt_idx); char_u *get_equalprg(void); -char_u *get_findexpr(void); +char_u *get_findfunc(void); void win_copy_options(win_T *wp_from, win_T *wp_to); void after_copy_winopt(win_T *wp); void copy_winopt(winopt_T *from, winopt_T *to); diff --git a/src/structs.h b/src/structs.h index 33367f099a..47999a9538 100644 --- a/src/structs.h +++ b/src/structs.h @@ -3248,6 +3248,8 @@ struct file_buffer #ifdef FEAT_EVAL char_u *b_p_tfu; // 'tagfunc' option value callback_T b_tfu_cb; // 'tagfunc' callback + char_u *b_p_ffu; // 'findfunc' option value + callback_T b_ffu_cb; // 'findfunc' callback #endif int b_p_eof; // 'endoffile' int b_p_eol; // 'endofline' @@ -3334,9 +3336,6 @@ struct file_buffer char_u *b_p_efm; // 'errorformat' local value #endif char_u *b_p_ep; // 'equalprg' local value -#ifdef FEAT_EVAL - char_u *b_p_fexpr; // 'findexpr' local value -#endif char_u *b_p_path; // 'path' local value int b_p_ar; // 'autoread' local value char_u *b_p_tags; // 'tags' local value diff --git a/src/testdir/test_findfile.vim b/src/testdir/test_findfile.vim index 25cd9daa7b..4db5850fe6 100644 --- a/src/testdir/test_findfile.vim +++ b/src/testdir/test_findfile.vim @@ -1,6 +1,7 @@ " Test findfile() and finddir() source check.vim +import './vim9.vim' as v9 let s:files = [ 'Xfinddir1/foo', \ 'Xfinddir1/bar', @@ -283,223 +284,491 @@ func Test_find_non_existing_path() let &path = save_path endfunc -" Test for 'findexpr' -func Test_findexpr() +" Test for 'findfunc' +func Test_findfunc() CheckUnix - call assert_equal('', &findexpr) - call writefile(['aFile'], 'Xfindexpr1.c', 'D') - call writefile(['bFile'], 'Xfindexpr2.c', 'D') - call writefile(['cFile'], 'Xfindexpr3.c', 'D') + call assert_equal('', &findfunc) + call writefile(['aFile'], 'Xfindfunc1.c', 'D') + call writefile(['bFile'], 'Xfindfunc2.c', 'D') + call writefile(['cFile'], 'Xfindfunc3.c', 'D') " basic tests - func FindExpr1() - let fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c'] - return fnames->copy()->filter('v:val =~? v:fname') + func FindFuncBasic(pat, cmdcomplete) + let fnames = ['Xfindfunc1.c', 'Xfindfunc2.c', 'Xfindfunc3.c'] + return fnames->copy()->filter('v:val =~? a:pat') endfunc - set findexpr=FindExpr1() - find Xfindexpr3 - call assert_match('Xfindexpr3.c', @%) + set findfunc=FindFuncBasic + find Xfindfunc3 + call assert_match('Xfindfunc3.c', @%) bw! 2find Xfind - call assert_match('Xfindexpr2.c', @%) + call assert_match('Xfindfunc2.c', @%) bw! call assert_fails('4find Xfind', 'E347: No more file "Xfind" found in path') call assert_fails('find foobar', 'E345: Can''t find file "foobar" in path') - sfind Xfindexpr2.c - call assert_match('Xfindexpr2.c', @%) + sfind Xfindfunc2.c + call assert_match('Xfindfunc2.c', @%) call assert_equal(2, winnr('$')) %bw! call assert_fails('sfind foobar', 'E345: Can''t find file "foobar" in path') - tabfind Xfindexpr3.c - call assert_match('Xfindexpr3.c', @%) + tabfind Xfindfunc3.c + call assert_match('Xfindfunc3.c', @%) call assert_equal(2, tabpagenr()) %bw! call assert_fails('tabfind foobar', 'E345: Can''t find file "foobar" in path') + " Test garbage collection + call test_garbagecollect_now() + find Xfindfunc2 + call assert_match('Xfindfunc2.c', @%) + bw! + delfunc FindFuncBasic + call test_garbagecollect_now() + call assert_fails('find Xfindfunc2', 'E117: Unknown function: FindFuncBasic') + " Buffer-local option - set findexpr=['abc'] + func GlobalFindFunc(pat, cmdcomplete) + return ['global'] + endfunc + func LocalFindFunc(pat, cmdcomplete) + return ['local'] + endfunc + set findfunc=GlobalFindFunc new - setlocal findexpr=['def'] + setlocal findfunc=LocalFindFunc find xxxx - call assert_equal('def', @%) + call assert_equal('local', @%) wincmd w find xxxx - call assert_equal('abc', @%) + call assert_equal('global', @%) aboveleft new - call assert_equal("['abc']", &findexpr) + call assert_equal("GlobalFindFunc", &findfunc) wincmd k aboveleft new - call assert_equal("['abc']", &findexpr) + call assert_equal("GlobalFindFunc", &findfunc) %bw! + delfunc GlobalFindFunc + delfunc LocalFindFunc - " Empty list - set findexpr=[] - call assert_fails('find xxxx', 'E345: Can''t find file "xxxx" in path') + " Assign an expression + set findfunc=[] + call assert_fails('find xxxx', 'E117: Unknown function: []') " Error cases - " Syntax error in the expression - set findexpr=FindExpr1{} - call assert_fails('find Xfindexpr1.c', 'E15: Invalid expression') + " Function that doesn't any argument + func FindFuncNoArg() + endfunc + set findfunc=FindFuncNoArg + call assert_fails('find Xfindfunc1.c', 'E118: Too many arguments for function: FindFuncNoArg') + delfunc FindFuncNoArg - " Find expression throws an error - func FindExpr2() + " Syntax error in the function + func FindFuncSyntaxError(pat, cmdcomplete) + return l + endfunc + set findfunc=FindFuncSyntaxError + call assert_fails('find Xfindfunc1.c', 'E121: Undefined variable: l') + delfunc FindFuncSyntaxError + + " Find function throws an error + func FindFuncWithThrow(pat, cmdcomplete) throw 'find error' endfunc - set findexpr=FindExpr2() - call assert_fails('find Xfindexpr1.c', 'find error') + set findfunc=FindFuncWithThrow + call assert_fails('find Xfindfunc1.c', 'find error') + delfunc FindFuncWithThrow - " Try using a null List as the expression - set findexpr=test_null_list() - call assert_fails('find Xfindexpr1.c', 'E345: Can''t find file "Xfindexpr1.c" in path') + " Try using a null function + call assert_fails('let &findfunc = test_null_function()', 'E129: Function name required') - " Try to create a new window from the find expression - func FindExpr3() + " Try to create a new window from the find function + func FindFuncNewWindow(pat, cmdexpand) new return ["foo"] endfunc - set findexpr=FindExpr3() - call assert_fails('find Xfindexpr1.c', 'E565: Not allowed to change text or change window') + set findfunc=FindFuncNewWindow + call assert_fails('find Xfindfunc1.c', 'E565: Not allowed to change text or change window') + delfunc FindFuncNewWindow - " Try to modify the current buffer from the find expression - func FindExpr4() + " Try to modify the current buffer from the find function + func FindFuncModifyBuf(pat, cmdexpand) call setline(1, ['abc']) return ["foo"] endfunc - set findexpr=FindExpr4() - call assert_fails('find Xfindexpr1.c', 'E565: Not allowed to change text or change window') - - " Expression returning a string - set findexpr='abc' - call assert_fails('find Xfindexpr1.c', "E1514: 'findexpr' did not return a List type") - - set findexpr& - delfunc! FindExpr1 - delfunc! FindExpr2 - delfunc! FindExpr3 - delfunc! FindExpr4 + set findfunc=FindFuncModifyBuf + call assert_fails('find Xfindfunc1.c', 'E565: Not allowed to change text or change window') + delfunc FindFuncModifyBuf + + " Return the wrong type from the function + func FindFuncWrongRet(pat, cmdexpand) + return 'foo' + endfunc + set findfunc=FindFuncWrongRet + call assert_fails('find Xfindfunc1.c', "E1514: 'findfunc' did not return a List type") + delfunc FindFuncWrongRet + + set findfunc& endfunc -" Test for using a script-local function for 'findexpr' -func Test_findexpr_scriptlocal_func() - func! s:FindExprScript() - let g:FindExprArg = v:fname +" Test for using a script-local function for 'findfunc' +func Test_findfunc_scriptlocal_func() + func! s:FindFuncScript(pat, cmdexpand) + let g:FindFuncArg = a:pat return ['xxx'] endfunc - set findexpr=s:FindExprScript() - call assert_equal(expand('') .. 'FindExprScript()', &findexpr) - call assert_equal(expand('') .. 'FindExprScript()', &g:findexpr) + set findfunc=s:FindFuncScript + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) new | only - let g:FindExprArg = '' + let g:FindFuncArg = '' find abc - call assert_equal('abc', g:FindExprArg) + call assert_equal('abc', g:FindFuncArg) bw! - set findexpr=FindExprScript() - call assert_equal(expand('') .. 'FindExprScript()', &findexpr) - call assert_equal(expand('') .. 'FindExprScript()', &g:findexpr) + set findfunc=FindFuncScript + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) new | only - let g:FindExprArg = '' + let g:FindFuncArg = '' find abc - call assert_equal('abc', g:FindExprArg) + call assert_equal('abc', g:FindFuncArg) bw! - let &findexpr = 's:FindExprScript()' - call assert_equal(expand('') .. 'FindExprScript()', &g:findexpr) + let &findfunc = 's:FindFuncScript' + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) new | only - let g:FindExprArg = '' + let g:FindFuncArg = '' find abc - call assert_equal('abc', g:FindExprArg) + call assert_equal('abc', g:FindFuncArg) bw! - let &findexpr = 'FindExprScript()' - call assert_equal(expand('') .. 'FindExprScript()', &g:findexpr) + let &findfunc = 'FindFuncScript' + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) new | only - let g:FindExprArg = '' + let g:FindFuncArg = '' find abc - call assert_equal('abc', g:FindExprArg) + call assert_equal('abc', g:FindFuncArg) bw! - set findexpr= - setglobal findexpr=s:FindExprScript() - setlocal findexpr= - call assert_equal(expand('') .. 'FindExprScript()', &findexpr) - call assert_equal(expand('') .. 'FindExprScript()', &g:findexpr) - call assert_equal('', &l:findexpr) + set findfunc= + setglobal findfunc=s:FindFuncScript + setlocal findfunc= + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + call assert_equal('', &l:findfunc) new | only - let g:FindExprArg = '' + let g:FindFuncArg = '' find abc - call assert_equal('abc', g:FindExprArg) + call assert_equal('abc', g:FindFuncArg) bw! new | only - set findexpr= - setglobal findexpr= - setlocal findexpr=s:FindExprScript() - call assert_equal(expand('') .. 'FindExprScript()', &findexpr) - call assert_equal(expand('') .. 'FindExprScript()', &l:findexpr) - call assert_equal('', &g:findexpr) - let g:FindExprArg = '' + set findfunc= + setglobal findfunc= + setlocal findfunc=s:FindFuncScript + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &l:findfunc) + call assert_equal('', &g:findfunc) + let g:FindFuncArg = '' find abc - call assert_equal('abc', g:FindExprArg) + call assert_equal('abc', g:FindFuncArg) bw! - set findexpr= - delfunc s:FindExprScript + set findfunc= + delfunc s:FindFuncScript endfunc -" Test for expanding the argument to the :find command using 'findexpr' -func Test_findexpr_expand_arg() - let s:fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c'] +" Test for expanding the argument to the :find command using 'findfunc' +func Test_findfunc_expand_arg() + let s:fnames = ['Xfindfunc1.c', 'Xfindfunc2.c', 'Xfindfunc3.c'] - " 'findexpr' that accepts a regular expression - func FindExprRegexp() - return s:fnames->copy()->filter('v:val =~? v:fname') + " 'findfunc' that accepts a regular expression + func FindFuncRegexp(pat, cmdcomplete) + return s:fnames->copy()->filter('v:val =~? a:pat') endfunc - " 'findexpr' that accepts a glob - func FindExprGlob() - let pat = glob2regpat(v:cmdcomplete ? $'*{v:fname}*' : v:fname) + " 'findfunc' that accepts a glob + func FindFuncGlob(pat_arg, cmdcomplete) + let pat = glob2regpat(a:cmdcomplete ? $'*{a:pat_arg}*' : a:pat_arg) return s:fnames->copy()->filter('v:val =~? pat') endfunc for regexp in [v:true, v:false] - let &findexpr = regexp ? 'FindExprRegexp()' : 'FindExprGlob()' + let &findfunc = regexp ? 'FindFuncRegexp' : 'FindFuncGlob' call feedkeys(":find \\\"\", "xt") - call assert_equal('"find Xfindexpr1.c', @:) + call assert_equal('"find Xfindfunc1.c', @:) call feedkeys(":find Xfind\\\\"\", "xt") - call assert_equal('"find Xfindexpr2.c', @:) + call assert_equal('"find Xfindfunc2.c', @:) call assert_equal(s:fnames, getcompletion('find ', 'cmdline')) call assert_equal(s:fnames, getcompletion('find Xfind', 'cmdline')) let pat = regexp ? 'X.*1\.c' : 'X*1.c' call feedkeys($":find {pat}\\\"\", "xt") - call assert_equal('"find Xfindexpr1.c', @:) - call assert_equal(['Xfindexpr1.c'], getcompletion($'find {pat}', 'cmdline')) + call assert_equal('"find Xfindfunc1.c', @:) + call assert_equal(['Xfindfunc1.c'], getcompletion($'find {pat}', 'cmdline')) call feedkeys(":find 3\\\"\", "xt") - call assert_equal('"find Xfindexpr3.c', @:) - call assert_equal(['Xfindexpr3.c'], getcompletion($'find 3', 'cmdline')) + call assert_equal('"find Xfindfunc3.c', @:) + call assert_equal(['Xfindfunc3.c'], getcompletion($'find 3', 'cmdline')) call feedkeys(":find Xfind\\\"\", "xt") - call assert_equal('"find Xfindexpr1.c Xfindexpr2.c Xfindexpr3.c', @:) + call assert_equal('"find Xfindfunc1.c Xfindfunc2.c Xfindfunc3.c', @:) call feedkeys(":find abc\\\"\", "xt") call assert_equal('"find abc', @:) call assert_equal([], getcompletion('find abc', 'cmdline')) endfor - set findexpr& - delfunc! FindExprRegexp - delfunc! FindExprGlob + set findfunc& + delfunc! FindFuncRegexp + delfunc! FindFuncGlob unlet s:fnames endfunc +" Test for different ways of setting the 'findfunc' option +func Test_findfunc_callback() + new + func FindFunc1(pat, cmdexpand) + let g:FindFunc1Args = [a:pat, a:cmdexpand] + return ['findfunc1'] + endfunc + + let lines =<< trim END + #" Test for using a function name + LET &findfunc = 'g:FindFunc1' + LET g:FindFunc1Args = [] + find abc1 + call assert_equal(['abc1', v:false], g:FindFunc1Args) + + #" Test for using a function() + set findfunc=function('g:FindFunc1') + LET g:FindFunc1Args = [] + find abc2 + call assert_equal(['abc2', v:false], g:FindFunc1Args) + + #" Using a funcref variable to set 'findfunc' + VAR Fn = function('g:FindFunc1') + LET &findfunc = Fn + LET g:FindFunc1Args = [] + find abc3 + call assert_equal(['abc3', v:false], g:FindFunc1Args) + + #" Using a string(funcref_variable) to set 'findfunc' + LET Fn = function('g:FindFunc1') + LET &findfunc = string(Fn) + LET g:FindFunc1Args = [] + find abc4 + call assert_equal(['abc4', v:false], g:FindFunc1Args) + + #" Test for using a funcref() + set findfunc=funcref('g:FindFunc1') + LET g:FindFunc1Args = [] + find abc5 + call assert_equal(['abc5', v:false], g:FindFunc1Args) + + #" Using a funcref variable to set 'findfunc' + LET Fn = funcref('g:FindFunc1') + LET &findfunc = Fn + LET g:FindFunc1Args = [] + find abc6 + call assert_equal(['abc6', v:false], g:FindFunc1Args) + + #" Using a string(funcref_variable) to set 'findfunc' + LET Fn = funcref('g:FindFunc1') + LET &findfunc = string(Fn) + LET g:FindFunc1Args = [] + find abc7 + call assert_equal(['abc7', v:false], g:FindFunc1Args) + + #" Test for using a lambda function using set + VAR optval = "LSTART pat, cmdexpand LMIDDLE FindFunc1(pat, cmdexpand) LEND" + LET optval = substitute(optval, ' ', '\\ ', 'g') + exe "set findfunc=" .. optval + LET g:FindFunc1Args = [] + find abc8 + call assert_equal(['abc8', v:false], g:FindFunc1Args) + + #" Test for using a lambda function using LET + LET &findfunc = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND + LET g:FindFunc1Args = [] + find abc9 + call assert_equal(['abc9', v:false], g:FindFunc1Args) + + #" Set 'findfunc' to a string(lambda expression) + LET &findfunc = 'LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND' + LET g:FindFunc1Args = [] + find abc10 + call assert_equal(['abc10', v:false], g:FindFunc1Args) + + #" Set 'findfunc' to a variable with a lambda expression + VAR Lambda = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND + LET &findfunc = Lambda + LET g:FindFunc1Args = [] + find abc11 + call assert_equal(['abc11', v:false], g:FindFunc1Args) + + #" Set 'findfunc' to a string(variable with a lambda expression) + LET Lambda = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND + LET &findfunc = string(Lambda) + LET g:FindFunc1Args = [] + find abc12 + call assert_equal(['abc12', v:false], g:FindFunc1Args) + + #" Try to use 'findfunc' after the function is deleted + func g:TmpFindFunc(pat, cmdexpand) + let g:TmpFindFunc1Args = [a:pat, a:cmdexpand] + endfunc + LET &findfunc = function('g:TmpFindFunc') + delfunc g:TmpFindFunc + call test_garbagecollect_now() + LET g:TmpFindFunc1Args = [] + call assert_fails('find abc13', 'E117:') + call assert_equal([], g:TmpFindFunc1Args) + + #" Try to use a function with three arguments for 'findfunc' + func g:TmpFindFunc2(x, y, z) + let g:TmpFindFunc2Args = [a:x, a:y, a:z] + endfunc + set findfunc=TmpFindFunc2 + LET g:TmpFindFunc2Args = [] + call assert_fails('find abc14', 'E119:') + call assert_equal([], g:TmpFindFunc2Args) + delfunc TmpFindFunc2 + + #" Try to use a function with zero arguments for 'findfunc' + func g:TmpFindFunc3() + let g:TmpFindFunc3Called = v:true + endfunc + set findfunc=TmpFindFunc3 + LET g:TmpFindFunc3Called = v:false + call assert_fails('find abc15', 'E118:') + call assert_equal(v:false, g:TmpFindFunc3Called) + delfunc TmpFindFunc3 + + #" Try to use a lambda function with three arguments for 'findfunc' + LET &findfunc = LSTART a, b, c LMIDDLE FindFunc1(a, v:false) LEND + LET g:FindFunc1Args = [] + call assert_fails('find abc16', 'E119:') + call assert_equal([], g:FindFunc1Args) + + #" Test for clearing the 'findfunc' option + set findfunc='' + set findfunc& + call assert_fails("set findfunc=function('abc')", "E700:") + call assert_fails("set findfunc=funcref('abc')", "E700:") + + #" set 'findfunc' to a non-existing function + LET &findfunc = function('g:FindFunc1') + call assert_fails("set findfunc=function('NonExistingFunc')", 'E700:') + call assert_fails("LET &findfunc = function('NonExistingFunc')", 'E700:') + LET g:FindFunc1Args = [] + find abc17 + call assert_equal(['abc17', v:false], g:FindFunc1Args) + END + call v9.CheckTransLegacySuccess(lines) + + " Test for using a script-local function name + func s:FindFunc2(pat, cmdexpand) + let g:FindFunc2Args = [a:pat, a:cmdexpand] + return ['findfunc2'] + endfunc + set findfunc=s:FindFunc2 + let g:FindFunc2Args = [] + find abc18 + call assert_equal(['abc18', v:false], g:FindFunc2Args) + + let &findfunc = 's:FindFunc2' + let g:FindFunc2Args = [] + find abc19 + call assert_equal(['abc19', v:false], g:FindFunc2Args) + delfunc s:FindFunc2 + + " Using Vim9 lambda expression in legacy context should fail + set findfunc=(pat,\ cmdexpand)\ =>\ FindFunc1(pat,\ v:false) + let g:FindFunc1Args = [] + call assert_fails('find abc20', 'E117:') + call assert_equal([], g:FindFunc1Args) + + " set 'findfunc' to a partial with dict. + func SetFindFunc() + let operator = {'execute': function('FindFuncExecute')} + let &findfunc = operator.execute + endfunc + func FindFuncExecute(pat, cmdexpand) dict + return ['findfuncexecute'] + endfunc + call SetFindFunc() + call test_garbagecollect_now() + set findfunc= + delfunc SetFindFunc + delfunc FindFuncExecute + + func FindFunc2(pat, cmdexpand) + let g:FindFunc2Args = [a:pat, a:cmdexpand] + return ['findfunc2'] + endfunc + + " Vim9 tests + let lines =<< trim END + vim9script + + def g:Vim9findFunc(pat: string, cmdexpand: bool): list + g:FindFunc1Args = [pat, cmdexpand] + return ['vim9findfunc'] + enddef + + # Test for using a def function with findfunc + set findfunc=function('g:Vim9findFunc') + g:FindFunc1Args = [] + find abc21 + assert_equal(['abc21', false], g:FindFunc1Args) + + # Test for using a global function name + &findfunc = g:FindFunc2 + g:FindFunc2Args = [] + find abc22 + assert_equal(['abc22', false], g:FindFunc2Args) + bw! + + # Test for using a script-local function name + def LocalFindFunc(pat: string, cmdexpand: bool): list + g:LocalFindFuncArgs = [pat, cmdexpand] + return ['localfindfunc'] + enddef + &findfunc = LocalFindFunc + g:LocalFindFuncArgs = [] + find abc23 + assert_equal(['abc23', false], g:LocalFindFuncArgs) + bw! + END + call v9.CheckScriptSuccess(lines) + + " setting 'findfunc' to a script local function outside of a script context + " should fail + let cleanup =<< trim END + call writefile([execute('messages')], 'Xtest.out') + qall + END + call writefile(cleanup, 'Xverify.vim', 'D') + call RunVim([], [], "-c \"set findfunc=s:abc\" -S Xverify.vim") + call assert_match('E81: Using not in a', readfile('Xtest.out')[0]) + call delete('Xtest.out') + + " cleanup + set findfunc& + delfunc FindFunc1 + delfunc FindFunc2 + unlet g:FindFunc1Args g:FindFunc2Args + %bw! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_modeline.vim b/src/testdir/test_modeline.vim index bb5bc6b515..0697fbbce9 100644 --- a/src/testdir/test_modeline.vim +++ b/src/testdir/test_modeline.vim @@ -208,7 +208,7 @@ func Test_modeline_fails_always() call s:modeline_fails('equalprg', 'equalprg=Something()', 'E520:') call s:modeline_fails('errorfile', 'errorfile=Something()', 'E520:') call s:modeline_fails('exrc', 'exrc=Something()', 'E520:') - call s:modeline_fails('findexpr', 'findexpr=Something()', 'E520:') + call s:modeline_fails('findfunc', 'findfunc=Something', 'E520:') call s:modeline_fails('formatprg', 'formatprg=Something()', 'E520:') call s:modeline_fails('fsync', 'fsync=Something()', 'E520:') call s:modeline_fails('grepprg', 'grepprg=Something()', 'E520:') diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 35b7d48dec..bd9da730b3 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -1570,7 +1570,7 @@ endfunc " Test for changing options in a sandbox func Test_opt_sandbox() - for opt in ['backupdir', 'cdpath', 'exrc', 'findexpr'] + for opt in ['backupdir', 'cdpath', 'exrc', 'findfunc'] call assert_fails('sandbox set ' .. opt .. '?', 'E48:') call assert_fails('sandbox let &' .. opt .. ' = 1', 'E48:') endfor diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim index ad0248c179..4a3e239143 100644 --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -1560,27 +1560,47 @@ def Run_Test_import_in_printexpr() set printexpr= enddef -" Test for using an imported function as 'findexpr' -func Test_import_in_findexpr() - call Run_Test_import_in_findexpr() +" Test for using an imported function as 'findfunc' +func Test_import_in_findfunc() + call Run_Test_import_in_findfunc() endfunc -def Run_Test_import_in_findexpr() +def Run_Test_import_in_findfunc() var lines =<< trim END - vim9script + vim9script - export def FindExpr(): list - var fnames = ['Xfile1.c', 'Xfile2.c', 'Xfile3.c'] - return fnames->copy()->filter('v:val =~? v:fname') - enddef + export def FindFunc(pat: string, cmdexpand: bool): list + var fnames = ['Xfile1.c', 'Xfile2.c', 'Xfile3.c'] + return fnames->filter((_, v) => v =~? pat) + enddef END - writefile(lines, 'Xfindexpr', 'D') + writefile(lines, 'Xfindfunc', 'D') + # Test using the "set" command lines =<< trim END - vim9script - import './Xfindexpr' as find + vim9script + import './Xfindfunc' as find1 + + set findfunc=find1.FindFunc + END + v9.CheckScriptSuccess(lines) + + enew! + find Xfile2 + assert_equal('Xfile2.c', @%) + bwipe! + + botright vert new + find Xfile1 + assert_equal('Xfile1.c', @%) + bw! + + # Test using the option variable + lines =<< trim END + vim9script + import './Xfindfunc' as find2 - set findexpr=find.FindExpr() + &findfunc = find2.FindFunc END v9.CheckScriptSuccess(lines) @@ -1593,7 +1613,7 @@ def Run_Test_import_in_findexpr() find Xfile1 assert_equal('Xfile1.c', @%) - set findexpr= + set findfunc= bwipe! enddef diff --git a/src/version.c b/src/version.c index 74660c6876..3e8bfbd7b9 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 */ +/**/ + 831, /**/ 830, /**/ diff --git a/src/vim.h b/src/vim.h index f4acaf92fa..2878541941 100644 --- a/src/vim.h +++ b/src/vim.h @@ -845,7 +845,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #define EXPAND_KEYMAP 58 #define EXPAND_DIRS_IN_CDPATH 59 #define EXPAND_SHELLCMDLINE 60 -#define EXPAND_FINDEXPR 61 +#define EXPAND_FINDFUNC 61 // Values for exmode_active (0 is no exmode) @@ -2189,8 +2189,7 @@ typedef int sock_T; #define VV_TYPE_TYPEALIAS 107 #define VV_TYPE_ENUM 108 #define VV_TYPE_ENUMVALUE 109 -#define VV_CMDCOMPLETE 110 -#define VV_LEN 111 // number of v: vars +#define VV_LEN 110 // number of v: vars // used for v_number in VAR_BOOL and VAR_SPECIAL #define VVAL_FALSE 0L // VAR_BOOL From b256221e8377abba3c121d612c559006a9233052 Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Sat, 2 Nov 2024 18:48:53 +0100 Subject: [PATCH 014/106] runtime(2html): Make links use color scheme colors in TOhtml The browser-default dark blue/purple colors don't fit in with most color schemes and also are unreadable if the color scheme has a dark background. closes: #10191 Signed-off-by: Max Bernstein Signed-off-by: Christian Brabandt --- runtime/syntax/2html.vim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/runtime/syntax/2html.vim b/runtime/syntax/2html.vim index f3ce8bed8d..ca40810e80 100644 --- a/runtime/syntax/2html.vim +++ b/runtime/syntax/2html.vim @@ -1,6 +1,6 @@ " Vim syntax support file " Maintainer: Ben Fritz -" Last Change: 2023 Sep 05 +" Last Change: 2024 Nov 02 " " Additional contributors: " @@ -1843,6 +1843,10 @@ if s:settings.use_css && !s:settings.no_doc " default font size for different elements call append('.', '* { font-size: 1em; }') + + " use color scheme styles for links + " browser-default blue/purple colors for links don't look like the existing theme and are unreadable on dark backgrounds + call append('.', 'a { color: inherit; }') + + " if we use any input elements for unselectable content, make sure they look " like normal text if !empty(s:settings.prevent_copy) From 6081c17890fefd9cb9a009beaace3d7f7b8d1605 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sun, 3 Nov 2024 09:06:10 +0100 Subject: [PATCH 015/106] runtime(doc): update help-toc description related: #10446 Signed-off-by: Christian Brabandt --- runtime/doc/helphelp.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index 86c4775fdd..8ade446e6e 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -1,4 +1,4 @@ -*helphelp.txt* For Vim version 9.1. Last change: 2024 Nov 02 +*helphelp.txt* For Vim version 9.1. Last change: 2024 Nov 03 VIM REFERENCE MANUAL by Bram Moolenaar @@ -278,6 +278,7 @@ The latter supports the following normal commands: > + | increase width of popup menu - | decrease width of popup menu ? | show/hide a help window + / | search for pattern | scroll down half a page | scroll up half a page @@ -288,7 +289,7 @@ The latter supports the following normal commands: > The plugin can also provide a table of contents in man pages, markdown files, and terminal buffers. In the latter, the entries will be the past executed -shell commands. To find those, the following regex is used: > +shell commands. To find those, the following pattern is used: > ^\w\+@\w\+:\f\+\$\s From 46dcd84d242db6b053cb5b777c896cede9ad9b27 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 3 Nov 2024 09:10:50 +0100 Subject: [PATCH 016/106] patch 9.1.0832: :set doesn't work for 'cot' and 'bkc' after :setlocal Problem: :set doesn't work for 'cot' and 'bkc' after :setlocal. Solution: clear the local flags when using :set (zeertzjq). closes: #15981 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- src/optionstr.c | 6 +++++ src/testdir/test_ins_complete.vim | 40 +++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 48 insertions(+) diff --git a/src/optionstr.c b/src/optionstr.c index 0554c0eb24..7c589e9173 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -1146,6 +1146,9 @@ did_set_backupcopy(optset_T *args) bkc = curbuf->b_p_bkc; flags = &curbuf->b_bkc_flags; } + else if (!(args->os_flags & OPT_GLOBAL)) + // When using :set, clear the local flags. + curbuf->b_bkc_flags = 0; if ((args->os_flags & OPT_LOCAL) && *bkc == NUL) // make the local value empty: use the global value @@ -1619,6 +1622,9 @@ did_set_completeopt(optset_T *args UNUSED) cot = curbuf->b_p_cot; flags = &curbuf->b_cot_flags; } + else if (!(args->os_flags & OPT_GLOBAL)) + // When using :set, clear the local flags. + curbuf->b_cot_flags = 0; if (check_opt_strings(cot, p_cot_values, TRUE) != OK) return e_invalid_argument; diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index df254847ee..8b478a190e 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -875,6 +875,46 @@ func Test_completeopt_buffer_local() call assert_equal('menu', &completeopt) call assert_equal('menu', &g:completeopt) + new | only + call setline(1, ['foofoo', 'foobar', 'foobaz', '']) + set completeopt& + setlocal completeopt=menu,fuzzy,noinsert + setglobal completeopt=menu,longest + call assert_equal('menu,fuzzy,noinsert', &completeopt) + call assert_equal('menu,fuzzy,noinsert', &l:completeopt) + call assert_equal('menu,longest', &g:completeopt) + call feedkeys("Gccf\\bz\", 'tnix') + call assert_equal('foobaz', getline('.')) + setlocal bufhidden=wipe + new | only! + call setline(1, ['foofoo', 'foobar', 'foobaz', '']) + call assert_equal('menu,longest', &completeopt) + call assert_equal('menu,longest', &g:completeopt) + call assert_equal('', &l:completeopt) + call feedkeys("Gccf\\\\", 'tnix') + call assert_equal('foo', getline('.')) + bwipe! + + new | only + call setline(1, ['foofoo', 'foobar', 'foobaz', '']) + set completeopt& + setlocal completeopt=menu,fuzzy,noinsert + set completeopt=menu,longest + call assert_equal('menu,longest', &completeopt) + call assert_equal('menu,longest', &g:completeopt) + call assert_equal('', &l:completeopt) + call feedkeys("Gccf\\\\", 'tnix') + call assert_equal('foo', getline('.')) + setlocal bufhidden=wipe + new | only! + call setline(1, ['foofoo', 'foobar', 'foobaz', '']) + call assert_equal('menu,longest', &completeopt) + call assert_equal('menu,longest', &g:completeopt) + call assert_equal('', &l:completeopt) + call feedkeys("Gccf\\\\", 'tnix') + call assert_equal('foo', getline('.')) + bwipe! + set completeopt& endfunc diff --git a/src/version.c b/src/version.c index 3e8bfbd7b9..e462585724 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 */ +/**/ + 832, /**/ 831, /**/ From 9fd5d9674f1e5392be9dff0ec338e25c05196fe9 Mon Sep 17 00:00:00 2001 From: Aliaksei Budavei <0x000c70@gmail.com> Date: Sun, 3 Nov 2024 09:15:35 +0100 Subject: [PATCH 017/106] patch 9.1.0833: CI: recent ASAN changes do not work for indent tests Problem: CI: recent ASAN changes do not work for indent tests Solution: Move code to runtime/indent/testdir/runtest.vim (Aliaksei Budavei) closes: #15981 Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com> Signed-off-by: Christian Brabandt --- runtime/indent/testdir/runtest.vim | 13 +++++++++++++ src/testdir/runtest.vim | 5 ----- src/version.c | 2 ++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/runtime/indent/testdir/runtest.vim b/runtime/indent/testdir/runtest.vim index dde8c5c47b..9559a810b1 100644 --- a/runtime/indent/testdir/runtest.vim +++ b/runtime/indent/testdir/runtest.vim @@ -14,6 +14,19 @@ set modeline set debug=throw set nomore +" Remember the directory where we started. +let indentDir = getcwd() +cd ../../src/testdir + +" Needed for ValgrindOrAsan(). +source shared.vim +exe 'cd ' .. fnameescape(indentDir) + +if ValgrindOrAsan() + let g:vim_indent = {"searchpair_timeout": 1024} + let g:python_indent = {"searchpair_timeout": 1024} +endif + au! SwapExists * call HandleSwapExists() func HandleSwapExists() " Ignore finding a swap file for the test input and output, the user might be diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index 9bb500e265..ded31975b8 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -247,11 +247,6 @@ func RunTheTest(test) let g:timeout_start = localtime() endif - if ValgrindOrAsan() - let g:vim_indent = {"searchpair_timeout": 1024} - let g:python_indent = {"searchpair_timeout": 1024} - endif - " Avoid stopping at the "hit enter" prompt set nomore diff --git a/src/version.c b/src/version.c index e462585724..393d2e398a 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 */ +/**/ + 833, /**/ 832, /**/ From ca6231b8a695489664aa0ca394840f2c77040928 Mon Sep 17 00:00:00 2001 From: Aliaksei Budavei <0x000c70@gmail.com> Date: Sun, 3 Nov 2024 09:19:14 +0100 Subject: [PATCH 018/106] patch 9.1.0834: tests: 2html test fails Problem: tests: 2html test fails (after b256221e8377) Solution: Adjust testdir/samples/Test_tohtml_basic.c.html (Aliaksei Budavei) closes: #15981 Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com> Signed-off-by: Christian Brabandt --- src/testdir/samples/Test_tohtml_basic.c.html | 1 + src/version.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/testdir/samples/Test_tohtml_basic.c.html b/src/testdir/samples/Test_tohtml_basic.c.html index d9467b5086..6c74e4f82d 100644 --- a/src/testdir/samples/Test_tohtml_basic.c.html +++ b/src/testdir/samples/Test_tohtml_basic.c.html @@ -13,6 +13,7 @@ pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #ffffff; } body { font-family: monospace; color: #000000; background-color: #ffffff; } * { font-size: 1em; } +a { color: inherit; } --> diff --git a/src/version.c b/src/version.c index 393d2e398a..743a9e017b 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 */ +/**/ + 834, /**/ 833, /**/ From 6eda269600b5ca952f28e808c662f67e581933d7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 3 Nov 2024 09:23:33 +0100 Subject: [PATCH 019/106] patch 9.1.0835: :setglobal doesn't work properly for 'ffu' and 'tsrfu' Problem: :setglobal doesn't work properly for 'ffu' and 'tsrfu' when the local value is set (after v9.1.0831) Solution: Check os_flags instead of buffer option variable (zeertzjq). closes: #15980 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- src/ex_docmd.c | 11 ++++++--- src/insexpand.c | 7 +++--- src/testdir/test_findfile.vim | 37 +++++++++++++++++++++++++++- src/testdir/test_ins_complete.vim | 41 +++++++++++++++++++++++++++++++ src/version.c | 2 ++ 5 files changed, 90 insertions(+), 8 deletions(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 380bd236fd..859dc8563a 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -6934,6 +6934,9 @@ get_findfunc_callback(void) return *curbuf->b_p_ffu != NUL ? &curbuf->b_ffu_cb : &ffu_cb; } +/* + * Call 'findfunc' to obtain a list of file names. + */ static list_T * call_findfunc(char_u *pat, int cmdcomplete) { @@ -6944,7 +6947,6 @@ call_findfunc(char_u *pat, int cmdcomplete) sctx_T saved_sctx = current_sctx; sctx_T *ctx; - // Call 'findfunc' to obtain the list of file names. args[0].v_type = VAR_STRING; args[0].vval.v_string = pat; args[1].v_type = VAR_BOOL; @@ -7076,15 +7078,16 @@ did_set_findfunc(optset_T *args UNUSED) { int retval; - if (*curbuf->b_p_ffu != NUL) - { + if (args->os_flags & OPT_LOCAL) // buffer-local option set retval = option_set_callback_func(curbuf->b_p_ffu, &curbuf->b_ffu_cb); - } else { // global option set retval = option_set_callback_func(p_ffu, &ffu_cb); + // when using :set, free the local callback + if (!(args->os_flags & OPT_GLOBAL)) + free_callback(&curbuf->b_ffu_cb); } if (retval == FAIL) diff --git a/src/insexpand.c b/src/insexpand.c index c22eb6dc2f..f176d75754 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -2687,16 +2687,17 @@ did_set_thesaurusfunc(optset_T *args UNUSED) { int retval; - if (*curbuf->b_p_tsrfu != NUL) - { + if (args->os_flags & OPT_LOCAL) // buffer-local option set retval = option_set_callback_func(curbuf->b_p_tsrfu, &curbuf->b_tsrfu_cb); - } else { // global option set retval = option_set_callback_func(p_tsrfu, &tsrfu_cb); + // when using :set, free the local callback + if (!(args->os_flags & OPT_GLOBAL)) + free_callback(&curbuf->b_tsrfu_cb); } return retval == FAIL ? e_invalid_argument : NULL; diff --git a/src/testdir/test_findfile.vim b/src/testdir/test_findfile.vim index 4db5850fe6..c974c40147 100644 --- a/src/testdir/test_findfile.vim +++ b/src/testdir/test_findfile.vim @@ -359,7 +359,7 @@ func Test_findfunc() " Error cases - " Function that doesn't any argument + " Function that doesn't take any arguments func FindFuncNoArg() endfunc set findfunc=FindFuncNoArg @@ -479,6 +479,41 @@ func Test_findfunc_scriptlocal_func() call assert_equal('abc', g:FindFuncArg) bw! + new | only + set findfunc= + setlocal findfunc=NoSuchFunc + setglobal findfunc=s:FindFuncScript + call assert_equal('NoSuchFunc', &findfunc) + call assert_equal('NoSuchFunc', &l:findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + new | only + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + call assert_equal('', &l:findfunc) + let g:FindFuncArg = '' + find abc + call assert_equal('abc', g:FindFuncArg) + bw! + + new | only + set findfunc= + setlocal findfunc=NoSuchFunc + set findfunc=s:FindFuncScript + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + call assert_equal('', &l:findfunc) + let g:FindFuncArg = '' + find abc + call assert_equal('abc', g:FindFuncArg) + new | only + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + call assert_equal('', &l:findfunc) + let g:FindFuncArg = '' + find abc + call assert_equal('abc', g:FindFuncArg) + bw! + set findfunc= delfunc s:FindFuncScript endfunc diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 8b478a190e..fd4c7cded5 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -2190,6 +2190,7 @@ func Test_thesaurusfunc_callback() call add(g:TsrFunc3Args, [a:findstart, a:base]) return a:findstart ? 0 : [] endfunc + set tsrfu=s:TsrFunc3 new call setline(1, 'script1') @@ -2205,6 +2206,46 @@ func Test_thesaurusfunc_callback() call feedkeys("A\\\", 'x') call assert_equal([[1, ''], [0, 'script2']], g:TsrFunc3Args) bw! + + new | only + set thesaurusfunc= + setlocal thesaurusfunc=NoSuchFunc + setglobal thesaurusfunc=s:TsrFunc3 + call assert_equal('NoSuchFunc', &thesaurusfunc) + call assert_equal('NoSuchFunc', &l:thesaurusfunc) + call assert_equal('s:TsrFunc3', &g:thesaurusfunc) + new | only + call assert_equal('s:TsrFunc3', &thesaurusfunc) + call assert_equal('s:TsrFunc3', &g:thesaurusfunc) + call assert_equal('', &l:thesaurusfunc) + call setline(1, 'script1') + let g:TsrFunc3Args = [] + call feedkeys("A\\\", 'x') + call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) + bw! + + new | only + set thesaurusfunc= + setlocal thesaurusfunc=NoSuchFunc + set thesaurusfunc=s:TsrFunc3 + call assert_equal('s:TsrFunc3', &thesaurusfunc) + call assert_equal('s:TsrFunc3', &g:thesaurusfunc) + call assert_equal('', &l:thesaurusfunc) + call setline(1, 'script1') + let g:TsrFunc3Args = [] + call feedkeys("A\\\", 'x') + call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) + setlocal bufhidden=wipe + new | only! + call assert_equal('s:TsrFunc3', &thesaurusfunc) + call assert_equal('s:TsrFunc3', &g:thesaurusfunc) + call assert_equal('', &l:thesaurusfunc) + call setline(1, 'script1') + let g:TsrFunc3Args = [] + call feedkeys("A\\\", 'x') + call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) + bw! + delfunc s:TsrFunc3 " invalid return value diff --git a/src/version.c b/src/version.c index 743a9e017b..b39cf1e92e 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 */ +/**/ + 835, /**/ 834, /**/ From a54816b884157f6b7973a188f85c708d15cbf72f Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sun, 3 Nov 2024 10:49:23 +0100 Subject: [PATCH 020/106] patch 9.1.0836: The vimtutor can be improved Problem: the vimtutor can be improved Solution: port and include the interactive vimtutor plugin from Neovim (by Felipe Morales) (Yegappan Lakshmanan) closes: #6414 Signed-off-by: Christian Brabandt Signed-off-by: Yegappan Lakshmanan --- Filelist | 4 + runtime/autoload/tutor.vim | 219 +++++ runtime/defaults.vim | 6 +- runtime/doc/Make_all.mak | 2 + runtime/doc/pi_tutor.txt | 51 + runtime/doc/tags | 5 + runtime/doc/usr_01.txt | 4 +- runtime/doc/version9.txt | 4 +- runtime/filetype.vim | 3 + runtime/ftplugin/tutor.vim | 45 + runtime/plugin/tutor.vim | 6 + runtime/syntax/tutor.vim | 77 ++ runtime/syntax/vimnormal.vim | 16 + runtime/tutor/en/vim-01-beginner.tutor | 980 ++++++++++++++++++++ runtime/tutor/en/vim-01-beginner.tutor.json | 45 + runtime/tutor/tutor.tutor | 247 +++++ runtime/tutor/tutor.tutor.json | 35 + src/Makefile | 8 +- src/version.c | 2 + 19 files changed, 1752 insertions(+), 7 deletions(-) create mode 100644 runtime/autoload/tutor.vim create mode 100644 runtime/doc/pi_tutor.txt create mode 100644 runtime/ftplugin/tutor.vim create mode 100644 runtime/plugin/tutor.vim create mode 100644 runtime/syntax/tutor.vim create mode 100644 runtime/syntax/vimnormal.vim create mode 100644 runtime/tutor/en/vim-01-beginner.tutor create mode 100644 runtime/tutor/en/vim-01-beginner.tutor.json create mode 100644 runtime/tutor/tutor.tutor create mode 100644 runtime/tutor/tutor.tutor.json diff --git a/Filelist b/Filelist index 7d2074a04c..4fbcc0a2f8 100644 --- a/Filelist +++ b/Filelist @@ -762,6 +762,10 @@ RT_ALL = \ runtime/tools/[a-z]*[a-z0-9] \ runtime/tutor/README.txt \ runtime/tutor/tutor \ + runtime/tutor/en/vim-01-beginner.tutor \ + runtime/tutor/en/vim-01-beginner.tutor.json \ + runtime/tutor/tutor.tutor \ + runtime/tutor/tutor.tutor.json \ runtime/tutor/tutor.vim \ runtime/vimrc_example.vim \ runtime/pack/dist/opt/cfilter/plugin/cfilter.vim \ diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim new file mode 100644 index 0000000000..3265fdde36 --- /dev/null +++ b/runtime/autoload/tutor.vim @@ -0,0 +1,219 @@ +" vim: fdm=marker et ts=4 sw=4 + +" Setup: {{{1 +function! tutor#SetupVim() + if !exists('g:did_load_ftplugin') || g:did_load_ftplugin != 1 + filetype plugin on + endif + if has('syntax') + if !exists('g:syntax_on') || g:syntax_on == 0 + syntax on + endif + endif +endfunction + +" Loads metadata file, if available +function! tutor#LoadMetadata() + let b:tutor_metadata = json_decode(join(readfile(expand('%').'.json'), "\n")) +endfunction + +" Mappings: {{{1 + +function! tutor#SetNormalMappings() + nnoremap :call tutor#FollowLink(0) + nnoremap <2-LeftMouse> :call tutor#MouseDoubleClick() + nnoremap >> :call tutor#InjectCommand() +endfunction + +function! tutor#MouseDoubleClick() + if foldclosed(line('.')) > -1 + normal! zo + else + if match(getline('.'), '^#\{1,} ') > -1 + silent normal! zc + else + call tutor#FollowLink(0) + endif + endif +endfunction + +function! tutor#InjectCommand() + let l:cmd = substitute(getline('.'), '^\s*', '', '') + exe l:cmd + redraw | echohl WarningMsg | echon "tutor: ran" | echohl None | echon " " | echohl Statement | echon l:cmd +endfunction + +function! tutor#FollowLink(force) + let l:stack_s = join(map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")'), '') + if l:stack_s =~# 'tutorLink' + let l:link_start = searchpairpos('\[', '', ')', 'nbcW') + let l:link_end = searchpairpos('\[', '', ')', 'ncW') + if l:link_start[0] == l:link_end[0] + let l:linkData = getline(l:link_start[0])[l:link_start[1]-1:l:link_end[1]-1] + else + return + endif + let l:target = matchstr(l:linkData, '(\@<=.*)\@=') + if a:force != 1 && match(l:target, '\*.\+\*') > -1 + call cursor(l:link_start[0], l:link_end[1]) + call search(l:target, '') + normal! ^ + elseif a:force != 1 && match(l:target, '^@tutor:') > -1 + let l:tutor = matchstr(l:target, '@tutor:\zs.*') + exe "Tutor ".l:tutor + else + exe "help ".l:target + endif + endif +endfunction + +" Folding And Info: {{{1 + +function! tutor#TutorFolds() + if getline(v:lnum) =~# '^#\{1,6}' + return ">". len(matchstr(getline(v:lnum), '^#\{1,6}')) + else + return "=" + endif +endfunction + +" Marks: {{{1 + +function! tutor#ApplyMarks() + hi! link tutorExpect Special + if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect') + let b:tutor_sign_id = 1 + for expct in keys(b:tutor_metadata['expect']) + let lnum = eval(expct) + call matchaddpos('tutorExpect', [lnum]) + call tutor#CheckLine(lnum) + endfor + endif +endfunction + +function! tutor#ApplyMarksOnChanged() + if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect') + let lnum = line('.') + if index(keys(b:tutor_metadata['expect']), string(lnum)) > -1 + call tutor#CheckLine(lnum) + endif + endif +endfunction + +function! tutor#CheckLine(line) + if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect') + let bufn = bufnr('%') + let ctext = getline(a:line) + if b:tutor_metadata['expect'][string(a:line)] == -1 || ctext ==# b:tutor_metadata['expect'][string(a:line)] + exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorok buffer=".bufn + else + exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorbad buffer=".bufn + endif + let b:tutor_sign_id+=1 + endif +endfunction + +" Tutor Cmd: {{{1 + +function! s:Locale() + if exists('v:lang') && v:lang =~ '\a\a' + let l:lang = v:lang + elseif $LC_ALL =~ '\a\a' + let l:lang = $LC_ALL + elseif $LANG =~ '\a\a' + let l:lang = $LANG + else + let l:lang = 'en_US' + endif + return split(l:lang, '_') +endfunction + +function! s:GlobPath(lp, pat) + if version >= 704 && has('patch279') + return globpath(a:lp, a:pat, 1, 1) + else + return split(globpath(a:lp, a:pat, 1), '\n') + endif +endfunction + +function! s:Sort(a, b) + let mod_a = fnamemodify(a:a, ':t') + let mod_b = fnamemodify(a:b, ':t') + if mod_a == mod_b + let retval = 0 + elseif mod_a > mod_b + if match(mod_a, '^vim-') > -1 && match(mod_b, '^vim-') == -1 + let retval = -1 + else + let retval = 1 + endif + else + if match(mod_b, '^vim-') > -1 && match(mod_a, '^vim-') == -1 + let retval = 1 + else + let retval = -1 + endif + endif + return retval +endfunction + +function! s:GlobTutorials(name) + " search for tutorials: + " 1. non-localized + let l:tutors = s:GlobPath(&rtp, 'tutor/'.a:name.'.tutor') + " 2. localized for current locale + let l:locale_tutors = s:GlobPath(&rtp, 'tutor/'.s:Locale()[0].'/'.a:name.'.tutor') + " 3. fallback to 'en' + if len(l:locale_tutors) == 0 + let l:locale_tutors = s:GlobPath(&rtp, 'tutor/en/'.a:name.'.tutor') + endif + call extend(l:tutors, l:locale_tutors) + return uniq(sort(l:tutors, 's:Sort'), 's:Sort') +endfunction + +function! tutor#TutorCmd(tutor_name) + if match(a:tutor_name, '[[:space:]]') > 0 + echom "Only one argument accepted (check spaces)" + return + endif + + if a:tutor_name == '' + let l:tutor_name = 'vim-01-beginner.tutor' + else + let l:tutor_name = a:tutor_name + endif + + if match(l:tutor_name, '\.tutor$') > 0 + let l:tutor_name = fnamemodify(l:tutor_name, ':r') + endif + + let l:tutors = s:GlobTutorials(l:tutor_name) + + if len(l:tutors) == 0 + echom "No tutorial with that name found" + return + endif + + if len(l:tutors) == 1 + let l:to_open = l:tutors[0] + else + let l:idx = 0 + let l:candidates = ['Several tutorials with that name found. Select one:'] + for candidate in map(copy(l:tutors), + \'fnamemodify(v:val, ":h:h:t")."/".s:Locale()[0]."/".fnamemodify(v:val, ":t")') + let l:idx += 1 + call add(l:candidates, l:idx.'. '.candidate) + endfor + let l:tutor_to_open = inputlist(l:candidates) + let l:to_open = l:tutors[l:tutor_to_open-1] + endif + + call tutor#SetupVim() + exe "edit ".l:to_open +endfunction + +function! tutor#TutorCmdComplete(lead,line,pos) + let l:tutors = s:GlobTutorials('*') + let l:names = uniq(sort(map(l:tutors, 'fnamemodify(v:val, ":t:r")'), 's:Sort')) + return join(l:names, "\n") +endfunction diff --git a/runtime/defaults.vim b/runtime/defaults.vim index 459841ffcc..4e58233ea5 100644 --- a/runtime/defaults.vim +++ b/runtime/defaults.vim @@ -1,7 +1,7 @@ " The default vimrc file. " " Maintainer: The Vim Project -" Last change: 2023 Aug 10 +" Last Change: 2024 Nov 03 " Former Maintainer: Bram Moolenaar " " This is loaded if no vimrc file was found. @@ -107,11 +107,11 @@ if 1 " (happens when dropping a file on gvim), for a commit or rebase message " (likely a different one than last time), and when using xxd(1) to filter " and edit binary files (it transforms input files back and forth, causing - " them to have dual nature, so to speak) + " them to have dual nature, so to speak) or when running the new tutor autocmd BufReadPost * \ let line = line("'\"") \ | if line >= 1 && line <= line("$") && &filetype !~# 'commit' - \ && index(['xxd', 'gitrebase'], &filetype) == -1 + \ && index(['xxd', 'gitrebase', 'tutor'], &filetype) == -1 \ | execute "normal! g`\"" \ | endif diff --git a/runtime/doc/Make_all.mak b/runtime/doc/Make_all.mak index f36ad7eca5..ccc429b0c7 100644 --- a/runtime/doc/Make_all.mak +++ b/runtime/doc/Make_all.mak @@ -75,6 +75,7 @@ DOCS = \ pi_paren.txt \ pi_spec.txt \ pi_tar.txt \ + pi_tutor.txt \ pi_vimball.txt \ pi_zip.txt \ popup.txt \ @@ -228,6 +229,7 @@ HTMLS = \ pi_paren.html \ pi_spec.html \ pi_tar.html \ + pi_tutor.html \ pi_vimball.html \ pi_zip.html \ popup.html \ diff --git a/runtime/doc/pi_tutor.txt b/runtime/doc/pi_tutor.txt new file mode 100644 index 0000000000..7aaafd19ad --- /dev/null +++ b/runtime/doc/pi_tutor.txt @@ -0,0 +1,51 @@ +*pi_tutor.txt* For Vim version 9.1. Last change: 2024 Nov 02 + +INTERACTIVE TUTORIALS FOR VIM *vim-tutor-mode* + +vim-tutor-mode provides a system to follow and create interactive tutorials +for vim and third party plugins. It replaces the venerable `vimtutor` system. + +============================================================================== +1. Usage *vim-tutor-usage* + +vim-tutor-mode tutorials are hypertext documents, they have rich text and +contain links. To stand out from the rest of the text, links are underlined. +You can follow them by placing the cursor over them and pressing , or +by double-clicking them. + +1.1 Commands +------------ + *:Tutor* +:Tutor {tutorial} Opens a tutorial. Command-line completion for + {tutorial} is provided, the candidates are a list of + '.tutor' files found in the 'tutor/' folder in + the 'runtimepath'. Tutorials prefixed with 'vim-' will + always be shown first. + + If no {tutorial} is provided, the command starts the + 'vim-01-beginner' tutorial, which is equivalent to + Vim's `vimtutor`. + +============================================================================= +2. Creating tutorials *vim-tutor-create* + +Writing vim-tutor-mode tutorials is easy. For an overview of the format used, +please consult the 'tutor.tutor' file: > + + :Tutor tutor +< +New tutorials must be placed in the 'tutor/' folder in the 'runtimepath' +to be detected by the :Tutor command. + +It is recommended to use a less formal style when writing tutorials than in +regular documentation (unless the content requires it). + +============================================================================ +3. Contributing + +Development of the plugin is done over at github [1]. Feel free to report +issues and make suggestions. + +[1]: https://github.com/fmoralesc/vim-tutor-mode + +" vim: set ft=help : diff --git a/runtime/doc/tags b/runtime/doc/tags index 79d9dafb94..37a8e266d5 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -2177,6 +2177,7 @@ $quote eval.txt /*$quote* :Termdebug terminal.txt /*:Termdebug* :TermdebugCommand terminal.txt /*:TermdebugCommand* :Texplore pi_netrw.txt /*:Texplore* +:Tutor pi_tutor.txt /*:Tutor* :Until terminal.txt /*:Until* :Up terminal.txt /*:Up* :UseVimball pi_vimball.txt /*:UseVimball* @@ -9438,6 +9439,7 @@ pi_netrw.txt pi_netrw.txt /*pi_netrw.txt* pi_paren.txt pi_paren.txt /*pi_paren.txt* pi_spec.txt pi_spec.txt /*pi_spec.txt* pi_tar.txt pi_tar.txt /*pi_tar.txt* +pi_tutor.txt pi_tutor.txt /*pi_tutor.txt* pi_vimball.txt pi_vimball.txt /*pi_vimball.txt* pi_zip.txt pi_zip.txt /*pi_zip.txt* pkzip options.txt /*pkzip* @@ -11244,6 +11246,9 @@ vim-script-intro usr_41.txt /*vim-script-intro* vim-script-library eval.txt /*vim-script-library* vim-security intro.txt /*vim-security* vim-shebang various.txt /*vim-shebang* +vim-tutor-create pi_tutor.txt /*vim-tutor-create* +vim-tutor-mode pi_tutor.txt /*vim-tutor-mode* +vim-tutor-usage pi_tutor.txt /*vim-tutor-usage* vim-use intro.txt /*vim-use* vim-variable eval.txt /*vim-variable* vim.b if_lua.txt /*vim.b* diff --git a/runtime/doc/usr_01.txt b/runtime/doc/usr_01.txt index fdf1b5386b..9902691bad 100644 --- a/runtime/doc/usr_01.txt +++ b/runtime/doc/usr_01.txt @@ -1,4 +1,4 @@ -*usr_01.txt* For Vim version 9.1. Last change: 2024 May 11 +*usr_01.txt* For Vim version 9.1. Last change: 2024 Nov 03 VIM USER MANUAL - by Bram Moolenaar @@ -107,6 +107,8 @@ For more info see |vimrc| and |compatible-default|. ============================================================================== *01.3* Using the Vim tutor *tutor* *vimtutor* +For the interactive tutor, see |vim-tutor-mode| + Instead of reading the text (boring!) you can use the vimtutor to learn your first Vim commands. This is a 30-minute tutorial that teaches the most basic Vim functionality hands-on. diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 5f9250348b..d016ccfb1b 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2024 Nov 02 +*version9.txt* For Vim version 9.1. Last change: 2024 Nov 03 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41603,6 +41603,8 @@ Changed~ - the putty terminal is detected using an |TermResponse| autocommand in |defaults.vim| and Vim switches to a dark background - the |help-TOC| package is included to ease navigating the documentation. +- an interactive tutor plugin has been included |vim-tutor-mode|, can be + started via |:Tutor| *added-9.2* Added ~ diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 36461f69f8..f2ddcc6767 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -2589,6 +2589,9 @@ au BufNewFile,BufReadPost *.tsscl setf tsscl " TSV Files au BufNewFile,BufRead *.tsv setf tsv +" Tutor mode +au BufNewFile,BufReadPost *.tutor setf tutor + " TWIG files au BufNewFile,BufReadPost *.twig setf twig diff --git a/runtime/ftplugin/tutor.vim b/runtime/ftplugin/tutor.vim new file mode 100644 index 0000000000..30783d9799 --- /dev/null +++ b/runtime/ftplugin/tutor.vim @@ -0,0 +1,45 @@ +" vim: fdm=marker + +" Base: {{{1 +call tutor#SetupVim() + +" Buffer Settings: {{{1 +setlocal noreadonly +if !exists('g:tutor_debug') || g:tutor_debug == 0 + setlocal buftype=nofile + setlocal concealcursor+=inv + setlocal conceallevel=2 +else + setlocal buftype= + setlocal concealcursor& + setlocal conceallevel=0 +endif +setlocal noundofile + +setlocal keywordprg=:help +setlocal iskeyword=@,-,_ + +" The user will have to enable the folds himself, but we provide the foldexpr +" function. +setlocal foldmethod=manual +setlocal foldexpr=tutor#TutorFolds() +setlocal foldlevel=4 + +" Load metadata if it exists: {{{1 +if filereadable(expand('%').'.json') + call tutor#LoadMetadata() +endif + +" Mappings: {{{1 + +call tutor#SetNormalMappings() + +" Checks: {{{1 + +sign define tutorok text=✓ texthl=tutorOK +sign define tutorbad text=✗ texthl=tutorX + +if !exists('g:tutor_debug') || g:tutor_debug == 0 + call tutor#ApplyMarks() + autocmd! TextChanged,TextChangedI call tutor#ApplyMarksOnChanged() +endif diff --git a/runtime/plugin/tutor.vim b/runtime/plugin/tutor.vim new file mode 100644 index 0000000000..1411b1ac63 --- /dev/null +++ b/runtime/plugin/tutor.vim @@ -0,0 +1,6 @@ +if exists('g:loaded_tutor_mode_plugin') || &compatible + finish +endif +let g:loaded_tutor_mode_plugin = 1 + +command! -nargs=? -complete=custom,tutor#TutorCmdComplete Tutor call tutor#TutorCmd() diff --git a/runtime/syntax/tutor.vim b/runtime/syntax/tutor.vim new file mode 100644 index 0000000000..83ca547fdd --- /dev/null +++ b/runtime/syntax/tutor.vim @@ -0,0 +1,77 @@ +if exists("b:current_syntax") + finish +endif + +syn include @VIM syntax/vim.vim +unlet b:current_syntax +syn include @TUTORSHELL syntax/sh.vim +unlet b:current_syntax +syn include @VIMNORMAL syntax/vimnormal.vim + +syn match tutorLink /\[.\{-}\](.\{-})/ contains=tutorInlineNormal +syn match tutorLinkBands /\[\|\]\|(\|)/ contained containedin=tutorLink,tutorLinkAnchor conceal +syn match tutorLinkAnchor /(.\{-})/ contained containedin=tutorLink conceal +syn match tutorURL /\(https\?\|file\):\/\/[[:graph:]]\+\>\/\?/ +syn match tutorEmail /\<[[:graph:]]\+@[[:graph:]]\+\>/ +syn match tutorInternalAnchor /\*[[:alnum:]-]\+\*/ contained conceal containedin=tutorSection + +syn match tutorSection /^#\{1,6}\s.\+$/ fold contains=tutorInlineNormal +syn match tutorSectionBullet /#/ contained containedin=tutorSection + +syn match tutorTOC /\ctable of contents:/ + +syn match tutorConcealedEscapes /\\[`*!\[\]():$-]\@=/ conceal + +syn region tutorEmphasis matchgroup=Delimiter start=/[\*]\@=?@ABCDGHIJKLMNOPQRSUVWXYZgmqstz~iu]/ nextgroup=normalMod +syn match normalMod /m\@BW\[\]`bstweE{}ftFT;,$]/ +syn match normalCount /[0-9]/ +syn region normalSearch start=/[/?]\@<=./ end=/.\@=/ contains=normalKey keepend +syn region normalChange start=/\([cr][wWbBeE()\[\]{}pst]\)\@<=./ end=/.\@=/ contains=normalKey keepend +syn match normalCharSearch /\c[ftr]\@<=\w/ +syn match normalMark /\(f\@'\@!/ + +hi! link normalOp Operator +hi! link normalMod PreProc +hi! link normalObject Structure +hi! link normalCount Number +hi! link normalMark Identifier +hi! link normalKey Special diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor new file mode 100644 index 0000000000..ebb946158c --- /dev/null +++ b/runtime/tutor/en/vim-01-beginner.tutor @@ -0,0 +1,980 @@ +# Welcome to the VIM Tutor + +Vim is a very powerful editor that has many commands, too many to explain in +a tutor such as this. This tutor is designed to describe enough of the +commands that you will be able to easily use Vim as an all-purpose editor. +It is IMPORTANT to remember that this tutor is set up to teach by use. That +means that you need to do the exercises to learn them properly. If you only +read the text, you will soon forget what is most important! + +For now, make sure that your Shift-Lock key is NOT depressed and press the +`j`{normal} key enough times to move the cursor so that Lesson 0 completely +fills the screen. + +# Lesson 0 + +NOTE: The commands in the lessons will modify the text, but those changes +won't be saved. Don't worry about messing things up; just remember that +pressing []() and then [u](u) will undo the latest change. + +This tutorial is interactive, and there are a few things you should know. +- Type []() on links [like this](holy-grail ) to open the linked help section. +- Or simply type [K](K) on any word to find its documentation! +- Sometimes you will be required to modify text like +this here +Once you have done the changes correctly, the ✗ sign at the left will change +to ✓. I imagine you can already see how neat Vim can be. ;) +Other times, you'll be prompted to run a command (I'll explain this later): +~~~ cmd + :help +~~~ +or press a sequence of keys +~~~ normal + 0fd3wP$P +~~~ + +Text within <'s and >'s (like ``{normal}) describes a key to press +instead of text to type. + +Now, move to the next lesson (use the `j`{normal} key to scroll down). + +## Lesson 1.1: MOVING THE CURSOR + +** To move the cursor, press the `h`, `j`, `k`, `l` keys as indicated. ** + + ↑ + k Hint: The `h`{normal} key is at the left and moves left. + ← h l → The `l`{normal} key is at the right and moves right. + j The `j`{normal} key looks like a down arrow. + ↓ + + 1. Move the cursor around the screen until you are comfortable. + + 2. Hold down the down key (`j`{normal}) until it repeats. + Now you know how to move to the next lesson. + + 3. Using the down key, move to Lesson 1.2. + +NOTE: If you are ever unsure about something you typed, press to place + you in Normal mode. Then retype the command you wanted. + +NOTE: The cursor keys should also work. But using hjkl you will be able to + move around much faster, once you get used to it. Really! + +# Lesson 1.2: EXITING VIM + +!! NOTE: Before executing any of the steps below, +read this entire lesson !! + + 1. Press the key (to make sure you are in Normal mode). + + 2. Type: + + `:q!`{vim} ``{normal}. + + This exits the editor, DISCARDING any changes you have made. + + 3. Open vim and get back here by executing the command that got you into + this tutor. That might be: + + :Tutor + + 4. If you have these steps memorized and are confident, execute steps + 1 through 3 to exit and re-enter the editor. + +NOTE: [:q!](:q) discards any changes you made. In a few lessons you + will learn how to save the changes to a file. + + 5. Move the cursor down to Lesson 1.3. + +## Lesson 1.3: TEXT EDITING - DELETION + +** Press `x`{normal} to delete the character under the cursor. ** + + 1. Move the cursor to the line below marked ✗. + + 2. To fix the errors, move the cursor until it is on top of the + character to be deleted. + + 3. Press [the x key](x) to delete the unwanted character. + + 4. Repeat steps 2 through 4 until the sentence is correct. + +The ccow jumpedd ovverr thhe mooon. + + 5. Now that the line is correct, go on to Lesson 1.4. + +NOTE: As you go through this tutor, do not try to memorize, learn by + usage. + +# Lesson 1.4: TEXT EDITING: INSERTION + +** Press `i`{normal} to insert text. ** + + 1. Move the cursor to the first line below marked ✗. + + 2. To make the first line the same as the second, move the cursor on top + of the first character AFTER where the text is to be inserted. + + 3. Press `i`{normal} and type in the necessary additions. + + 4. As each error is fixed press ``{normal} to return to Normal mode. + Repeat steps 2 through 4 to correct the sentence. + +There is text misng this . +There is some text missing from this line. + + 5. When you are comfortable inserting text move to Lesson 1.5. + +# Lesson 1.5: TEXT EDITING: APPENDING + +** Press `A`{normal} to append text. ** + + 1. Move the cursor to the first line below marked ✗. + It does not matter on what character the cursor is in that line. + + 2. Press [A](A) and type in the necessary additions. + + 3. As the text has been appended press ``{normal} to return to Normal + mode. + + 4. Move the cursor to the second line marked ✗ and repeat + steps 2 and 3 to correct this sentence. + +There is some text missing from th +There is some text missing from this line. +There is also some text miss +There is also some text missing here. + + 5. When you are comfortable appending text move to Lesson 1.6. + +# Lesson 1.6: EDITING A FILE + +** Use `:wq`{vim} to save a file and exit. ** + +!! NOTE: Before executing any of the steps below, read this entire lesson !! + + 1. Exit this tutor as you did in Lesson 1.2: `:q!`{vim} + Or, if you have access to another terminal, do the following there. + + 2. At the shell prompt type this command: +~~~ sh + $ vim tutor +~~~ + 'vim' is the command to start the Vim editor, 'tutor' is the name of + the file you wish to edit. Use a file that may be changed. + + 3. Insert and delete text as you learned in the previous lessons. + + 4. Save the file with changes and exit Vim with: +~~~ cmd + :wq +~~~ + + Note you'll need to press `` to execute the command. + + 5. If you have quit vimtutor in step 1 restart the vimtutor and move down + to the following summary. + + 6. After reading the above steps and understanding them: do it. + +# Lesson 1 SUMMARY + + 1. The cursor is moved using either the arrow keys or the hjkl keys. + h (left) j (down) k (up) l (right) + + 2. To start Vim from the shell prompt type: + +~~~ sh + $ vim FILENAME +~~~ + + 3. To exit Vim type: ``{normal} `:q!`{vim} ``{normal} to trash + all changes. + OR type: ``{normal} `:wq`{vim} ``{normal} to save + the changes. + + 4. To delete the character at the cursor type: `x`{normal} + + 5. To insert or append text type: + `i`{normal} insert text ``{normal} insert before the cursor. + `A`{normal} append text ``{normal} append after the line. + +NOTE: Pressing ``{normal} will place you in Normal mode or will cancel + an unwanted and partially completed command. + +Now continue with Lesson 2. + +# Lesson 2.1: DELETION COMMANDS + +** Type `dw`{normal} to delete a word. ** + + 1. Press ``{normal} to make sure you are in Normal mode. + + 2. Move the cursor to the line below marked ✗. + + 3. Move the cursor to the beginning of a word that needs to be deleted. + + 4. Type [d](d)[w](w) to make the word disappear. + +There are a some words fun that don't belong paper in this sentence. + + 5. Repeat steps 3 and 4 until the sentence is correct and go to Lesson 2.2. + +# Lesson 2.2: MORE DELETION COMMANDS + +** Type `d$`{normal} to delete to the end of the line. ** + + 1. Press ``{normal} to make sure you are in Normal mode. + + 2. Move the cursor to the line below marked ✗. + + 3. Move the cursor to the end of the correct line (AFTER the first . ). + + 4. Type `d$`{normal} to delete to the end of the line. + +Somebody typed the end of this line twice. end of this line twice. + + 5. Move on to Lesson 2.3 to understand what is happening. + +# Lesson 2.3: ON OPERATORS AND MOTIONS + +Many commands that change text are made from an [operator](operator) and +a [motion](navigation). +The format for a delete command with the [d](d) delete operator is as follows: + + d motion + + Where: + d - is the delete operator. + motion - is what the operator will operate on (listed below). + + A short list of motions: + [w](w) - until the start of the next word, EXCLUDING its first character. + [e](e) - to the end of the current word, INCLUDING the last character. + [$]($) - to the end of the line, INCLUDING the last character. + + Thus typing `de`{normal} will delete from the cursor to the end of the word. + +NOTE: Pressing just the motion while in Normal mode without an operator + will move the cursor as specified. + +# Lesson 2.4: USING A COUNT FOR A MOTION + +** Typing a number before a motion repeats it that many times. ** + + 1. Move the cursor to the start of the line marked ✓ below. + + 2. Type `2w`{normal} to move the cursor two words forward. + + 3. Type `3e`{normal} to move the cursor to the end of the third word forward. + + 4. Type `0`{normal} ([zero](0)) to move to the start of the line. + + 5. Repeat steps 2 and 3 with different numbers. + +This is just a line with words you can move around in. + + 6. Move on to Lesson 2.5. + +# Lesson 2.5: USING A COUNT TO DELETE MORE + +** Typing a number with an operator repeats it that many times. ** + +In the combination of the delete operator and a motion mentioned above you +insert a count before the motion to delete more: + d number motion + + 1. Move the cursor to the first UPPER CASE word in the line marked ✗. + + 2. Type `d2w`{normal} to delete the two UPPER CASE words + + 3. Repeat steps 1 and 2 with a different count to delete the consecutive + UPPER CASE words with one command + +This ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up. + +# Lesson 2.6: OPERATING ON LINES + +** Type `dd`{normal} to delete a whole line. ** + +Due to the frequency of whole line deletion, the designers of Vi decided +it would be easier to simply type two d's to delete a line. + + 1. Move the cursor to the second line in the phrase below. + 2. Type [dd](dd) to delete the line. + 3. Now move to the fourth line. + 4. Type `2dd`{normal} to delete two lines. + +1) Roses are red, +2) Mud is fun, +3) Violets are blue, +4) I have a car, +5) Clocks tell time, +6) Sugar is sweet +7) And so are you. + +# Lesson 2.7: THE UNDO COMMAND + +** Press `u`{normal} to undo the last commands, `U`{normal} to fix a whole line. ** + + 1. Move the cursor to the line below marked ✗ and place it on the + first error. + 2. Type `x`{normal} to delete the first unwanted character. + 3. Now type `u`{normal} to undo the last command executed. + 4. This time fix all the errors on the line using the `x`{normal} command. + 5. Now type a capital `U`{normal} to return the line to its original state. + 6. Now type `u`{normal} a few times to undo the `U`{normal} and preceding + commands. + 7. Now type ``{normal} (Control + R) a few times to redo the commands + (undo the undos). + +Fiix the errors oon thhis line and reeplace them witth undo. + + 8. These are very useful commands. Now move on to the Lesson 2 Summary. + +# Lesson 2 SUMMARY + + 1. To delete from the cursor up to the next word type: `dw`{normal} + 2. To delete from the cursor to the end of a line type: `d$`{normal} + 3. To delete a whole line type: `dd`{normal} + 4. To repeat a motion prepend it with a number: `2w`{normal} + + 5. The format for a change command is: + operator [number] motion + where: + operator - is what to do, such as [d](d) for delete + [number] - is an optional count to repeat the motion + motion - moves over the text to operate on, such as: + [w](w) (word), + [$]($) (to the end of line), etc. + + 6. To move to the start of the line use a zero: [0](0) + + 7. To undo previous actions, type: `u`{normal} (lowercase u) + To undo all the changes on a line, type: `U`{normal} (capital U) + To undo the undo's, type: ``{normal} + +# Lesson 3.1: THE PUT COMMAND + +** Type `p`{normal} to put previously deleted text after the cursor. ** + + 1. Move the cursor to the first ✓ line below. + + 2. Type `dd`{normal} to delete the line and store it in a Vim register. + + 3. Move the cursor to the c) line, ABOVE where the deleted line should go. + + 4. Type `p`{normal} to put the line below the cursor. + + 5. Repeat steps 2 through 4 to put all the lines in correct order. + +d) Can you learn too? +b) Violets are blue, +c) Intelligence is learned, +a) Roses are red, + +# Lesson 3.2: THE REPLACE COMMAND + +** Type `rx`{normal} to replace the character at the cursor with x. ** + + 1. Move the cursor to the first line below marked ✗. + + 2. Move the cursor so that it is on top of the first error. + + 3. Type `r`{normal} and then the character which should be there. + + 4. Repeat steps 2 and 3 until the first line is equal to the second one. + +Whan this lime was tuoed in, someone presswd some wrojg keys! +When this line was typed in, someone pressed some wrong keys! + + 5. Now move on to Lesson 3.3. + +NOTE: Remember that you should be learning by doing, not memorization. + +# Lesson 3.3: THE CHANGE OPERATOR + +** To change until the end of a word, type `ce`{normal}. ** + + 1. Move the cursor to the first line below marked ✗. + + 2. Place the cursor on the "u" in "lubw". + + 3. Type `ce`{normal} and the correct word (in this case, type "ine" ). + + 4. Press ``{normal} and move to the next character that needs to be + changed. + + 5. Repeat steps 3 and 4 until the first sentence is the same as the second. + +This lubw has a few wptfd that mrrf changing usf the change operator. +This line has a few words that need changing using the change operator. + +Notice that [c](c)e deletes the word and places you in Insert mode. + +# Lesson 3.4: MORE CHANGES USING `c`{normal} + +** The change operator is used with the same motions as delete. ** + + 1. The change operator works in the same way as delete. The format is: + + c [number] motion + + 2. The motions are the same, such as `w`{normal} (word) and `$`{normal} (end of line). + + 3. Move to the first line below marked ✗. + + 4. Move the cursor to the first error. + + 5. Type `c$`{normal} and type the rest of the line like the second and press ``{normal}. + +The end of this line needs some help to make it like the second. +The end of this line needs to be corrected using the `c$`{normal} command. + +NOTE: You can use the Backspace key to correct mistakes while typing. + +# Lesson 3 SUMMARY + + 1. To put back text that has just been deleted, type [p](p). This puts the + deleted text AFTER the cursor (if a line was deleted it will go on the + line below the cursor). + + 2. To replace the character under the cursor, type [r](r) and then the + character you want to have there. + + 3. The [change operator](c) allows you to change from the cursor to where + the motion takes you. Type `ce`{normal} to change from the cursor to the + end of the word, `c$`{normal} to change to the end of a line. + + 4. The format for change is: + + c [number] motion + +Now go on to the next lesson. + +# Lesson 4.1: CURSOR LOCATION AND FILE STATUS + +** Type ``{normal} to show your location in a file and the file status. + Type `G`{normal} to move to a line in the file. ** + +NOTE: Read this entire lesson before executing any of the steps!! + + 1. Hold down the ``{normal} key and press `g`{normal}. We call this + ``{normal}. A message will appear at the bottom of the page with the + filename and the position in the file. Remember the line number for + Step 3. + +NOTE: You may see the cursor position in the lower right corner of the + screen. This happens when the ['ruler']('ruler') option is set. + 2. Press [G](G) to move you to the bottom of the file. + Type [gg](gg) to move you to the start of the file. + + 3. Type the number of the line you were on and then `G`{normal}. This will + return you to the line you were on when you first pressed ``{normal}. + + 4. If you feel confident to do this, execute steps 1 through 3. + +# Lesson 4.2: THE SEARCH COMMAND + +** Type `/`{normal} followed by a phrase to search for the phrase. ** + + 1. In Normal mode type the `/`{normal} character. Notice that it and the + cursor appear at the bottom of the screen as with the `:`{normal} command. + + 2. Now type 'errroor' ``{normal}. This is the word you want to search + for. + + 3. To search for the same phrase again, simply type [n](n). + To search for the same phrase in the opposite direction, type [N](N). + + 4. To search for a phrase in the backward direction, use [?](?) instead + of `/`{normal}. + + 5. To go back to where you came from press ``{normal} (keep ``{normal} pressed down while pressing the letter `o`{normal}). Repeat to go back + further. ``{normal} goes forward. + +"errroor" is not the way to spell error; errroor is an error. + +NOTE: When the search reaches the end of the file it will continue at the + start, unless the ['wrapscan']('wrapscan') option has been reset. + +# Lesson 4.3: MATCHING PARENTHESES SEARCH + +** Type `%`{normal} to find a matching ),], or }. ** + + 1. Place the cursor on any (, [, or { in the line below marked ✓. + + 2. Now type the [%](%) character. + + 3. The cursor will move to the matching parenthesis or bracket. + + 4. Type `%`{normal} to move the cursor to the other matching bracket. + + 5. Move the cursor to another (,),[,],{ or } and see what `%`{normal} does. + +This ( is a test line with ('s, ['s ] and {'s } in it. )) + +NOTE: This is very useful in debugging a program with unmatched parentheses! + +# Lesson 4.4: THE SUBSTITUTE COMMAND + +** Type `:s/old/new/g` to substitute "new" for "old". ** + + 1. Move the cursor to the line below marked ✗. + + 2. Type +~~~ cmd + :s/thee/the/ +~~~ + + NOTE that the [:s](:s) command only changed the first occurrence of "thee" in the line. + + 3. Now type +~~~ cmd + :s/thee/the/g +~~~ + + Adding the g [flag](:s_flags) means to substitute globally in the line, + change all occurrences of "thee" in the line. + +Usually thee best time to see thee flowers is in thee spring. + + 4. To change every occurrence of a character string between two lines, type +~~~ cmd + :#,#s/old/new/g +~~~ + where #,# are the line numbers of the range of lines where the + substitution is to be done. + + Type +~~~ cmd + :%s/old/new/g +~~~ + to change every occurrence in the whole file. + + Type +~~~ cmd + :%s/old/new/gc +~~~ + to find every occurrence in the whole file, with a prompt whether to + substitute or not. + +# Lesson 4 SUMMARY + + 1. ``{normal} displays your location and the file status. + `G`{normal} moves to the end of the file. + number `G`{normal} moves to that line number. + `gg`{normal} moves to the first line. + + 2. Typing `/`{normal} followed by a phrase searches FORWARD for the phrase. + Typing `?`{normal} followed by a phrase searches BACKWARD for the phrase. + After a search type `n`{normal} to find the next occurrence in the same + direction or `N`{normal} to search in the opposite direction. + ``{normal} takes you back to older positions, ``{normal} to + newer positions. + + 3. Typing `%`{normal} while the cursor is on a (,),[,],{, or } goes to its + match. + + 4. To substitute new for the first old in a line type +~~~ cmd + :s/old/new +~~~ + To substitute new for all 'old's on a line type +~~~ cmd + :s/old/new/g +~~~ + To substitute phrases between two line #'s type +~~~ cmd + :#,#s/old/new/g +~~~ + To substitute all occurrences in the file type +~~~ cmd + :%s/old/new/g +~~~ + To ask for confirmation each time add 'c' +~~~ cmd + :%s/old/new/gc +~~~ + +# Lesson 5.1: HOW TO EXECUTE AN EXTERNAL COMMAND + +** Type `:!`{vim} followed by an external command to execute that command. ** + + 1. Type the familiar command `:`{normal} to set the cursor at the bottom of + the screen. This allows you to enter a command-line command. + + 2. Now type the [!](!cmd) (exclamation point) character. This allows you to + execute any external shell command. + + 3. As an example type "ls" following the "!" and then hit ``{normal}. + This will show you a listing of your directory, just as if you were + at the shell prompt. + +NOTE: It is possible to execute any external command this way, also with + arguments. + +NOTE: All `:`{vim} commands must be finished by hitting ``{normal}. + From here on we will not always mention it. + +# Lesson 5.2: MORE ON WRITING FILES + +** To save the changes made to the text, type `:w`{vim} FILENAME. ** + + 1. Type `:!ls`{vim} to get a listing of your directory. + You already know you must hit ``{normal} after this. + + 2. Choose a filename that does not exist yet, such as TEST. + + 3. Now type: +~~~ cmd + :w TEST +~~~ + (where TEST is the filename you chose.) + + 4. This saves the whole file (the Vim Tutor) under the name TEST. + To verify this, type `:!ls`{vim} again to see your directory. + +NOTE: If you were to exit Vim and start it again with `vim TEST`, the file + would be an exact copy of the tutor when you saved it. + + 5. Now remove the file by typing: +~~~ cmd + :!rm TEST +~~~ + +# Lesson 5.3: SELECTING TEXT TO WRITE + +** To save part of the file, type `v`{normal} motion `:w FILENAME`{vim}. ** + + 1. Move the cursor to this line. + + 2. Press [v](v) and move the cursor to the fifth item below. Notice that the + text is highlighted. + + 3. Press the `:`{normal} character. At the bottom of the screen + + :'<,'> + + will appear. + + 4. Type + + `:w TEST`{vim} + + where TEST is a filename that does not exist yet. Verify that you see + + `:'<,'>w TEST`{vim} + + before you press ``{normal}. + + 5. Vim will write the selected lines to the file TEST. Use `:!ls`{vim} to see it. Do not remove it yet! We will use it in the next lesson. + +NOTE: Pressing [v](v) starts [Visual selection](visual-mode). You can move + the cursor around to make the selection bigger or smaller. Then you can + use an operator to do something with the text. For example, `d`{normal} + deletes the text. + +# Lesson 5.4: RETRIEVING AND MERGING FILES + +** To insert the contents of a file, type `:r FILENAME`{vim}. ** + + 1. Place the cursor just above this line. + +NOTE: After executing Step 2 you will see text from Lesson 5.3. Then move + DOWN to see this lesson again. + + 2. Now retrieve your TEST file using the command + + `:r TEST`{vim} + + where TEST is the name of the file you used. + The file you retrieve is placed below the cursor line. + + 3. To verify that a file was retrieved, cursor back and notice that there + are now two copies of Lesson 5.3, the original and the file version. + +NOTE: You can also read the output of an external command. For example, + + `:r !ls`{vim} + + reads the output of the `ls` command and puts it below the cursor. + +# Lesson 5 SUMMARY + + 1. [:!command](:!cmd) executes an external command. + + Some useful examples are: + `:!ls`{vim} - shows a directory listing + `:!rm FILENAME`{vim} - removes file FILENAME + + 2. [:w](:w) FILENAME writes the current Vim file to disk with + name FILENAME. + + 3. [v](v) motion :w FILENAME saves the Visually selected lines in file + FILENAME. + + 4. [:r](:r) FILENAME retrieves disk file FILENAME and puts it + below the cursor position. + + 5. [:r !dir](:r!) reads the output of the dir command and + puts it below the cursor position. + +# Lesson 6.1: THE OPEN COMMAND + +** Type `o`{normal} to open a line below the cursor and place you in Insert mode. ** + + 1. Move the cursor to the line below marked ✓. + + 2. Type the lowercase letter `o`{normal} to [open](o) up a line BELOW the + cursor and place you in Insert mode. + + 3. Now type some text and press ``{normal} to exit Insert mode. + +After typing `o`{normal} the cursor is placed on the open line in Insert mode. + + 4. To open up a line ABOVE the cursor, simply type a [capital O](O), rather + than a lowercase `o`{normal}. Try this on the line below. + +Open up a line above this by typing O while the cursor is on this line. + +# Lesson 6.2: THE APPEND COMMAND + +** Type `a`{normal} to insert text AFTER the cursor. ** + + 1. Move the cursor to the start of the line below marked ✗. + + 2. Press `e`{normal} until the cursor is on the end of "li". + + 3. Type the lowercase letter `a`{normal} to [append](a) text AFTER the + cursor. + + 4. Complete the word like the line below it. Press ``{normal} to exit + Insert mode. + + 5. Use `e`{normal} to move to the next incomplete word and repeat steps 3 + and 4. + +This li will allow you to pract appendi text to a line. +This line will allow you to practice appending text to a line. + +NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only + difference is where the characters are inserted. + +# Lesson 6.3: ANOTHER WAY TO REPLACE + +** Type a capital `R`{normal} to replace more than one character. ** + + 1. Move the cursor to the first line below marked ✗. Move the cursor to + the beginning of the first "xxx". + + 2. Now press `R`{normal} ([capital R](R)) and type the number below it in the + second line, so that it replaces the "xxx". + + 3. Press ``{normal} to leave [Replace mode](mode-replace). Notice that + the rest of the line remains unmodified. + + 4. Repeat the steps to replace the remaining "xxx". + +Adding 123 to xxx gives you xxx. +Adding 123 to 456 gives you 579. + +NOTE: Replace mode is like Insert mode, but every typed character deletes an + existing character. + +# Lesson 6.4: COPY AND PASTE TEXT + +** Use the `y`{normal} operator to copy text and `p`{normal} to paste it. ** + + 1. Go to the line marked with ✓ below and place the cursor after "a)". + + 2. Start Visual mode with `v`{normal} and move the cursor to just before + "first". + + 3. Type `y`{normal} to [yank](yank) (copy) the highlighted text. + + 4. Move the cursor to the end of the next line: `j$`{normal} + + 5. Type `p`{normal} to [put](put) (paste) the text. + + 6. Press `a`{normal} and then type "second". Press ``{normal} to leave + Insert mode. + + 7. Use Visual mode to select "item.", yank it with `y`{normal}, move to the + end of the next line with `j$`{normal} and put the text there with `p`{normal} + +a) This is the first item. +b) + +NOTE: you can use `y`{normal} as an operator: `yw`{normal} yanks one word. + +# Lesson 6.5: SET OPTION + +** Set an option so a search or substitute ignores case. ** + + 1. Search for 'ignore' by entering: `/ignore` + Repeat several times by pressing `n`{normal}. + + 2. Set the 'ic' (Ignore case) option by entering: +~~~ cmd + :set ic +~~~ + 3. Now search for 'ignore' again by pressing `n`{normal}. + Notice that Ignore and IGNORE are now also found. + + 4. Set the 'hlsearch' and 'incsearch' options: +~~~ cmd + :set hls is +~~~ + 5. Now type the search command again and see what happens: /ignore + + 6. To disable ignoring case enter: +~~~ cmd + :set noic +~~~ + 7. To toggle the value of a setting, prepend it with "inv": +~~~ cmd + :set invic +~~~ +NOTE: To remove the highlighting of matches enter: +~~~ cmd + :nohlsearch +~~~ +NOTE: If you want to ignore case for just one search command, use [\c](/\c) + in the phrase: /ignore\c + +# Lesson 6 SUMMARY + + 1. Type `o`{normal} to open a line BELOW the cursor and start Insert mode. + Type `O`{normal} to open a line ABOVE the cursor. + + 2. Type `a`{normal} to insert text AFTER the cursor. + Type `A`{normal} to insert text after the end of the line. + + 3. The `e`{normal} command moves to the end of a word. + + 4. The `y`{normal} operator copies text, `p`{normal} pastes it. + + 5. Typing a capital `R`{normal} enters Replace mode until ``{normal} is + pressed. + + 6. Typing "[:set](:set) xxx" sets the option "xxx". Some options are: + + 'ic' 'ignorecase' ignore upper/lower case when searching + 'is' 'incsearch' show partial matches for a search phrase + 'hls' 'hlsearch' highlight all matching phrases + + You can either use the long or the short option name. + + 7. Prepend "no" to switch an option off: +~~~ cmd + :set noic +~~~ + 8. Prepend "inv" to toggle an option: +~~~ cmd + :set invic +~~~ + +# Lesson 7.1: GETTING HELP + +** Use the on-line help system. ** + +Vim has a comprehensive on-line help system. To get started, try one of +these three: + - press the ``{normal} key (if you have one) + - press the ``{normal} key (if you have one) + - type + `:help`{vim} + +Read the text in the help window to find out how the help works. +Type ``{normal} to jump from one window to another. +Type `:q`{vim} to close the help window. + +You can find help on just about any subject, by giving an argument to the +":help" command. Try these (don't forget pressing ): +~~~ cmd + :help w + :help c_CTRL-D + :help insert-index + :help user-manual +~~~ +# Lesson 7.2: CREATE A STARTUP SCRIPT + +** Enable Vim features. ** + +Vim has many more features than Vi, but most of them are disabled by +default. To start using more features you have to create a "vimrc" file. + + 1. Start editing the "vimrc" file. + `:call mkdir(stdpath('config'),'p')`{vim} + `:exe 'edit' stdpath('config').'/init.vim'`{vim} + + 2. Write the file with: + `:w`{vim} + + You can add all your preferred settings to this "vimrc" file. + For more information type `:help vimrc-intro`{vim}. + +# Lesson 7.3: COMPLETION + +** Command line completion with ``{normal} and ``{normal}. ** + + 1. Look what files exist in the directory: `:!ls`{vim} + + 2. Type the start of a command: `:e`{vim} + + 3. Press ``{normal} and Vim will show a list of commands that start + with "e". + + 4. Press ``{normal} and Vim will complete the command name to ":edit". + + 5. Now add a space and the start of an existing file name: `:edit FIL`{vim} + + 6. Press ``{normal}. Vim will complete the name (if it is unique). + +NOTE: Completion works for many commands. It is especially useful for + `:help`{vim}. + +# Lesson 7 SUMMARY + + 1. Type `:help`{vim} + or press ``{normal} or ``{normal} to open a help window. + + 2. Type `:help TOPIC`{vim} to find help on TOPIC. + + 3. Type ``{normal} to jump to another window + + 4. Type `:q`{vim} to close the help window + + 5. Create a vimrc startup script to keep your preferred settings. + + 6. While in command mode, press ``{normal} to see possible completions. + Press ``{normal} to use one completion. + +# CONCLUSION + +This was intended to give a brief overview of the Vim editor, just enough to +allow you to use the editor fairly easily. It is far from complete as Vim has +many many more commands. Consult the help often. + +There are many resources online to learn more about vim. Here's a bunch of +them: + +- *Learn Vim Progressively*: http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/ +- *Learning Vim in 2014*: http://benmccormick.org/learning-vim-in-2014/ +- *Vimcasts*: http://vimcasts.org/ +- *Vim Video-Tutorials by Derek Wyatt*: http://derekwyatt.org/vim/tutorials/ +- *Learn Vimscript the Hard Way*: http://learnvimscriptthehardway.stevelosh.com/ +- *7 Habits of Effective Text Editing*: http://www.moolenaar.net/habits.html +- *vim-galore*: https://github.com/mhinz/vim-galore + +If you prefer a book, *Practical Vim* and the sequel *Modern Vim* by Drew Neil +are recommended often. + +This tutorial was written by Michael C. Pierce and Robert K. Ware, Colorado +School of Mines using ideas supplied by Charles Smith, Colorado State +University. E-mail: bware@mines.colorado.edu. + +Modified for Vim by Bram Moolenaar. +Modified for vim-tutor-mode by Felipe Morales. diff --git a/runtime/tutor/en/vim-01-beginner.tutor.json b/runtime/tutor/en/vim-01-beginner.tutor.json new file mode 100644 index 0000000000..af22cf2aca --- /dev/null +++ b/runtime/tutor/en/vim-01-beginner.tutor.json @@ -0,0 +1,45 @@ +{ + "expect": { + "24": -1, + "103": "The cow jumped over the moon.", + "124": "There is some text missing from this line.", + "125": "There is some text missing from this line.", + "144": "There is some text missing from this line.", + "145": "There is some text missing from this line.", + "146": "There is also some text missing here.", + "147": "There is also some text missing here.", + "220": "There are some words that don't belong in this sentence.", + "236": "Somebody typed the end of this line twice.", + "276": -1, + "295": "This line of words is cleaned up.", + "309": -1, + "310": -1, + "311": -1, + "312": -1, + "313": -1, + "314": -1, + "315": -1, + "332": "Fix the errors on this line and replace them with undo.", + "372": -1, + "373": -1, + "374": -1, + "375": -1, + "389": "When this line was typed in, someone pressed some wrong keys!", + "390": "When this line was typed in, someone pressed some wrong keys!", + "411": "This line has a few words that need changing using the change operator.", + "412": "This line has a few words that need changing using the change operator.", + "432": "The end of this line needs to be corrected using the `c$` command.", + "433": "The end of this line needs to be corrected using the `c$` command.", + "497": -1, + "516": -1, + "541": "Usually the best time to see the flowers is in the spring.", + "735": -1, + "740": -1, + "759": "This line will allow you to practice appending text to a line.", + "760": "This line will allow you to practice appending text to a line.", + "780": "Adding 123 to 456 gives you 579.", + "781": "Adding 123 to 456 gives you 579.", + "807": "a) This is the first item.", + "808": "b) This is the second item." + } +} diff --git a/runtime/tutor/tutor.tutor b/runtime/tutor/tutor.tutor new file mode 100644 index 0000000000..b46fcc4836 --- /dev/null +++ b/runtime/tutor/tutor.tutor @@ -0,0 +1,247 @@ +# CREATING A VIM TUTORIAL WITH VIM-TUTOR-MODE + +This tutorial will guide you through the steps required to create a tutorial +file for vim-tutor-mode. It is also meant as a demo of vim-tutor-mode +capabilities. + +Table of contents: + +- [Setting up](*setting-up*) +- [vim-tutor-mode's markup](*markup*) + - [emphasis](*emphasis*) + - [headers](*headers*) + - [links](*links*) + - [codeblocks](*codeblocks*) +- [Interactive elements](*interactive*) + - [expect](*expect*) + +## SETTING UP *setting-up* + +First, you'll need to enable "debug" mode +~~~ cmd + :let g:tutor_debug = 1 +~~~ +This will allow saving changes to the tutor files and will disable conceals, so +you can more easily check your changes. + +After this, create a new .tutor file (we will be practicing on this very file, so you +don't need to do this now): +~~~ cmd + :e new-tutorial.tutor +~~~ + +## VIM-TUTOR-MODE's MARKDOWN *markup* + +vim-tutor-mode uses a subset of markdown's syntax to format the tutorials. The +subset supported should be enough for most tutorials and the maintainers will +try to keep it as small as possible (if regular markdown allows for several +ways to do the same thing, tutor markdown will only provide the one the +maintainers think is easier to handle). + +### Emphasis *emphasis* + +For emphasized text (italics), as in normal markdown, you use \*. E.g.: + + \*text\* + +is displayed like + + *text* + +Note: The underscores variant is not supported. + +For strong emphasis (bold), you use \*\*. E.g.: + + \*\*this\*\* + +is displayed like + + **this** + +1. Format the line below so it becomes a lesson description: + +This is text with important information +This is text with **important information** + +Note: Some words (e.g., NOTE, IMPORTANT, tip, ATTENTION, etc.) will also be +highlighted. You don't need to mark them specially. + +2. Turn the line below into a TODO item: + +Document '&variable' +TODO: Document '&variable' + +### Headers *headers* + +3. Practice fixing the lines below: + +This is a level 1 header +# This is a level 1 header +This is a level 3 header +### This is a level 3 header +This is a header with a label +# This is a header with a label {*label*} + +4. Now, create a 4th level section here, and add a label like in the previous +exercise: + + + + ATTENTION We will use this label later, so remember it. + +### Links *links* + +It is good practice to include links in your tutorials to reference materials, +like vim's own help or external documents. You can also link to other parts of +the document. + +Links have the syntax + + \[label\]\(target\) + +#### Help links + +If the target of a link matches a help topic, opening it will open it. + +5. Fix the following line: + +A link to help for the 'breakindent' option +A link to help for the ['breakindent']('breakindent') option + +#### Anchor links + +A link can also lead to a place in the file itself. Anchors are written + + \*anchor\* + +and are hidden by default. Links to them look like + + \[label\]\(\*anchor\*\) + +6. Add the appropriate link: + +A link to the Links section +A link to the [Links](*links*) section + +7. Now, create a link to the section you created on exercise 4 + above. + + + +# Tutorial links + +You can also have links to other tutorials. For this, you'll write the anchor in the format + + @tutor:TUTORIAL + +7. Create a link to this tutorial: + +A link to the vim-tutor-mode tutorial +A link to [the vim-tutor-mode tutorial](@tutor:tutor) + +### Codeblocks *codeblocks* + +vim-tutor-mode tutorials can include viml sections + + ~~~ cmd + echom "hello" + ~~~ + +is displayed as +~~~ cmd +echom "hello" +~~~ + +8. Copy the viml section below + + + + + +~~~ viml +echom 'the value of &number is'.string(&number) +~~~ + +You can inline viml code using "\`" and "\`{vim}": + + \`call myFunction()\`{vim} + +is displayed as + + `call myFunction()`{vim} + +[normal](Normal-mode) commands can also be embedded in tutorials. + + ~~~ normal + ftdaW + ~~~ + +is displayed as +~~~ normal +ftdaW +~~~ + +Note: you can also write `norm` or `normal`. + +9. Copy the normal section below + + + + + +~~~ normal +d2w +~~~ + +You can also inline normal commands by using "\`" and "\`{normal}": + + \`gq\`{normal} is very useful. + +is displayed: + + `gq`{normal} is very useful. + +10. Complete the line as shown + +d +`d2w`{normal} + +Commands to run in the system shell can be highlighted by indenting a line +starting with "$". + +~~~ sh + $ vim --version +~~~ + +## INTERACTIVE ELEMENTS *interactive* + +As visible in this very document, vim-tutor-mode includes some interactive +elements to provide feedback to the user about his progress. If the text in +these elements satisfies some set condition, a ✓ sign will appear in the gutter +to the left. Otherwise, a ✗ sign is displayed. + +### expect *expect* + +"expect" lines check that the contents of the line are identical to some preset text +(like in the exercises above). + +These elements are specified in separate JSON files like this + +~~~ json +{ + "expect": { + "1": "This is how this line should look.", + "2": "This is how this line should look.", + "3": -1 + } +} +~~~ + +These files contain an "expect" dictionary, for which the keys are line numbers and +the values are the expected text. A value of -1 means that the condition for the line +will always be satisfied, no matter what (this is useful for letting the user play a bit). + +This is an "expect" line that is always satisfied. Try changing it. + +These files conventionally have the same name as the tutorial document with the `.json` +extension appended (for a full example, see the file that corresponds to this tutorial). diff --git a/runtime/tutor/tutor.tutor.json b/runtime/tutor/tutor.tutor.json new file mode 100644 index 0000000000..bf3eae8586 --- /dev/null +++ b/runtime/tutor/tutor.tutor.json @@ -0,0 +1,35 @@ +{ + "expect": { + "63": "This is text with **important information**", + "64": "This is text with **important information**", + "71": "Document '&variable'", + "72": "Document '&variable'", + "78": "# This is a level 1 header", + "79": "# This is a level 1 header", + "80": "### This is a level 3 header", + "81": "### This is a level 3 header", + "82": "# This is a header with a label {*label*}", + "83": "# This is a header with a label {*label*}", + "108": "A link to help for the ['breakindent']('breakindent') option", + "109": "A link to help for the ['breakindent']('breakindent') option", + "123": "A link to the [Links](*links*) section", + "124": "A link to the [Links](*links*) section", + "139": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)", + "140": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)", + "157": "~~~ viml", + "158": "echom 'the value of &number is'.string(&number)", + "159": "~~~", + "161": "~~~ viml", + "162": "echom 'the value of &number is'.string(&number)", + "163": "~~~", + "188": "~~~ normal", + "189": "d2w", + "190": "~~~", + "192": "~~~ normal", + "193": "d2w", + "194": "~~~", + "206": "`d2w`{normal}", + "207": "`d2w`{normal}", + "244": -1 + } +} diff --git a/src/Makefile b/src/Makefile index 0b4a453ac0..c7ba9fbf7c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2346,7 +2346,7 @@ installrtbase: $(HELPSOURCE)/vim.1 $(DEST_VIM) $(VIMTARGET) $(DEST_RT) \ $(DEST_AUTO) $(DEST_AUTO)/dist $(DEST_AUTO)/xml \ $(DEST_AUTO)/rust $(DEST_AUTO)/cargo \ $(DEST_IMPORT) $(DEST_IMPORT)/dist \ - $(DEST_PLUG) $(DEST_TUTOR) $(DEST_SPELL) $(DEST_COMP) + $(DEST_PLUG) $(DEST_TUTOR) $(DEST_TUTOR)/en $(DEST_SPELL) $(DEST_COMP) -$(SHELL) ./installman.sh install $(DEST_MAN) "" $(INSTALLMANARGS) # Generate the help tags with ":helptags" to handle all languages. # Move the distributed tags file aside and restore it, to avoid it being @@ -2473,8 +2473,10 @@ installgtutorbin: $(DEST_BIN) installtutor: $(DEST_RT) $(DEST_TUTOR) -$(INSTALL_DATA) $(TUTORSOURCE)/README* $(TUTORSOURCE)/tutor* $(DEST_TUTOR) + -$(INSTALL_DATA) $(TUTORSOURCE)/en/* $(DEST_TUTOR)/en/ -rm -f $(DEST_TUTOR)/*.info chmod $(HELPMOD) $(DEST_TUTOR)/* + chmod $(DIRMOD) $(DEST_TUTOR)/en # Install the spell files, if they exist. This assumes at least the English # spell file is there. @@ -2671,7 +2673,8 @@ $(DESTDIR)$(exec_prefix) $(DEST_BIN) \ $(DEST_SYN)/modula2 $(DEST_SYN)/modula2/opt \ $(DEST_IND) $(DEST_FTP) \ $(DEST_LANG) $(DEST_KMAP) $(DEST_COMP) $(DEST_MACRO) \ - $(DEST_PACK) $(DEST_TOOLS) $(DEST_TUTOR) $(DEST_SPELL) \ + $(DEST_PACK) $(DEST_TOOLS) $(DEST_TUTOR) $(DEST_TUTOR)/en \ + $(DEST_SPELL) \ $(DEST_AUTO) $(DEST_AUTO)/dist $(DEST_AUTO)/xml \ $(DEST_AUTO)/cargo $(DEST_AUTO)/rust \ $(DEST_IMPORT) $(DEST_IMPORT)/dist $(DEST_PLUG): @@ -2854,6 +2857,7 @@ uninstall_runtime: -rm -f $(DEST_IND)/*.vim $(DEST_IND)/README.txt -rm -rf $(DEST_MACRO) -rm -rf $(DEST_PACK) + -rm -rf $(DEST_TUTOR)/en -rm -rf $(DEST_TUTOR) -rm -rf $(DEST_SPELL) -rm -rf $(DEST_TOOLS) diff --git a/src/version.c b/src/version.c index b39cf1e92e..43c77a21f0 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 */ +/**/ + 836, /**/ 835, /**/ From 17c71daf83f45c3ee81a33716e56e1b485e76a8b Mon Sep 17 00:00:00 2001 From: Paul Desmond Parker Date: Sun, 3 Nov 2024 20:47:53 +0100 Subject: [PATCH 021/106] runtime(vimtutor): Add a second chapter fixes: #5719 closes: #5729 Signed-off-by: Paul Desmond Parker Signed-off-by: Christian Brabandt --- runtime/doc/usr_01.txt | 7 +- runtime/doc/version9.txt | 1 + runtime/doc/vimtutor.1 | 99 ++++++++++++++---- runtime/doc/vimtutor.man | 80 +++++++++++---- runtime/tutor/tutor | 11 +- runtime/tutor/tutor.vim | 9 +- runtime/tutor/tutor2 | 199 +++++++++++++++++++++++++++++++++++++ runtime/tutor/tutor2.utf-8 | 199 +++++++++++++++++++++++++++++++++++++ src/vimtutor | 128 ++++++++++++++++++++++-- vimtutor.bat | 7 +- 10 files changed, 684 insertions(+), 56 deletions(-) create mode 100644 runtime/tutor/tutor2 create mode 100644 runtime/tutor/tutor2.utf-8 diff --git a/runtime/doc/usr_01.txt b/runtime/doc/usr_01.txt index 9902691bad..604e26bfec 100644 --- a/runtime/doc/usr_01.txt +++ b/runtime/doc/usr_01.txt @@ -120,8 +120,11 @@ On Unix, if Vim has been properly installed, you can start it from the shell: On MS-Windows you can find it in the Program/Vim menu. Or execute vimtutor.bat in the $VIMRUNTIME directory. -This will make a copy of the tutor file, so that you can edit it without -the risk of damaging the original. +This will make a copy of chapter 1 tutor file, so that you can edit it without +the risk of damaging the original. To continue with chapter 2, you can use +the following command: > + vimtutor -c 2 +< There are a few translated versions of the tutor. To find out if yours is available, use the two-letter language code. For French: > diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index d016ccfb1b..999a09cfc1 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -41605,6 +41605,7 @@ Changed~ - the |help-TOC| package is included to ease navigating the documentation. - an interactive tutor plugin has been included |vim-tutor-mode|, can be started via |:Tutor| +- improve the |vimtutor| and add a second chapter for more advanced tips *added-9.2* Added ~ diff --git a/runtime/doc/vimtutor.1 b/runtime/doc/vimtutor.1 index a71bc02858..3d3f32b70b 100644 --- a/runtime/doc/vimtutor.1 +++ b/runtime/doc/vimtutor.1 @@ -1,16 +1,18 @@ -.TH VIMTUTOR 1 "2024 August 12" +.TH VIMTUTOR 1 "2024 November 03" .SH NAME vimtutor \- the Vim tutor .SH SYNOPSIS .br -.B vimtutor [\-g] [language] +.B vimtutor [\-l | \-\-language ISO639] [\-c | \-\-chapter NUMBER] [\-g | \-\-gui] [ISO639] +.br +.B vimtutor [\-h | \-\-help] +.br +.B vimtutor [\-\-list] .SH DESCRIPTION .B Vimtutor starts the .B Vim tutor. -It copies the tutor file first, so that it can be modified without changing -the original file. .PP The .B Vimtutor @@ -28,34 +30,91 @@ be used. If a tutor in this language is available, it will be used. Otherwise the English version will be used. .PP +.B Vimtutor +only opens temporary copies of the original tutor files, there is no danger of overwriting the lessons. +.PP .B Vim -is always started in Vi compatible mode. +is always started in +.B Vi +compatible mode. +.SH OPTIONS +.TP +.BR \-l ", " \-\-language =\fIISO639\fR +Set the two or three letter language code. E.g. 'it', 'es', 'bar'. Defaults to language of locale if available, else to English. +.TP +.BR \-c ", " \-\-chapter =\fINUMBER\fR +Set the one or two digit chapter number. Defaults to chapter one. +.TP +.BR \-g ", " \-\-gui +Start +.B vimtutor +in the GUI version of vim if available, otherwise fallback to console vim. +.TP +.BR \-h ", " \-\-help +Display usage information. +.TP +.BR \-\-list +Display chapters and languages. +.SH EXAMPLES +To start +.B vimtutor +in German on chapter one: +.PP +.nf +.RS +vimtutor de +.RE +.fi +.PP +In English on chapter two: +.PP +.nf +.RS +vimtutor -c2 +.RE +.fi +.PP +Longform command for Bavarian in the GUI on chapter one: +.PP +.nf +.RS +vimtutor --language bar --chapter 1 --gui +.RE +.fi .SH FILES .TP 15 /usr/local/share/vim/vim??/tutor/tutor[.language] The .B Vimtutor -text file(s). -.br -.I vim?? -is short version number, like vim91 for -.B Vim 9.1 +chapter one text file(s). +.TP 15 +/usr/local/share/vim/vim??/tutor/tutor02[.language] +The +.B Vimtutor +chapter two text file(s). .TP 15 /usr/local/share/vim/vim??/tutor/tutor.vim -The Vim script used to copy the +The +.B Vim +script used to copy the .B Vimtutor -text file. -.SH AUTHOR +chapter one text file. +.TP 15 +/usr/local/share/vim/vim??/tutor/tutor02.vim The +.B Vim +script used to copy the .B Vimtutor -was originally written for Vi by Michael C. Pierce and Robert K. Ware, -Colorado School of Mines using ideas supplied by Charles Smith, -Colorado State University. -E-mail: bware@mines.colorado.edu (now invalid). -.br -It was modified for +chapter two text file. +.SH AUTHOR +.B The Vi Tutorial +was originally written for Vi by Michael C. Pierce and Robert K. Ware, Colorado School of Mines using ideas supplied by Charles Smith, Colorado State University. +.B E-mail: bware@mines.colorado.edu. +.PP +Modified for .B Vim by Bram Moolenaar. -For the names of the translators see the tutor files. +.PP +Translation contributors are listed in the tutor files. .SH SEE ALSO vim(1) diff --git a/runtime/doc/vimtutor.man b/runtime/doc/vimtutor.man index f1e113e2b5..459542e304 100644 --- a/runtime/doc/vimtutor.man +++ b/runtime/doc/vimtutor.man @@ -1,16 +1,16 @@ VIMTUTOR(1) General Commands Manual VIMTUTOR(1) - - NAME vimtutor - the Vim tutor SYNOPSIS - vimtutor [-g] [language] + vimtutor [-l | --language ISO639] [-c | --chapter NUMBER] [-g | --gui] + [ISO639] + vimtutor [-h | --help] + vimtutor [--list] DESCRIPTION - Vimtutor starts the Vim tutor. It copies the tutor file first, so that - it can be modified without changing the original file. + Vimtutor starts the Vim tutor. The Vimtutor is useful for people that want to learn their first Vim commands. @@ -21,31 +21,73 @@ DESCRIPTION The optional [language] argument is the two-letter name of a language, like "it" or "es". If the [language] argument is missing, the language - of the current locale will be used. If a tutor in this language is - available, it will be used. Otherwise the English version will be + of the current locale will be used. If a tutor in this language is + available, it will be used. Otherwise the English version will be used. + Vimtutor only opens temporary copies of the original tutor files, there + is no danger of overwriting the lessons. + Vim is always started in Vi compatible mode. +OPTIONS + -l, --language=ISO639 + Set the two or three letter language code. E.g. 'it', 'es', + 'bar'. Defaults to language of locale if available, else to Eng‐ + lish. + + -c, --chapter=NUMBER + Set the one or two digit chapter number. Defaults to chapter + one. + + -g, --gui + Start vimtutor in the GUI version of vim if available, otherwise + fallback to console vim. + + -h, --help + Display usage information. + + --list Display chapters and languages. + +EXAMPLES + To start vimtutor in German on chapter one: + + vimtutor de + + In English on chapter two: + + vimtutor -c2 + + Longform command for Bavarian in the GUI on chapter one: + + vimtutor --language bar --chapter 1 --gui + FILES /usr/local/share/vim/vim??/tutor/tutor[.language] - The Vimtutor text file(s). - vim?? is short version number, like vim91 for Vim 9.1 + The Vimtutor chapter one text file(s). + + /usr/local/share/vim/vim??/tutor/tutor02[.language] + The Vimtutor chapter two text file(s). /usr/local/share/vim/vim??/tutor/tutor.vim - The Vim script used to copy the Vimtutor text file. + The Vim script used to copy the Vimtutor chapter one + text file. + + /usr/local/share/vim/vim??/tutor/tutor02.vim + The Vim script used to copy the Vimtutor chapter two + text file. AUTHOR - The Vimtutor was originally written for Vi by Michael C. Pierce and - Robert K. Ware, Colorado School of Mines using ideas supplied by - Charles Smith, Colorado State University. E-mail: bware@mines.col‐ - orado.edu (now invalid). - It was modified for Vim by Bram Moolenaar. For the names of the trans‐ - lators see the tutor files. + The Vi Tutorial was originally written for Vi by Michael C. Pierce and + Robert K. Ware, Colorado School of Mines using ideas supplied by + Charles Smith, Colorado State University. E-mail: bware@mines.col‐ + orado.edu. -SEE ALSO - vim(1) + Modified for Vim by Bram Moolenaar. + Translation contributors are listed in the tutor files. +SEE ALSO + vim(1) - 2024 August 12 VIMTUTOR(1) + 2024 November 03 VIMTUTOR(1) diff --git a/runtime/tutor/tutor b/runtime/tutor/tutor index 3df15f1a1d..3ddcda1614 100644 --- a/runtime/tutor/tutor +++ b/runtime/tutor/tutor @@ -945,10 +945,13 @@ NOTE: Completion works for many commands. Just try pressing CTRL-D and ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - This concludes the Vim Tutor. It was intended to give a brief overview of - the Vim editor, just enough to allow you to use the editor fairly easily. - It is far from complete as Vim has many many more commands. Read the user - manual next: ":help user-manual". + This concludes Chapter 1 of the Vim Tutor. Consider continuing with Chapter 2. + + It was intended to give a brief overview of the Vim editor, just enough to + allow you to use the editor fairly easily. It is far from complete as Vim + has many many more commands. + + Read the user manual next: ":help user-manual". For further reading and studying, this book is recommended: Vim - Vi Improved - by Steve Oualline diff --git a/runtime/tutor/tutor.vim b/runtime/tutor/tutor.vim index 809fd1d126..551231ab42 100644 --- a/runtime/tutor/tutor.vim +++ b/runtime/tutor/tutor.vim @@ -180,8 +180,13 @@ if &enc == 'utf-8' && s:ext !~ '\.utf-8' let s:ext .= '.utf-8' endif -" 2. Build the name of the file: -let s:tutorfile = "/tutor/tutor" +" 2. Build the name of the file and chapter +let s:chapter = exists("$CHAPTER") ? $CHAPTER : '' +if s:chapter == "1" + let s:chapter = '' +endif + +let s:tutorfile = "/tutor/tutor" . s:chapter let s:tutorxx = $VIMRUNTIME . s:tutorfile . s:ext " 3. Finding the file: diff --git a/runtime/tutor/tutor2 b/runtime/tutor/tutor2 new file mode 100644 index 0000000000..eaeef40035 --- /dev/null +++ b/runtime/tutor/tutor2 @@ -0,0 +1,199 @@ +=============================================================================== += W e l c o m e t o t h e V I M T u t o r - Version 1.7 = +=============================================================================== += = += C h a p t e r - T w o = += = +=============================================================================== + + Hic Sunt Dracones: if this is your first exposure to vim and you + intended to avail yourself of the introductory chapter, kindly type + :q and try again. + + The approximate time required to complete this chapter is 8-10 minutes, + depending upon how much time is spent with experimentation. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Lesson 2.1.1: THE NAMED REGISTERS + + + ** Store two yanked words concurrently and then paste them ** + + 1. Move the cursor to the line below marked ---> + + 2. Navigate to any point on the word 'Edward' and type "ayiw + +MNEMONIC: into register(") named (a) (y)ank (i)nner (w)ord + + 3. Navigate forward to the word 'cookie' (fk or 2fc or $2b or /co) + and type "byiw + + 4. Navigate to any point on the word 'Vince' and type ciwa + +MNEMONIC: (c)hange (i)nner (w)ord with named (a) + + 5. Navigate to any point on the word 'cake' and type ciwb + +---> a) Edward will henceforth be in charge of the cookie rations + b) In this capacity, Vince will have sole cake discretionary powers + +NOTE: Delete also works into registers, i.e. "sdiw will delete the word under + the cursor into register s. + +REFERENCE: Registers :h registers + Named Registers :h quotea + Motion :h motion.txt /inner + CTRL-R :h insert /CTRL-R + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Lesson 2.1.2: THE EXPRESSION REGISTER + + + ** Insert the results of calculations on the fly ** + + 1. Move the cursor to the line below marked ---> + + 2. Navigate to any point on the supplied number + + 3. Type ciw=60*60*24 + + 4. On the next line, enter insert mode and add today's date with + =system('date') + +NOTE: All calls to system are OS dependent, e.g. on Windows use + system('date /t') or :r!date /t + +---> I have forgotten the exact number of seconds in a day, is it 84600? + Today's date is: + +NOTE: the same can be achieved with :pu=system('date') + or, with fewer keystrokes :r!date + +REFERENCE: Expression Register :h quote= + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Lesson 2.1.3: THE NUMBERED REGISTERS + + + ** Press yy and dd to witness their effect on the registers ** + + 1. Move the cursor to the line below marked ---> + + 2. yank the zeroth line, then inspect registers with :reg + + 3. delete line 0. with "cdd, then inspect registers + (Where do you expect line 0 to be?) + + 4. continue deleting each successive line, inspecting :reg as you go + +NOTE: You should notice that old full-line deletions move down the list + as new full-line deletions are added + + 5. Now (p)aste the following registers in order; c, 7, 4, 8, 2. i.e. "7p + +---> 0. This + 9. wobble + 8. secret + 7. is + 6. on + 5. axis + 4. a + 3. war + 2. message + 1. tribute + +NOTE: Whole line deletions (dd) are much longer lived in the numbered registers + than whole line yanks, or deletions involving smaller movements + +REFERENCE: Numbered Registers :h quote0 + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Lesson 2.1.4: THE BEAUTY OF MARKS + + + ** Code monkey arithmetic avoidance ** + +NOTE: a common conundrum when coding is moving around large chunks of code. + The following technique helps avoid number line calculations associated + with operatins like "a147d or :945,1091d a or even worse using + i=1091-945 first + + 1. Move the cursor to the line below marked ---> + + 2. Go to the first line of the function and mark it with ma + +NOTE: exact position on line is NOT important! + + 3. Navigate to the end of the line and then the end of the code block + with $% + + 4. Delete the block into register a with "ad'a + +MNEMONIC: into register(") named (a) put the (d)eletion from the cursor to the + LINE containing mark(') (a) + + 5. Paste the block between BBB and CCC "ap + +NOTE: practice this operation multiple times to become fluent ma$%"ad'a + +---> AAA + function itGotRealBigRealFast() { + if ( somethingIsTrue ) { + doIt() + } + // the taxonomy of our function has changed and it + // no longer makes alphabetical sense in it's current position + + // imagine hundreds of lines of code + + // naively you could navigate to the start and end and record or + // remember each line number + } + BBB + CCC + +NOTE: marks and registers do not share a namespace, therefore register a is + completely independent of mark a. This is not true of registers and + macros. + +REFERENCE: Marks :h marks + Mark Motions :h mark-motions (difference between ' and `) + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Lesson 2.1 SUMMARY + + + 1. To store (yank, delete) text into, and retrieve (paste) from, a total of + 26 registers (a-z) + 2. Yank a whole word from anywhere within a word: yiw + 3. Change a whole word from anywhere within a word: ciw + 4. Insert text directly from registers in insert mode: (C-r)a + + 5. Insert the results of simple arithmetic operations: (C-r)=60*60 + in insert mode + 6. Insert the results of system calls: (C-r)=system('ls -1') + in insert mode + + 7. Inspect registers with :reg + 8. Learn the final destination of whole line deletions: dd in the numbered + registers, i.e. descending from register 1 - 9. Appreciate that whole + line deletions are preserved in the numbered registers longer than any + other operation + 9. Learn the final destination of all yanks in the numbered registers and + how ephemeral they are + + 10. Place marks from command mode m[a-zA-Z0-9] + 11. Move line-wise to a mark with ' + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This concludes chapter two of the Vim Tutor. It is a work in progress. + + This chapter was written by Paul D. Parker. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/runtime/tutor/tutor2.utf-8 b/runtime/tutor/tutor2.utf-8 new file mode 100644 index 0000000000..eaeef40035 --- /dev/null +++ b/runtime/tutor/tutor2.utf-8 @@ -0,0 +1,199 @@ +=============================================================================== += W e l c o m e t o t h e V I M T u t o r - Version 1.7 = +=============================================================================== += = += C h a p t e r - T w o = += = +=============================================================================== + + Hic Sunt Dracones: if this is your first exposure to vim and you + intended to avail yourself of the introductory chapter, kindly type + :q and try again. + + The approximate time required to complete this chapter is 8-10 minutes, + depending upon how much time is spent with experimentation. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Lesson 2.1.1: THE NAMED REGISTERS + + + ** Store two yanked words concurrently and then paste them ** + + 1. Move the cursor to the line below marked ---> + + 2. Navigate to any point on the word 'Edward' and type "ayiw + +MNEMONIC: into register(") named (a) (y)ank (i)nner (w)ord + + 3. Navigate forward to the word 'cookie' (fk or 2fc or $2b or /co) + and type "byiw + + 4. Navigate to any point on the word 'Vince' and type ciwa + +MNEMONIC: (c)hange (i)nner (w)ord with named (a) + + 5. Navigate to any point on the word 'cake' and type ciwb + +---> a) Edward will henceforth be in charge of the cookie rations + b) In this capacity, Vince will have sole cake discretionary powers + +NOTE: Delete also works into registers, i.e. "sdiw will delete the word under + the cursor into register s. + +REFERENCE: Registers :h registers + Named Registers :h quotea + Motion :h motion.txt /inner + CTRL-R :h insert /CTRL-R + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Lesson 2.1.2: THE EXPRESSION REGISTER + + + ** Insert the results of calculations on the fly ** + + 1. Move the cursor to the line below marked ---> + + 2. Navigate to any point on the supplied number + + 3. Type ciw=60*60*24 + + 4. On the next line, enter insert mode and add today's date with + =system('date') + +NOTE: All calls to system are OS dependent, e.g. on Windows use + system('date /t') or :r!date /t + +---> I have forgotten the exact number of seconds in a day, is it 84600? + Today's date is: + +NOTE: the same can be achieved with :pu=system('date') + or, with fewer keystrokes :r!date + +REFERENCE: Expression Register :h quote= + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Lesson 2.1.3: THE NUMBERED REGISTERS + + + ** Press yy and dd to witness their effect on the registers ** + + 1. Move the cursor to the line below marked ---> + + 2. yank the zeroth line, then inspect registers with :reg + + 3. delete line 0. with "cdd, then inspect registers + (Where do you expect line 0 to be?) + + 4. continue deleting each successive line, inspecting :reg as you go + +NOTE: You should notice that old full-line deletions move down the list + as new full-line deletions are added + + 5. Now (p)aste the following registers in order; c, 7, 4, 8, 2. i.e. "7p + +---> 0. This + 9. wobble + 8. secret + 7. is + 6. on + 5. axis + 4. a + 3. war + 2. message + 1. tribute + +NOTE: Whole line deletions (dd) are much longer lived in the numbered registers + than whole line yanks, or deletions involving smaller movements + +REFERENCE: Numbered Registers :h quote0 + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Lesson 2.1.4: THE BEAUTY OF MARKS + + + ** Code monkey arithmetic avoidance ** + +NOTE: a common conundrum when coding is moving around large chunks of code. + The following technique helps avoid number line calculations associated + with operatins like "a147d or :945,1091d a or even worse using + i=1091-945 first + + 1. Move the cursor to the line below marked ---> + + 2. Go to the first line of the function and mark it with ma + +NOTE: exact position on line is NOT important! + + 3. Navigate to the end of the line and then the end of the code block + with $% + + 4. Delete the block into register a with "ad'a + +MNEMONIC: into register(") named (a) put the (d)eletion from the cursor to the + LINE containing mark(') (a) + + 5. Paste the block between BBB and CCC "ap + +NOTE: practice this operation multiple times to become fluent ma$%"ad'a + +---> AAA + function itGotRealBigRealFast() { + if ( somethingIsTrue ) { + doIt() + } + // the taxonomy of our function has changed and it + // no longer makes alphabetical sense in it's current position + + // imagine hundreds of lines of code + + // naively you could navigate to the start and end and record or + // remember each line number + } + BBB + CCC + +NOTE: marks and registers do not share a namespace, therefore register a is + completely independent of mark a. This is not true of registers and + macros. + +REFERENCE: Marks :h marks + Mark Motions :h mark-motions (difference between ' and `) + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Lesson 2.1 SUMMARY + + + 1. To store (yank, delete) text into, and retrieve (paste) from, a total of + 26 registers (a-z) + 2. Yank a whole word from anywhere within a word: yiw + 3. Change a whole word from anywhere within a word: ciw + 4. Insert text directly from registers in insert mode: (C-r)a + + 5. Insert the results of simple arithmetic operations: (C-r)=60*60 + in insert mode + 6. Insert the results of system calls: (C-r)=system('ls -1') + in insert mode + + 7. Inspect registers with :reg + 8. Learn the final destination of whole line deletions: dd in the numbered + registers, i.e. descending from register 1 - 9. Appreciate that whole + line deletions are preserved in the numbered registers longer than any + other operation + 9. Learn the final destination of all yanks in the numbered registers and + how ephemeral they are + + 10. Place marks from command mode m[a-zA-Z0-9] + 11. Move line-wise to a mark with ' + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This concludes chapter two of the Vim Tutor. It is a work in progress. + + This chapter was written by Paul D. Parker. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/vimtutor b/src/vimtutor index 3b154f2883..3faf100b4d 100755 --- a/src/vimtutor +++ b/src/vimtutor @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Start Vim on a copy of the tutor file. @@ -13,15 +13,126 @@ # have Vim installed with its version number. # We anticipate up to a future Vim 8.1 version :-). seq="vim vim81 vim80 vim8 vim74 vim73 vim72 vim71 vim70 vim7 vim6 vi" -if test "$1" = "-g"; then - # Try to use the GUI version of Vim if possible, it will fall back - # on Vim if Gvim is not installed. - seq="gvim gvim81 gvim80 gvim8 gvim74 gvim73 gvim72 gvim71 gvim70 gvim7 gvim6 $seq" + +usage() +{ + echo "==USAGE=========================================================================================" + echo "${0##*/} [-(-l)anguage ISO639] [-(-c)hapter) NUMBER] [-(-g)ui] | [-(-h)elp] | [--list]" + printf "\twhere:\n" + printf "\t\tISO639 (default=en) is a 2 or 3 character language code\n" + printf "\t\tNUMBER (default=01) is one or two digits representing the chapter number\n" + printf "\texamples:\n" + printf "\t\tvimtutor -l es -c 2 -g\n" + printf "\t\tvimtutor --language de --chapter 02\n" + printf "\t\tvimtutor fr\n" + echo "More information at 'man vimtutor'" + echo "================================================================================================" +} + +listOptions() +{ + declare -A language + language[bar]=Bavarian + language[bg]=Bulgarian + language[ca]=Catalan + language[cs]=Czech + language[da]=Danish + language[de]=German + language[el]=Greek + language[en]=English\(default\) + language[eo]=Esperanto + language[es]=Spanish + language[fr]=French + language[hr]=Croatian + language[hu]=Hungarian + language[it]=Italian + language[ja]=Japanese + language[ko]=Korean + language[lv]=Latvian + language[nb]=Bokmål + language[nl]=Dutch + language[no]=Norwegian + language[pl]=Polish + language[pt]=Portuguese + language[ru]=Russian + language[sk]=Slovak + language[sr]=Serbian + language[sv]=Swedish + language[tr]=Turkish + language[uk]=English + language[vi]=Vietnamese + language[zh]=Chinese + + echo "==OPTIONS=======================================================================================" + echo "Chapter: 1" + for code in bar bg ca cs da de el en eo es fr hr hu it ja ko lv nb nl no pl pt ru sk sr sv tr uk vi zh + do + printf "\tLang: %s => %s\n" ${code} ${language[${code}]} + done + echo "Chapter: 2" + for code in en + do + printf "\tLang: %s => %s\n" ${code} ${language[${code}]} + done + echo "================================================================================================" +} + +validateLang() +{ + if [[ $xx =~ ^[^a-z]*$ ]]; then echo "Error: iso639 code must contain only [a-z]" && exit 1; fi + if [ ${#xx} == 2 ] || [ ${#xx} == 3 ]; then :; else echo "Error: iso639 code must be 2 or 3 characters only" && exit 1; fi + export xx +} + +validateChapter() +{ + if [[ $cc =~ ^[0-9]*$ ]]; then :; else echo "Error: chapter argument must contain digits only" && exit 1; fi + if [ $cc == "0" ]; then echo "Error: chapter must be non-zero" && exit 1; fi + if [ $cc == "00" ]; then echo "Error: chapter must be non-zero" && exit 1; fi + export CHAPTER="$cc" +} + +shopt -s extglob +while [ "$1" != "" ]; do + case $1 in + -g | --gui ) seq="gvim gvim91 gvim90 gvim81 gvim80 gvim8 gvim74 gvim73 gvim72 gvim71 gvim70 gvim7 gvim6 $seq" + ;; + -l | --language ) shift + xx=$1 + validateLang + ;; + -l[a-z][a-z]?([a-z]) ) xx=${1#*l} + validateLang + ;; + --language[a-z][a-z]?([a-z]) ) xx=${1#*e} + validateLang + ;; + [a-z][a-z]?([a-z]) ) xx=$1 + validateLang + ;; + -c | --chapter ) shift + cc=$1 + validateChapter + ;; + -c[0-9]?([0-9]) ) cc=${1#*c} + validateChapter + ;; + --chapter[0-9]?([0-9]) ) cc=${1#*r} + validateChapter + ;; + -h | --help ) usage + exit + ;; + --list ) listOptions + exit + ;; + "" ) ;; + * ) usage + exit 1 + esac shift -fi +done -xx=$1 -export xx # We need a temp file for the copy. First try using a standard command. tmp="${TMPDIR-/tmp}" @@ -68,6 +179,7 @@ fi # Use Vim to copy the tutor, it knows the value of $VIMRUNTIME # The script tutor.vim tells Vim which file to copy + $VIM -f -u NONE -c 'so $VIMRUNTIME/tutor/tutor.vim' # Start vim without any .vimrc, set 'nocompatible' and 'showcmd' diff --git a/vimtutor.bat b/vimtutor.bat index da0940a34c..6695ee397f 100644 --- a/vimtutor.bat +++ b/vimtutor.bat @@ -1,7 +1,7 @@ :: Start Vim on a copy of the tutor file. @echo off -:: Usage: vimtutor [-console] [xx] +:: Usage: vimtutor [-chapter 2] [-console] [xx] :: :: -console means gvim will not be used :: xx is a language code like "es" or "nl". @@ -25,6 +25,11 @@ GOTO end :dir_ok +IF .%1==.-chapter ( + SET CHAPTER=%2 + SHIFT + SHIFT +) SET xx=%1 IF NOT .%1==.-console GOTO use_gui From 2cf145b78b888fa03d3b26280fcd405b3c946bef Mon Sep 17 00:00:00 2001 From: Jonas Sortie Termansen Date: Sun, 3 Nov 2024 20:58:21 +0100 Subject: [PATCH 022/106] patch 9.1.0837: cross-compiling has some issues Problem: Cross-compiling to good modern operating systems is difficult as configure assumes obscure bugs are present by default. However, most core autoconf-based packages today assume features work when in doubt, making cross-compilation easier. Solution: Assume features work by default and continue to issue a warning with the appropriate cache variable. This solution shifts the burden onto the users of rare buggy operating systems and makes cross-compilation work out of the box for everyone else. The vim_cv_terminfo test was accidentally negated, where the yes case was in the error handler, leading to false positives if the test program failed to compile. Split the timer_create detection into two phases: First locating the the library containing timer_create, and then another check to check if timer_create works to properly support cross-compilation. Signed-off-by: Jonas 'Sortie' Termansen Signed-off-by: Christian Brabandt --- src/auto/configure | 152 ++++++++++++++++++++++++++++----------------- src/configure.ac | 110 +++++++++++++++++--------------- src/version.c | 2 + 3 files changed, 157 insertions(+), 107 deletions(-) diff --git a/src/auto/configure b/src/auto/configure index 4a99071c84..db8a89ba03 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -11328,7 +11328,9 @@ else $as_nop if test "$cross_compiling" = yes then : - as_fn_error $? "cross-compiling: please set 'vim_cv_toupper_broken'" "$LINENO" 5 + vim_cv_toupper_broken=no + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_toupper_broken'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_toupper_broken'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -12746,7 +12748,7 @@ fi if test "x$olibs" != "x$LIBS"; then if test "$cross_compiling" = yes then : - res="FAIL" + res="OK" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -12822,7 +12824,9 @@ else $as_nop if test "$cross_compiling" = yes then : - as_fn_error $? "cross-compiling: please set 'vim_cv_terminfo'" "$LINENO" 5 + vim_cv_terminfo=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_terminfo'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_terminfo'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -12840,17 +12844,17 @@ else $as_nop # include #endif int main() -{char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(!strcmp(s==0 ? "" : s, "1")); } +{char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(!!strcmp(s==0 ? "" : s, "1")); } _ACEOF if ac_fn_c_try_run "$LINENO" then : - vim_cv_terminfo=no + vim_cv_terminfo=yes else $as_nop - vim_cv_terminfo=yes + vim_cv_terminfo=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -12877,7 +12881,9 @@ else $as_nop if test "$cross_compiling" = yes then : - as_fn_error $? "failed to compile test program." "$LINENO" 5 + vim_cv_tgetent=zero + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_tgetent'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_tgetent'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -13253,7 +13259,9 @@ else $as_nop if test "$cross_compiling" = yes then : - as_fn_error $? "cross-compiling: please set 'vim_cv_getcwd_broken'" "$LINENO" 5 + vim_cv_getcwd_broken=no + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_getcwd_broken'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_getcwd_broken'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -14149,50 +14157,29 @@ then : printf %s "(cached) " >&6 else $as_nop -if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: failed to build test program; if cross-compiling please set 'vim_cv_timer_create'" >&5 -printf "%s\n" "$as_me: WARNING: failed to build test program; if cross-compiling please set 'vim_cv_timer_create'" >&2;} - -else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if STDC_HEADERS -# include -# include -#endif -#include -#include -static void set_flag(union sigval sv) {} + #include int main (void) { - struct timespec ts; - struct sigevent action = {0}; - timer_t timer_id; - - action.sigev_notify = SIGEV_THREAD; - action.sigev_notify_function = set_flag; - if (timer_create(CLOCK_MONOTONIC, &action, &timer_id) < 0) - exit(1); // cannot create a monotonic timer + timer_create(CLOCK_MONOTONIC, NULL, NULL); ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" +if ac_fn_c_try_compile "$LINENO" then : vim_cv_timer_create=yes else $as_nop vim_cv_timer_create=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $vim_cv_timer_create" >&5 printf "%s\n" "$vim_cv_timer_create" >&6; } @@ -14203,14 +14190,60 @@ if test "x$vim_cv_timer_create" = "xno" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for timer_create with -lrt" >&5 printf %s "checking for timer_create with -lrt... " >&6; } if test ${vim_cv_timer_create_with_lrt+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + +int +main (void) +{ + + timer_create(CLOCK_MONOTONIC, NULL, NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + vim_cv_timer_create_with_lrt=yes +else $as_nop + vim_cv_timer_create_with_lrt=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $vim_cv_timer_create_with_lrt" >&5 +printf "%s\n" "$vim_cv_timer_create_with_lrt" >&6; } + LIBS="$save_LIBS" +else + vim_cv_timer_create_with_lrt=no +fi + +if test "x$vim_cv_timer_create" = "xyes" || + test "x$vim_cv_timer_create_with_lrt" = "xyes"; then + save_LIBS="$LIBS" + if test "x$vim_cv_timer_create_works" = "xyes" ; then + LIBS="$LIBS -lrt" + fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if timer_create works" >&5 +printf %s "checking if timer_create works... " >&6; } +if test ${vim_cv_timer_create_works+y} then : printf %s "(cached) " >&6 else $as_nop if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: failed to build test program; if cross-compiling please set 'vim_cv_timer_create_with_lrt'" >&5 -printf "%s\n" "$as_me: WARNING: failed to build test program; if cross-compiling please set 'vim_cv_timer_create_with_lrt'" >&2;} + vim_cv_timer_create_works=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_timer_create_works'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_timer_create_works'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -14235,7 +14268,7 @@ main (void) action.sigev_notify = SIGEV_THREAD; action.sigev_notify_function = set_flag; if (timer_create(CLOCK_MONOTONIC, &action, &timer_id) < 0) - exit(1); // cannot create a monotonic timer + exit(1); // cannot create a monotonic timer ; return 0; @@ -14243,30 +14276,25 @@ main (void) _ACEOF if ac_fn_c_try_run "$LINENO" then : - vim_cv_timer_create_with_lrt=yes + vim_cv_timer_create_works=yes else $as_nop - vim_cv_timer_create_with_lrt=no + vim_cv_timer_create_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $vim_cv_timer_create_with_lrt" >&5 -printf "%s\n" "$vim_cv_timer_create_with_lrt" >&6; } - LIBS="$save_LIBS" -else - vim_cv_timer_create_with_lrt=no -fi - -if test "x$vim_cv_timer_create" = "xyes" ; then - printf "%s\n" "#define HAVE_TIMER_CREATE 1" >>confdefs.h +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $vim_cv_timer_create_works" >&5 +printf "%s\n" "$vim_cv_timer_create_works" >&6; } -fi -if test "x$vim_cv_timer_create_with_lrt" = "xyes" ; then - printf "%s\n" "#define HAVE_TIMER_CREATE 1" >>confdefs.h + if test "x$vim_cv_timer_create_works" = "xyes" ; then + printf "%s\n" "#define HAVE_TIMER_CREATE 1" >>confdefs.h - LIBS="$LIBS -lrt" + LIBS="$LIBS -lrt" + else + LIBS="$save_LIBS" + fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stat() ignores a trailing slash" >&5 @@ -14279,7 +14307,9 @@ else $as_nop if test "$cross_compiling" = yes then : - as_fn_error $? "cross-compiling: please set 'vim_cv_stat_ignores_slash'" "$LINENO" 5 + vim_cv_stat_ignores_slash=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_stat_ignores_slash'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_stat_ignores_slash'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -15414,8 +15444,8 @@ printf "%s\n" "#define VIM_SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h printf %s "checking uint32_t is 32 bits... " >&6; } if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cannot check uint32_t when cross-compiling." >&5 -printf "%s\n" "$as_me: WARNING: cannot check uint32_t when cross-compiling." >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: assuming uint32_t is correct when cross-compiling" >&5 +printf "%s\n" "$as_me: WARNING: assuming uint32_t is correct when cross-compiling" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15478,7 +15508,9 @@ else $as_nop if test "$cross_compiling" = yes then : - as_fn_error $? "cross-compiling: please set 'vim_cv_memmove_handles_overlap'" "$LINENO" 5 + vim_cv_memmove_handles_overlap=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_memmove_handles_overlap'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_memmove_handles_overlap'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -15518,7 +15550,9 @@ else $as_nop if test "$cross_compiling" = yes then : - as_fn_error $? "cross-compiling: please set 'vim_cv_bcopy_handles_overlap'" "$LINENO" 5 + vim_cv_bcopy_handles_overlap=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_bcopy_handles_overlap'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_bcopy_handles_overlap'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -15558,7 +15592,9 @@ else $as_nop if test "$cross_compiling" = yes then : - as_fn_error $? "cross-compiling: please set 'vim_cv_memcpy_handles_overlap'" "$LINENO" 5 + vim_cv_memcpy_handles_overlap=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: consider setting 'vim_cv_memcpy_handles_overlap'" >&5 +printf "%s\n" "$as_me: WARNING: cross-compiling: consider setting 'vim_cv_memcpy_handles_overlap'" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/src/configure.ac b/src/configure.ac index 233e9077fc..24479d3861 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -3297,7 +3297,8 @@ int main() { exit(toupper('A') == 'A' && tolower('z') == 'z'); } ],[ vim_cv_toupper_broken=no ],[ - AC_MSG_ERROR(cross-compiling: please set 'vim_cv_toupper_broken') + vim_cv_toupper_broken=no + AC_MSG_WARN(cross-compiling: consider setting 'vim_cv_toupper_broken') ])]) if test "x$vim_cv_toupper_broken" = "xyes" ; then @@ -3510,7 +3511,7 @@ else # include #endif int main() {char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(0); }])], - res="OK", res="FAIL", res="FAIL") + res="OK", res="FAIL", res="OK") if test "$res" = "OK"; then break fi @@ -3549,13 +3550,14 @@ AC_CACHE_CHECK([whether we talk terminfo], [vim_cv_terminfo], # include #endif int main() -{char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(!strcmp(s==0 ? "" : s, "1")); } +{char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(!!strcmp(s==0 ? "" : s, "1")); } ]])],[ + vim_cv_terminfo=yes + ],[ vim_cv_terminfo=no ],[ vim_cv_terminfo=yes - ],[ - AC_MSG_ERROR(cross-compiling: please set 'vim_cv_terminfo') + AC_MSG_WARN(cross-compiling: consider setting 'vim_cv_terminfo') ]) ]) @@ -3581,7 +3583,8 @@ int main() ],[ vim_cv_tgetent=non-zero ],[ - AC_MSG_ERROR(failed to compile test program.) + vim_cv_tgetent=zero + AC_MSG_WARN(cross-compiling: consider setting 'vim_cv_tgetent') ]) ]) @@ -3747,7 +3750,8 @@ int main() ],[ vim_cv_getcwd_broken=yes ],[ - AC_MSG_ERROR(cross-compiling: please set 'vim_cv_getcwd_broken') + vim_cv_getcwd_broken=no + AC_MSG_WARN(cross-compiling: consider setting 'vim_cv_getcwd_broken') ]) ]) @@ -3871,30 +3875,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM( AC_MSG_RESULT(no)) dnl Check for timer_create. It probably requires the 'rt' library. -dnl Run the program to find out if timer_create(CLOCK_MONOTONIC) actually -dnl works, on Solaris timer_create() exists but fails at runtime. AC_CACHE_CHECK([for timer_create without -lrt], [vim_cv_timer_create], [ -AC_RUN_IFELSE([AC_LANG_PROGRAM([ -#if STDC_HEADERS -# include -# include -#endif -#include -#include -static void set_flag(union sigval sv) {} -], [ - struct timespec ts; - struct sigevent action = {0}; - timer_t timer_id; - - action.sigev_notify = SIGEV_THREAD; - action.sigev_notify_function = set_flag; - if (timer_create(CLOCK_MONOTONIC, &action, &timer_id) < 0) - exit(1); // cannot create a monotonic timer - ])], - vim_cv_timer_create=yes, - vim_cv_timer_create=no, - AC_MSG_WARN([failed to build test program; if cross-compiling please set 'vim_cv_timer_create']) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ + #include + ], [ + timer_create(CLOCK_MONOTONIC, NULL, NULL); + ])], + vim_cv_timer_create=yes, + vim_cv_timer_create=no )]) dnl If the previous failed, check for timer_create() and linking with -lrt. @@ -3902,6 +3890,29 @@ if test "x$vim_cv_timer_create" = "xno" ; then save_LIBS="$LIBS" LIBS="$LIBS -lrt" AC_CACHE_CHECK([for timer_create with -lrt], [vim_cv_timer_create_with_lrt], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ + #include + ], [ + timer_create(CLOCK_MONOTONIC, NULL, NULL); + ])], + vim_cv_timer_create_with_lrt=yes, + vim_cv_timer_create_with_lrt=no + )]) + LIBS="$save_LIBS" +else + vim_cv_timer_create_with_lrt=no +fi + +dnl Run the program to find out if timer_create(CLOCK_MONOTONIC) actually +dnl works, on Solaris timer_create() exists but fails at runtime. +if test "x$vim_cv_timer_create" = "xyes" || + test "x$vim_cv_timer_create_with_lrt" = "xyes"; then + save_LIBS="$LIBS" + if test "x$vim_cv_timer_create_works" = "xyes" ; then + LIBS="$LIBS -lrt" + fi + + AC_CACHE_CHECK([if timer_create works], [vim_cv_timer_create_works], [ AC_RUN_IFELSE([AC_LANG_PROGRAM([ #if STDC_HEADERS # include @@ -3918,23 +3929,20 @@ if test "x$vim_cv_timer_create" = "xno" ; then action.sigev_notify = SIGEV_THREAD; action.sigev_notify_function = set_flag; if (timer_create(CLOCK_MONOTONIC, &action, &timer_id) < 0) - exit(1); // cannot create a monotonic timer + exit(1); // cannot create a monotonic timer ])], - vim_cv_timer_create_with_lrt=yes, - vim_cv_timer_create_with_lrt=no, - AC_MSG_WARN([failed to build test program; if cross-compiling please set 'vim_cv_timer_create_with_lrt']) + vim_cv_timer_create_works=yes, + vim_cv_timer_create_works=no, + vim_cv_timer_create_works=yes + AC_MSG_WARN([cross-compiling: consider setting 'vim_cv_timer_create_works']) )]) - LIBS="$save_LIBS" -else - vim_cv_timer_create_with_lrt=no -fi -if test "x$vim_cv_timer_create" = "xyes" ; then - AC_DEFINE(HAVE_TIMER_CREATE) -fi -if test "x$vim_cv_timer_create_with_lrt" = "xyes" ; then - AC_DEFINE(HAVE_TIMER_CREATE) - LIBS="$LIBS -lrt" + if test "x$vim_cv_timer_create_works" = "xyes" ; then + AC_DEFINE(HAVE_TIMER_CREATE) + LIBS="$LIBS -lrt" + else + LIBS="$save_LIBS" + fi fi AC_CACHE_CHECK([whether stat() ignores a trailing slash], [vim_cv_stat_ignores_slash], @@ -3953,7 +3961,8 @@ int main() {struct stat st; exit(stat("configure/", &st) != 0); } ],[ vim_cv_stat_ignores_slash=no ],[ - AC_MSG_ERROR(cross-compiling: please set 'vim_cv_stat_ignores_slash') + vim_cv_stat_ignores_slash=yes + AC_MSG_WARN(cross-compiling: consider setting 'vim_cv_stat_ignores_slash') ]) ]) @@ -4320,7 +4329,7 @@ int main() { }])], AC_MSG_RESULT(ok), AC_MSG_ERROR([WRONG! uint32_t not defined correctly.]), -AC_MSG_WARN([cannot check uint32_t when cross-compiling.])) +AC_MSG_WARN([assuming uint32_t is correct when cross-compiling])) dnl Check for memmove() before bcopy(), makes memmove() be used when both are dnl present, fixes problem with incompatibility between Solaris 2.4 and 2.5. @@ -4355,7 +4364,8 @@ AC_CACHE_CHECK([whether memmove handles overlaps],[vim_cv_memmove_handles_overla ],[ vim_cv_memmove_handles_overlap=no ],[ - AC_MSG_ERROR(cross-compiling: please set 'vim_cv_memmove_handles_overlap') + vim_cv_memmove_handles_overlap=yes + AC_MSG_WARN(cross-compiling: consider setting 'vim_cv_memmove_handles_overlap') ]) ]) @@ -4370,7 +4380,8 @@ else ],[ vim_cv_bcopy_handles_overlap=no ],[ - AC_MSG_ERROR(cross-compiling: please set 'vim_cv_bcopy_handles_overlap') + vim_cv_bcopy_handles_overlap=yes + AC_MSG_WARN(cross-compiling: consider setting 'vim_cv_bcopy_handles_overlap') ]) ]) @@ -4385,7 +4396,8 @@ else ],[ vim_cv_memcpy_handles_overlap=no ],[ - AC_MSG_ERROR(cross-compiling: please set 'vim_cv_memcpy_handles_overlap') + vim_cv_memcpy_handles_overlap=yes + AC_MSG_WARN(cross-compiling: consider setting 'vim_cv_memcpy_handles_overlap') ]) ]) diff --git a/src/version.c b/src/version.c index 43c77a21f0..8ca759218e 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 */ +/**/ + 837, /**/ 836, /**/ From c39c0230c420d0c047afcdcdc3a0626c186d2e12 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sun, 3 Nov 2024 21:21:23 +0100 Subject: [PATCH 023/106] Filelist: vimtutor chapter 2 is missing in Filelist Signed-off-by: Christian Brabandt --- Filelist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Filelist b/Filelist index 4fbcc0a2f8..96af57b439 100644 --- a/Filelist +++ b/Filelist @@ -767,6 +767,8 @@ RT_ALL = \ runtime/tutor/tutor.tutor \ runtime/tutor/tutor.tutor.json \ runtime/tutor/tutor.vim \ + runtime/tutor/tutor2 \ + runtime/tutor/tutor2.utf-8 \ runtime/vimrc_example.vim \ runtime/pack/dist/opt/cfilter/plugin/cfilter.vim \ runtime/pack/dist/opt/comment/plugin/comment.vim \ From ac2bb9dfeabc583b33414c50c80d105f480f707f Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Mon, 4 Nov 2024 19:37:24 +0100 Subject: [PATCH 024/106] runtime(doc): add help specific modeline to pi_tutor.txt related: #6414 Signed-off-by: Christian Brabandt --- runtime/doc/pi_tutor.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/runtime/doc/pi_tutor.txt b/runtime/doc/pi_tutor.txt index 7aaafd19ad..0f8479e88f 100644 --- a/runtime/doc/pi_tutor.txt +++ b/runtime/doc/pi_tutor.txt @@ -1,11 +1,11 @@ -*pi_tutor.txt* For Vim version 9.1. Last change: 2024 Nov 02 +*pi_tutor.txt* For Vim version 9.1. Last change: 2024 Nov 03 INTERACTIVE TUTORIALS FOR VIM *vim-tutor-mode* vim-tutor-mode provides a system to follow and create interactive tutorials for vim and third party plugins. It replaces the venerable `vimtutor` system. -============================================================================== +============================================================================= 1. Usage *vim-tutor-usage* vim-tutor-mode tutorials are hypertext documents, they have rich text and @@ -40,7 +40,7 @@ to be detected by the :Tutor command. It is recommended to use a less formal style when writing tutorials than in regular documentation (unless the content requires it). -============================================================================ +============================================================================= 3. Contributing Development of the plugin is done over at github [1]. Feel free to report @@ -48,4 +48,5 @@ issues and make suggestions. [1]: https://github.com/fmoralesc/vim-tutor-mode -" vim: set ft=help : +============================================================================= + vim:tw=78:ts=8:noet:ft=help:norl: From 09cc8c92d158710d8845ec5c83b64af96a0cbe47 Mon Sep 17 00:00:00 2001 From: Aliaksei Budavei <0x000c70@gmail.com> Date: Mon, 4 Nov 2024 19:43:22 +0100 Subject: [PATCH 025/106] patch 9.1.0838: vimtutor is bash-specific Problem: vimtutor is bash-specific (after 17c71daf83f45c3ee8) Solution: port back to POSIX sh (Aliaksei Budavei). Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com> Signed-off-by: Christian Brabandt --- src/version.c | 2 + src/vimtutor | 149 ++++++++++++++++++++++++++------------------------ 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/src/version.c b/src/version.c index 8ca759218e..d213e66a38 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 */ +/**/ + 838, /**/ 837, /**/ diff --git a/src/vimtutor b/src/vimtutor index 3faf100b4d..6e29a76023 100755 --- a/src/vimtutor +++ b/src/vimtutor @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # Start Vim on a copy of the tutor file. @@ -11,8 +11,7 @@ # Vim could be called "vim" or "vi". Also check for "vimN", for people who # have Vim installed with its version number. -# We anticipate up to a future Vim 8.1 version :-). -seq="vim vim81 vim80 vim8 vim74 vim73 vim72 vim71 vim70 vim7 vim6 vi" +seq="vim vim91 vim90 vim81 vim80 vim8 vim74 vim73 vim72 vim71 vim70 vim7 vim6 vi" usage() { @@ -31,94 +30,104 @@ usage() listOptions() { - declare -A language - language[bar]=Bavarian - language[bg]=Bulgarian - language[ca]=Catalan - language[cs]=Czech - language[da]=Danish - language[de]=German - language[el]=Greek - language[en]=English\(default\) - language[eo]=Esperanto - language[es]=Spanish - language[fr]=French - language[hr]=Croatian - language[hu]=Hungarian - language[it]=Italian - language[ja]=Japanese - language[ko]=Korean - language[lv]=Latvian - language[nb]=Bokmål - language[nl]=Dutch - language[no]=Norwegian - language[pl]=Polish - language[pt]=Portuguese - language[ru]=Russian - language[sk]=Slovak - language[sr]=Serbian - language[sv]=Swedish - language[tr]=Turkish - language[uk]=English - language[vi]=Vietnamese - language[zh]=Chinese - - echo "==OPTIONS=======================================================================================" - echo "Chapter: 1" - for code in bar bg ca cs da de el en eo es fr hr hu it ja ko lv nb nl no pl pt ru sk sr sv tr uk vi zh - do - printf "\tLang: %s => %s\n" ${code} ${language[${code}]} - done - echo "Chapter: 2" - for code in en - do - printf "\tLang: %s => %s\n" ${code} ${language[${code}]} - done - echo "================================================================================================" + echo "==OPTIONS=======================================================================================" + echo "Chapter: 1" + printf "\tLang: %-3s => %s\n" \ +bar Bavarian \ +bg Bulgarian \ +ca Catalan \ +cs Czech \ +da Danish \ +de German \ +el Greek \ +en English\(default\) \ +eo Esperanto \ +es Spanish \ +fr French \ +hr Croatian \ +hu Hungarian \ +it Italian \ +ja Japanese \ +ko Korean \ +lv Latvian \ +nb Bokmål \ +nl Dutch \ +no Norwegian \ +pl Polish \ +pt Portuguese \ +ru Russian \ +sk Slovak \ +sr Serbian \ +sv Swedish \ +tr Turkish \ +uk English \ +vi Vietnamese \ +zh Chinese + + echo "Chapter: 2" + printf "\tLang: %-3s => %s\n" \ +en English\(default\) + echo "================================================================================================" } validateLang() { - if [[ $xx =~ ^[^a-z]*$ ]]; then echo "Error: iso639 code must contain only [a-z]" && exit 1; fi - if [ ${#xx} == 2 ] || [ ${#xx} == 3 ]; then :; else echo "Error: iso639 code must be 2 or 3 characters only" && exit 1; fi + case "$xx" in + '' | *[!a-z]* ) + echo "Error: iso639 code must contain only [a-z]" + exit 1 + esac + + case "${#xx}" in + [23] ) + ;; + * ) + echo "Error: iso639 code must be 2 or 3 characters only" + exit 1 + esac + export xx } validateChapter() { - if [[ $cc =~ ^[0-9]*$ ]]; then :; else echo "Error: chapter argument must contain digits only" && exit 1; fi - if [ $cc == "0" ]; then echo "Error: chapter must be non-zero" && exit 1; fi - if [ $cc == "00" ]; then echo "Error: chapter must be non-zero" && exit 1; fi + case "$cc" in + '' | *[!0-9]* ) + echo "Error: chapter argument must contain digits only" + exit 1 + ;; + 0 | 00 ) + echo "Error: chapter must be non-zero" + exit 1 + esac + export CHAPTER="$cc" } -shopt -s extglob while [ "$1" != "" ]; do - case $1 in + case "$1" in -g | --gui ) seq="gvim gvim91 gvim90 gvim81 gvim80 gvim8 gvim74 gvim73 gvim72 gvim71 gvim70 gvim7 gvim6 $seq" ;; -l | --language ) shift - xx=$1 + xx="$1" validateLang ;; - -l[a-z][a-z]?([a-z]) ) xx=${1#*l} - validateLang + -l[a-z][a-z][a-z] | -l[a-z][a-z] ) + export xx="${1#*l}" ;; - --language[a-z][a-z]?([a-z]) ) xx=${1#*e} - validateLang + --language[a-z][a-z][a-z] | --language[a-z][a-z] ) + export xx="${1#*e}" ;; - [a-z][a-z]?([a-z]) ) xx=$1 - validateLang + [a-z][a-z][a-z] | [a-z][a-z] ) export xx="$1" ;; -c | --chapter ) shift - cc=$1 + cc="$1" validateChapter ;; - -c[0-9]?([0-9]) ) cc=${1#*c} - validateChapter + -c[1-9][0-9] | -c[1-9] ) export CHAPTER="${1#*c}" ;; - --chapter[0-9]?([0-9]) ) cc=${1#*r} - validateChapter + --chapter[1-9][0-9] | --chapter[1-9] ) + export CHAPTER="${1#*r}" ;; -h | --help ) usage exit @@ -129,8 +138,8 @@ while [ "$1" != "" ]; do "" ) ;; * ) usage exit 1 - esac - shift + esac + shift done @@ -161,10 +170,10 @@ fi export TUTORCOPY # remove the copy of the tutor on exit -trap "rm -rf $TODELETE" 0 1 2 3 9 11 13 15 +trap "rm -rf $TODELETE" EXIT HUP INT QUIT SEGV PIPE TERM for i in $seq; do - testvim=$(which $i 2>/dev/null) + testvim=$(command -v "$i" 2>/dev/null) if test -f "$testvim"; then VIM=$i break From 9dadfe7a5205180941dbce3648a00422d32bb63d Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 4 Nov 2024 19:48:37 +0100 Subject: [PATCH 026/106] runtime(debversions): Update Debian versions - Move mantic to unsupported - Reorder names to maintain alphabetic order - Bump date to submit upstream closes: #15991 Signed-off-by: James McCoy Signed-off-by: Christian Brabandt --- runtime/syntax/shared/debversions.vim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runtime/syntax/shared/debversions.vim b/runtime/syntax/shared/debversions.vim index a3ad0b2624..404a0a49e3 100644 --- a/runtime/syntax/shared/debversions.vim +++ b/runtime/syntax/shared/debversions.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Debian version information " Maintainer: Debian Vim Maintainers -" Last Change: 2024 Oct 31 +" Last Change: 2024 Nov 04 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/shared/debversions.vim let s:cpo = &cpo @@ -11,7 +11,7 @@ let g:debSharedSupportedVersions = [ \ 'oldstable', 'stable', 'testing', 'unstable', 'experimental', 'sid', 'rc-buggy', \ 'bullseye', 'bookworm', 'trixie', 'forky', \ - \ 'focal', 'jammy', 'mantic', 'noble', 'oracular', 'plucky', + \ 'focal', 'jammy', 'noble', 'oracular', 'plucky', \ 'devel' \ ] let g:debSharedUnsupportedVersions = [ @@ -23,8 +23,8 @@ let g:debSharedUnsupportedVersions = [ \ 'gutsy', 'hardy', 'intrepid', 'jaunty', 'karmic', 'lucid', \ 'maverick', 'natty', 'oneiric', 'precise', 'quantal', 'raring', 'saucy', \ 'trusty', 'utopic', 'vivid', 'wily', 'xenial', 'yakkety', 'zesty', - \ 'artful', 'bionic', 'cosmic', 'disco', 'eoan', 'hirsute', - \ 'impish', 'kinetic', 'lunar', 'groovy' + \ 'artful', 'bionic', 'cosmic', 'disco', 'eoan', 'groovy', + \ 'hirsute', 'impish', 'kinetic', 'lunar', 'mantic', \ ] let &cpo=s:cpo From 19bc76c929a9d3f87d4ea932ba5c540bcd6023ee Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Mon, 4 Nov 2024 19:50:47 +0100 Subject: [PATCH 027/106] runtime(cook): include cook filetype plugin References: https://github.com/cooklang/spec?tab=readme-ov-file#comments closes: #15989 Signed-off-by: Riley Bruins Signed-off-by: Christian Brabandt --- .github/MAINTAINERS | 1 + runtime/ftplugin/cook.vim | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 runtime/ftplugin/cook.vim diff --git a/.github/MAINTAINERS b/.github/MAINTAINERS index ea342ef7a0..e2f1fafd9c 100644 --- a/.github/MAINTAINERS +++ b/.github/MAINTAINERS @@ -128,6 +128,7 @@ runtime/ftplugin/chatito.vim @ObserverOfTime runtime/ftplugin/chicken.vim @evhan runtime/ftplugin/clojure.vim @axvr runtime/ftplugin/cmakecache.vim @ribru17 +runtime/ftplugin/cook.vim @ribru17 runtime/ftplugin/cs.vim @nickspoons runtime/ftplugin/csh.vim @dkearns runtime/ftplugin/css.vim @dkearns diff --git a/runtime/ftplugin/cook.vim b/runtime/ftplugin/cook.vim new file mode 100644 index 0000000000..3697803e74 --- /dev/null +++ b/runtime/ftplugin/cook.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: Cooklang +" Maintainer: Riley Bruins +" Last Change: 2024 Nov 03 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=:-- commentstring=--\ %s + +let b:undo_ftplugin = 'setl com< cms<' From 93f65a4ab8168c766e4d3794607762b52762ef82 Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Mon, 4 Nov 2024 19:58:45 +0100 Subject: [PATCH 028/106] patch 9.1.0839: filetype: leo files are not recognized Problem: filetype: leo files are not recognized Solution: detect '*.leo' files as leo filetype, include a filetype plugin (Riley Bruins) References: https://github.com/ProvableHQ/leo closes: #15988 Signed-off-by: Riley Bruins Signed-off-by: Christian Brabandt --- .github/MAINTAINERS | 1 + runtime/filetype.vim | 3 +++ runtime/ftplugin/leo.vim | 13 +++++++++++++ src/testdir/test_filetype.vim | 1 + src/version.c | 2 ++ 5 files changed, 20 insertions(+) create mode 100644 runtime/ftplugin/leo.vim diff --git a/.github/MAINTAINERS b/.github/MAINTAINERS index e2f1fafd9c..b3822c2153 100644 --- a/.github/MAINTAINERS +++ b/.github/MAINTAINERS @@ -202,6 +202,7 @@ runtime/ftplugin/kdl.vim @imsnif @jiangyinzuo runtime/ftplugin/kivy.vim @ribru17 runtime/ftplugin/kotlin.vim @udalov runtime/ftplugin/ldapconf.vim @ribru17 +runtime/ftplugin/leo.vim @ribru17 runtime/ftplugin/less.vim @genoma runtime/ftplugin/lex.vim @ribru17 runtime/ftplugin/liquid.vim @tpope diff --git a/runtime/filetype.vim b/runtime/filetype.vim index f2ddcc6767..b3cec87216 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1325,6 +1325,9 @@ au BufRead,BufNewFile *.ldg,*.ledger,*.journal setf ledger " lf configuration (lfrc) au BufNewFile,BufRead lfrc setf lf +" Leo +au BufNewFile,BufRead *.leo setf leo + " Less au BufNewFile,BufRead *.less setf less diff --git a/runtime/ftplugin/leo.vim b/runtime/ftplugin/leo.vim new file mode 100644 index 0000000000..a009c02df4 --- /dev/null +++ b/runtime/ftplugin/leo.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: Leo +" Maintainer: Riley Bruins +" Last Change: 2024 Nov 03 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=:// commentstring=//\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 050ff5f391..9ddab96131 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -408,6 +408,7 @@ def s:GetFilenameChecks(): dict> ldif: ['file.ldif'], lean: ['file.lean'], ledger: ['file.ldg', 'file.ledger', 'file.journal'], + leo: ['file.leo'], less: ['file.less'], lex: ['file.lex', 'file.l', 'file.lxx', 'file.l++'], lf: ['lfrc'], diff --git a/src/version.c b/src/version.c index d213e66a38..f13567f308 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 */ +/**/ + 839, /**/ 838, /**/ From c04bc64ba61f2386fafb086b47f16f122a0c779a Mon Sep 17 00:00:00 2001 From: Serhii Khoma Date: Mon, 4 Nov 2024 20:14:43 +0100 Subject: [PATCH 029/106] patch 9.1.0840: filetype: idris2 files are not recognized Problem: filetype: idris2 files are not recognized Solution: detect '*.idr' files as idris2, '*.lidr' files as lidris2 and '*.ipkg' files as ipkg filetype (Serhii Khoma) closes: #15987 Signed-off-by: Serhii Khoma Signed-off-by: Christian Brabandt --- runtime/filetype.vim | 7 +++++++ src/testdir/test_filetype.vim | 3 +++ src/version.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index b3cec87216..6e9f0b222a 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1133,6 +1133,10 @@ au BufNewFile,BufRead indent.pro call dist#ft#ProtoCheck('indent') " IDL (Interactive Data Language), Prolog, Cproto or zsh module C au BufNewFile,BufRead *.pro call dist#ft#ProtoCheck('idlang') +" Idris2 +au BufNewFile,BufRead *.idr setf idris2 +au BufNewFile,BufRead *.lidr setf lidris2 + " Indent RC au BufNewFile,BufRead indentrc setf indent @@ -1152,6 +1156,9 @@ au BufRead,BufNewFile usw2kagt.log\c,usw2kagt.*.log\c,*.usw2kagt.log\c setf usw2 " Ipfilter au BufNewFile,BufRead ipf.conf,ipf6.conf,ipf.rules setf ipfilter +" Ipkg +au BufNewFile,BufRead *.ipkg setf ipkg + " Informix 4GL (source - canonical, include file, I4GL+M4 preproc.) au BufNewFile,BufRead *.4gl,*.4gh,*.m4gl setf fgl diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 9ddab96131..cca619bfaa 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -359,12 +359,14 @@ def s:GetFilenameChecks(): dict> ibasic: ['file.iba', 'file.ibi'], icemenu: ['/.icewm/menu', 'any/.icewm/menu'], icon: ['file.icn'], + idris2: ['file.idr'], indent: ['.indent.pro', 'indentrc'], inform: ['file.inf', 'file.INF'], initng: ['/etc/initng/any/file.i', 'file.ii', 'any/etc/initng/any/file.i'], inittab: ['inittab'], inko: ['file.inko'], ipfilter: ['ipf.conf', 'ipf6.conf', 'ipf.rules'], + ipkg: ['file.ipkg'], iss: ['file.iss'], ist: ['file.ist', 'file.mst'], j: ['file.ijs'], @@ -415,6 +417,7 @@ def s:GetFilenameChecks(): dict> lftp: ['lftp.conf', '.lftprc', 'anylftp/rc', 'lftp/rc', 'some-lftp/rc'], lhaskell: ['file.lhs'], libao: ['/etc/libao.conf', '/.libao', 'any/.libao', 'any/etc/libao.conf'], + lidris2: ['file.lidr'], lifelines: ['file.ll'], lilo: ['lilo.conf', 'lilo.conf-file'], lilypond: ['file.ly', 'file.ily'], diff --git a/src/version.c b/src/version.c index f13567f308..d00d280856 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 */ +/**/ + 840, /**/ 839, /**/ From cef8ab2c75841cee1cd72266aa662fbe54fc0acc Mon Sep 17 00:00:00 2001 From: Yee Cheng Chin Date: Mon, 4 Nov 2024 20:26:47 +0100 Subject: [PATCH 030/106] patch 9.1.0841: tests: still preferring python2 over python3 Problem: tests: still preferring python2 over python3 Solution: prefer Python 3 when picking a Python program in Vim tests, by checking for the more specific python version first and only when python3 not found, check for the python binary (Yee Cheng Chin) Most OSes have Python 3 mapped to `python3` instead of `python`. Vim tests should prioritize using that instead of Python 2 in case that is still installed on the host system. closes: #15986 Signed-off-by: Yee Cheng Chin Signed-off-by: Christian Brabandt --- src/testdir/shared.vim | 6 +++--- src/version.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim index a9b422c30e..8ae6fa0213 100644 --- a/src/testdir/shared.vim +++ b/src/testdir/shared.vim @@ -25,10 +25,10 @@ func PythonProg() if !(has('job') || executable('pkill')) return '' endif - if executable('python') - let s:python = 'python' - elseif executable('python3') + if executable('python3') let s:python = 'python3' + elseif executable('python') + let s:python = 'python' else return '' end diff --git a/src/version.c b/src/version.c index d00d280856..3c18aa479c 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 */ +/**/ + 841, /**/ 840, /**/ From 8bb5eaf019bc46e3b20e1509d88c07655f1632cd Mon Sep 17 00:00:00 2001 From: Jonas Sortie Termansen Date: Mon, 4 Nov 2024 20:32:27 +0100 Subject: [PATCH 031/106] patch 9.1.0842: not checking for the sync() systemcall Problem: not checking for the sync() systemcall Solution: check for sync in configure script, fix related #ifdefs (Jonas Termansen) It's better to check for features directly rather than maintaining a denylist of operating systems without them. closes: #15985 Signed-off-by: Jonas 'Sortie' Termansen Signed-off-by: Christian Brabandt --- src/auto/configure | 6 ++++++ src/config.h.in | 1 + src/configure.ac | 2 +- src/memfile.c | 9 +++------ src/version.c | 2 ++ 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/auto/configure b/src/auto/configure index db8a89ba03..062119e776 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -13642,6 +13642,12 @@ then : printf "%s\n" "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h fi +ac_fn_c_check_func "$LINENO" "sync" "ac_cv_func_sync" +if test "x$ac_cv_func_sync" = xyes +then : + printf "%s\n" "#define HAVE_SYNC 1" >>confdefs.h + +fi diff --git a/src/config.h.in b/src/config.h.in index 530c0829f0..3ff4605a03 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -209,6 +209,7 @@ #undef HAVE_CANBERRA #undef HAVE_SODIUM #undef HAVE_ST_BLKSIZE +#undef HAVE_SYNC #undef HAVE_SYSCONF #undef HAVE_SYSCTL #undef HAVE_SYSINFO diff --git a/src/configure.ac b/src/configure.ac index 24479d3861..56895f66ac 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -3769,7 +3769,7 @@ AC_CHECK_FUNCS(fchdir fchown fchmod fsync getcwd getpseudotty \ sigprocmask sigvec strcasecmp strcoll strerror strftime stricmp strncasecmp \ strnicmp strpbrk strptime strtol tgetent towlower towupper iswupper \ tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt \ - clock_gettime) + clock_gettime sync) AC_FUNC_SELECT_ARGTYPES AC_FUNC_FSEEKO diff --git a/src/memfile.c b/src/memfile.c index abb7c3fb3f..4707969f46 100644 --- a/src/memfile.c +++ b/src/memfile.c @@ -594,13 +594,10 @@ mf_sync(memfile_T *mfp, int flags) } else # endif - // OpenNT is strictly POSIX (Benzinger) - // Tandem/Himalaya NSK-OSS doesn't have sync() - // No sync() on Stratus VOS -# if defined(__OPENNT) || defined(__TANDEM) || defined(__VOS__) - fflush(NULL); -# else +# ifdef HAVE_SYNC sync(); +# else + fflush(NULL); # endif #endif #ifdef VMS diff --git a/src/version.c b/src/version.c index 3c18aa479c..7d02e6cf7d 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 */ +/**/ + 842, /**/ 841, /**/ From 59834ba6df10dc48565bf55ac6c8e8a4aa40210b Mon Sep 17 00:00:00 2001 From: Matteo Landi Date: Mon, 4 Nov 2024 20:46:54 +0100 Subject: [PATCH 032/106] runtime(matchparen): Add matchparen_disable_cursor_hl config option Set the "matchparen_disable_cursor_hl" config variable to disable highlighting the cursor with the MatchParen highlighting group. closes: #15984 Signed-off-by: Matteo Landi Signed-off-by: Christian Brabandt --- runtime/doc/pi_paren.txt | 21 ++++++++++++++++----- runtime/plugin/matchparen.vim | 17 ++++++++++++++--- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/runtime/doc/pi_paren.txt b/runtime/doc/pi_paren.txt index 719353fa94..049889699d 100644 --- a/runtime/doc/pi_paren.txt +++ b/runtime/doc/pi_paren.txt @@ -1,4 +1,4 @@ -*pi_paren.txt* For Vim version 9.1. Last change: 2013 May 08 +*pi_paren.txt* For Vim version 9.1. Last change: 2024 Nov 04 VIM REFERENCE MANUAL by Bram Moolenaar @@ -10,6 +10,7 @@ The functionality mentioned here is a |standard-plugin|. This plugin is only available if 'compatible' is not set. You can avoid loading this plugin by setting the "loaded_matchparen" variable: > + :let loaded_matchparen = 1 The plugin installs CursorMoved, CursorMovedI and WinEnter autocommands to @@ -29,6 +30,16 @@ the ":highlight" command. Example: > :hi MatchParen ctermbg=blue guibg=lightblue +By default the plugin will highlight both the paren under the cursor and the +matching one using the |hl-MatchParen| highlighting group. This may result in +the cursor briefly disappearing from the screen as the MatchParen colors take +over the cursor highlight. To prevent this from happening and have the plugin +only highlight the matching paren and not the one under the cursor +(effectively leaving the cursor style unchanged), you can set the +"matchparen_disable_cursor_hl" variable: > + + :let matchparen_disable_cursor_hl = 1 + The characters to be matched come from the 'matchpairs' option. You can change the value to highlight different matches. Note that not everything is possible. For example, you can't highlight single or double quotes, because @@ -46,10 +57,10 @@ are: closed folds. - 'synmaxcol' times 2 bytes before or after the cursor to avoid a delay in a long line with syntax highlighting. -- A timeout of 300 msec (60 msec in Insert mode). This can be changed with the - g:matchparen_timeout and g:matchparen_insert_timeout variables and their - buffer-local equivalents b:matchparen_timeout and - b:matchparen_insert_timeout. +- A timeout of 300 msec (60 msec in Insert mode). This can be changed with + the "g:matchparen_timeout" and "g:matchparen_insert_timeout" variables and + their buffer-local equivalents "b:matchparen_timeout" and + "b:matchparen_insert_timeout". If you would like the |%| command to work better, the matchit plugin can be used, see |matchit-install|. This plugin also helps to skip matches in diff --git a/runtime/plugin/matchparen.vim b/runtime/plugin/matchparen.vim index 2899612dce..661a34b578 100644 --- a/runtime/plugin/matchparen.vim +++ b/runtime/plugin/matchparen.vim @@ -17,6 +17,9 @@ endif if !exists("g:matchparen_insert_timeout") let g:matchparen_insert_timeout = 60 endif +if !exists("g:matchparen_disable_cursor_hl") + let g:matchparen_disable_cursor_hl = 0 +endif let s:has_matchaddpos = exists('*matchaddpos') @@ -189,10 +192,18 @@ func s:Highlight_Matching_Pair() " If a match is found setup match highlighting. if m_lnum > 0 && m_lnum >= stoplinetop && m_lnum <= stoplinebottom if s:has_matchaddpos - call add(w:matchparen_ids, matchaddpos('MatchParen', [[c_lnum, c_col - before], [m_lnum, m_col]], 10)) + if !g:matchparen_disable_cursor_hl + call add(w:matchparen_ids, matchaddpos('MatchParen', [[c_lnum, c_col - before], [m_lnum, m_col]], 10)) + else + call add(w:matchparen_ids, matchaddpos('MatchParen', [[m_lnum, m_col]], 10)) + endif else - exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) . - \ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/' + if !g:matchparen_disable_cursor_hl + exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) . + \ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/' + else + exe '3match MatchParen /\(\%' . m_lnum . 'l\%' . m_col . 'c\)/' + endif call add(w:matchparen_ids, 3) endif let w:paren_hl_on = 1 From 5ccac75d967e73669fd9dd5b83916a54a5989ae6 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Mon, 4 Nov 2024 21:02:42 +0100 Subject: [PATCH 033/106] runtime(doc): simplify vimtutor manpage a bit more Signed-off-by: Christian Brabandt --- runtime/doc/vimtutor.1 | 25 +++++-------------------- runtime/doc/vimtutor.man | 31 ++++++++----------------------- 2 files changed, 13 insertions(+), 43 deletions(-) diff --git a/runtime/doc/vimtutor.1 b/runtime/doc/vimtutor.1 index 3d3f32b70b..87f09785ff 100644 --- a/runtime/doc/vimtutor.1 +++ b/runtime/doc/vimtutor.1 @@ -1,4 +1,4 @@ -.TH VIMTUTOR 1 "2024 November 03" +.TH VIMTUTOR 1 "2024 November 04" .SH NAME vimtutor \- the Vim tutor .SH SYNOPSIS @@ -19,16 +19,8 @@ The is useful for people that want to learn their first .B Vim commands. -.PP -The optional argument \-g starts vimtutor with gvim rather than vim, if the -GUI version of Vim is available, or falls back to vim if gvim is not found. -.PP The optional [language] argument is the two-letter name of a language, like "it" or "es". -If the [language] argument is missing, the language of the current locale will -be used. -If a tutor in this language is available, it will be used. -Otherwise the English version will be used. .PP .B Vimtutor only opens temporary copies of the original tutor files, there is no danger of overwriting the lessons. @@ -43,7 +35,7 @@ compatible mode. Set the two or three letter language code. E.g. 'it', 'es', 'bar'. Defaults to language of locale if available, else to English. .TP .BR \-c ", " \-\-chapter =\fINUMBER\fR -Set the one or two digit chapter number. Defaults to chapter one. +Set the chapter number. Defaults to chapter one. .TP .BR \-g ", " \-\-gui Start @@ -88,7 +80,7 @@ The .B Vimtutor chapter one text file(s). .TP 15 -/usr/local/share/vim/vim??/tutor/tutor02[.language] +/usr/local/share/vim/vim??/tutor/tutor2[.language] The .B Vimtutor chapter two text file(s). @@ -98,18 +90,11 @@ The .B Vim script used to copy the .B Vimtutor -chapter one text file. -.TP 15 -/usr/local/share/vim/vim??/tutor/tutor02.vim -The -.B Vim -script used to copy the -.B Vimtutor -chapter two text file. +text file. .SH AUTHOR .B The Vi Tutorial was originally written for Vi by Michael C. Pierce and Robert K. Ware, Colorado School of Mines using ideas supplied by Charles Smith, Colorado State University. -.B E-mail: bware@mines.colorado.edu. +.B E-mail: bware@mines.colorado.edu (now invalid). .PP Modified for .B Vim diff --git a/runtime/doc/vimtutor.man b/runtime/doc/vimtutor.man index 459542e304..29b56cb97d 100644 --- a/runtime/doc/vimtutor.man +++ b/runtime/doc/vimtutor.man @@ -13,17 +13,8 @@ DESCRIPTION Vimtutor starts the Vim tutor. The Vimtutor is useful for people that want to learn their first Vim - commands. - - The optional argument -g starts vimtutor with gvim rather than vim, if - the GUI version of Vim is available, or falls back to vim if gvim is - not found. - - The optional [language] argument is the two-letter name of a language, - like "it" or "es". If the [language] argument is missing, the language - of the current locale will be used. If a tutor in this language is - available, it will be used. Otherwise the English version will be - used. + commands. The optional [language] argument is the two-letter name of a + language, like "it" or "es". Vimtutor only opens temporary copies of the original tutor files, there is no danger of overwriting the lessons. @@ -32,13 +23,12 @@ DESCRIPTION OPTIONS -l, --language=ISO639 - Set the two or three letter language code. E.g. 'it', 'es', + Set the two or three letter language code. E.g. 'it', 'es', 'bar'. Defaults to language of locale if available, else to Eng‐ lish. -c, --chapter=NUMBER - Set the one or two digit chapter number. Defaults to chapter - one. + Set the chapter number. Defaults to chapter one. -g, --gui Start vimtutor in the GUI version of vim if available, otherwise @@ -66,22 +56,17 @@ FILES /usr/local/share/vim/vim??/tutor/tutor[.language] The Vimtutor chapter one text file(s). - /usr/local/share/vim/vim??/tutor/tutor02[.language] + /usr/local/share/vim/vim??/tutor/tutor2[.language] The Vimtutor chapter two text file(s). /usr/local/share/vim/vim??/tutor/tutor.vim - The Vim script used to copy the Vimtutor chapter one - text file. - - /usr/local/share/vim/vim??/tutor/tutor02.vim - The Vim script used to copy the Vimtutor chapter two - text file. + The Vim script used to copy the Vimtutor text file. AUTHOR The Vi Tutorial was originally written for Vi by Michael C. Pierce and Robert K. Ware, Colorado School of Mines using ideas supplied by Charles Smith, Colorado State University. E-mail: bware@mines.col‐ - orado.edu. + orado.edu (now invalid). Modified for Vim by Bram Moolenaar. @@ -90,4 +75,4 @@ AUTHOR SEE ALSO vim(1) - 2024 November 03 VIMTUTOR(1) + 2024 November 04 VIMTUTOR(1) From 3780c11267415ff57f261fcd3e1dea0c2c9d8dd0 Mon Sep 17 00:00:00 2001 From: Enno Date: Wed, 6 Nov 2024 20:14:49 +0100 Subject: [PATCH 034/106] runtime(compiler): fix typo in cppcheck compiler plugin closes: #16002 Signed-off-by: Enno Signed-off-by: Christian Brabandt --- runtime/compiler/cppcheck.vim | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/runtime/compiler/cppcheck.vim b/runtime/compiler/cppcheck.vim index 20c906f412..d6fc0d6873 100644 --- a/runtime/compiler/cppcheck.vim +++ b/runtime/compiler/cppcheck.vim @@ -1,15 +1,13 @@ " vim compiler file " Compiler: cppcheck (C++ static checker) " Maintainer: Vincent B. (twinside@free.fr) -" Last Change: 2024 oct 17 by @Konfekt +" Last Change: 2024 Oct 17 by @Konfekt -if exists("cppcheck") - finish -endif +if exists("current_compiler") | finish | endif let current_compiler = "cppcheck" let s:cpo_save = &cpo -set cpo-=C +set cpo&vim let s:slash = has('win32')? '\' : '/' From 39cd9061b1f606776ec5e018a6cd330b976d07c1 Mon Sep 17 00:00:00 2001 From: Yee Cheng Chin Date: Wed, 6 Nov 2024 20:20:57 +0100 Subject: [PATCH 035/106] runtime(doc): update default value for fillchars option closes: #15998 Signed-off-by: Yee Cheng Chin Signed-off-by: Christian Brabandt --- runtime/doc/options.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 7a554dbb28..f9189e59ad 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.1. Last change: 2024 Nov 02 +*options.txt* For Vim version 9.1. Last change: 2024 Nov 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -3515,7 +3515,7 @@ A jump table for the options with a short description can be found at |Q_op|. Only alphanumeric characters, '-' and '_' can be used. *'fillchars'* *'fcs'* -'fillchars' 'fcs' string (default "vert:|,fold:-,eob:~") +'fillchars' 'fcs' string (default "vert:|,fold:-,eob:~,lastline:@") global or local to window |global-local| Characters to fill the statuslines, vertical separators and special lines in the window. From fd1a838d364b62a9211af23c47e0eab8d54ea452 Mon Sep 17 00:00:00 2001 From: John Marriott Date: Wed, 6 Nov 2024 21:21:50 +0100 Subject: [PATCH 036/106] patch 9.1.0843: too many strlen() calls in undo.c Problem: too many strlen() calls in undo.c Solution: refactor code and remove strlen() calls, update test_undo.vim and close remaining open swap files (John Marriott) closes: #15995 Signed-off-by: John Marriott Signed-off-by: Christian Brabandt --- src/structs.h | 2 ++ src/testdir/test_undo.vim | 20 +++++++++--- src/undo.c | 65 ++++++++++++++++++++++----------------- src/version.c | 2 ++ 4 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/structs.h b/src/structs.h index 47999a9538..66d57e02d8 100644 --- a/src/structs.h +++ b/src/structs.h @@ -397,6 +397,8 @@ typedef struct { char_u *ul_line; // text of the line long ul_len; // length of the line including NUL, plus text // properties + colnr_T ul_textlen; // length of the line excluding NUL and any text + // properties } undoline_T; typedef struct u_entry u_entry_T; diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim index eec0e0bc06..2e598d35c2 100644 --- a/src/testdir/test_undo.vim +++ b/src/testdir/test_undo.vim @@ -149,7 +149,7 @@ func Test_undotree_bufnr() " Drop created windows set ul& new - only! + bw! endfunc func Test_global_local_undolevels() @@ -193,6 +193,7 @@ func Test_global_local_undolevels() " Drop created windows set ul& new + bw! one two only! endfunc @@ -253,7 +254,7 @@ func Test_undo_del_chars() later 1h call assert_equal('123-abc', getline(1)) - close! + bw! endfunc func Test_undolist() @@ -274,7 +275,16 @@ func Test_undolist() call feedkeys('achange3\', 'xt') let a = execute('undolist') call assert_match("^\nnumber changes when *saved\n *2 *2 *.*\n *3 *2 .*$", a) - close! + + " 3 save number + if has("persistent_undo") + setl undofile + w Xundolist.txt + defer delete('Xundolist.txt') + let lastline = execute('undolist')->split("\n")[-1] + call assert_match("ago 1", lastline) + endif + bw! endfunc func Test_U_command() @@ -286,7 +296,7 @@ func Test_U_command() call assert_equal('', getline(1)) norm! U call assert_equal('change1change2', getline(1)) - close! + bw! endfunc func Test_undojoin() @@ -393,7 +403,7 @@ func Test_insert_expr() call feedkeys("u", 'x') call assert_equal(['a', 'b', 'c', '12', 'd'], getline(2, '$')) - close! + bw! endfunc func Test_undofile_earlier() diff --git a/src/undo.c b/src/undo.c index 8c2783acd5..52df9394fc 100644 --- a/src/undo.c +++ b/src/undo.c @@ -361,6 +361,7 @@ u_save_line(undoline_T *ul, linenr_T lnum) { char_u *line = ml_get(lnum); + ul->ul_textlen = ml_get_len(lnum); if (curbuf->b_ml.ml_line_len == 0) { ul->ul_len = 1; @@ -793,14 +794,10 @@ u_compute_hash(char_u *hash) { context_sha256_T ctx; linenr_T lnum; - char_u *p; sha256_start(&ctx); for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) - { - p = ml_get(lnum); - sha256_update(&ctx, p, (UINT32_T)(STRLEN(p) + 1)); - } + sha256_update(&ctx, ml_get(lnum), (UINT32_T)(ml_get_len(lnum) + 1)); sha256_finish(&ctx, hash); } @@ -820,8 +817,10 @@ u_get_undo_file_name(char_u *buf_ffname, int reading) char_u *undo_file_name = NULL; int dir_len; char_u *p; + size_t plen; stat_T st; char_u *ffname = buf_ffname; + size_t ffnamelen; #ifdef HAVE_READLINK char_u fname_buf[MAXPATHL]; #endif @@ -836,6 +835,7 @@ u_get_undo_file_name(char_u *buf_ffname, int reading) ffname = fname_buf; #endif + ffnamelen = STRLEN(ffname); // Loop over 'undodir'. When reading find the first file that exists. // When not reading use the first directory that exists or ".". dirp = p_udir; @@ -846,23 +846,24 @@ u_get_undo_file_name(char_u *buf_ffname, int reading) { // Use same directory as the ffname, // "dir/name" -> "dir/.name.un~" - undo_file_name = vim_strnsave(ffname, STRLEN(ffname) + 5); + undo_file_name = vim_strnsave(ffname, ffnamelen + 5); if (undo_file_name == NULL) break; p = gettail(undo_file_name); + plen = (size_t)(ffnamelen - (p - undo_file_name)); #ifdef VMS // VMS can not handle more than one dot in the filenames // use "dir/name" -> "dir/_un_name" - add _un_ // at the beginning to keep the extension - mch_memmove(p + 4, p, STRLEN(p) + 1); + mch_memmove(p + 4, p, plen + 1); mch_memmove(p, "_un_", 4); #else // Use same directory as the ffname, // "dir/name" -> "dir/.name.un~" - mch_memmove(p + 1, p, STRLEN(p) + 1); + mch_memmove(p + 1, p, plen + 1); *p = '.'; - STRCAT(p, ".un~"); + STRCPY(p + plen + 1, ".un~"); #endif } else @@ -872,7 +873,7 @@ u_get_undo_file_name(char_u *buf_ffname, int reading) { if (munged_name == NULL) { - munged_name = vim_strsave(ffname); + munged_name = vim_strnsave(ffname, ffnamelen); if (munged_name == NULL) return NULL; for (p = munged_name; *p != NUL; MB_PTR_ADV(p)) @@ -1189,7 +1190,6 @@ read_string_decrypt(bufinfo_T *bi, int len) static int serialize_header(bufinfo_T *bi, char_u *hash) { - long len; buf_T *buf = bi->bi_buf; FILE *fp = bi->bi_fp; char_u time_buf[8]; @@ -1205,6 +1205,7 @@ serialize_header(bufinfo_T *bi, char_u *hash) { char_u *header; int header_len; + long len; undo_write_bytes(bi, (long_u)UF_VERSION_CRYPT, 2); bi->bi_state = crypt_create_for_writing(crypt_get_method_nr(buf), @@ -1244,11 +1245,9 @@ serialize_header(bufinfo_T *bi, char_u *hash) // buffer-specific data undo_write_bytes(bi, (long_u)buf->b_ml.ml_line_count, 4); - len = buf->b_u_line_ptr.ul_line == NULL - ? 0L : (long)STRLEN(buf->b_u_line_ptr.ul_line); - undo_write_bytes(bi, (long_u)len, 4); - if (len > 0 && fwrite_crypt(bi, buf->b_u_line_ptr.ul_line, (size_t)len) - == FAIL) + undo_write_bytes(bi, (long_u)buf->b_u_line_ptr.ul_textlen, 4); + if (buf->b_u_line_ptr.ul_textlen > 0 && fwrite_crypt(bi, buf->b_u_line_ptr.ul_line, + (size_t)buf->b_u_line_ptr.ul_textlen) == FAIL) return FAIL; undo_write_bytes(bi, (long_u)buf->b_u_line_lnum, 4); undo_write_bytes(bi, (long_u)buf->b_u_line_colnr, 4); @@ -1415,7 +1414,6 @@ serialize_uep( u_entry_T *uep) { int i; - size_t len; undo_write_bytes(bi, (long_u)uep->ue_top, 4); undo_write_bytes(bi, (long_u)uep->ue_bot, 4); @@ -1425,10 +1423,10 @@ serialize_uep( { // Text is written without the text properties, since we cannot restore // the text property types. - len = STRLEN(uep->ue_array[i].ul_line); - if (undo_write_bytes(bi, (long_u)len, 4) == FAIL) + if (undo_write_bytes(bi, (long_u)uep->ue_array[i].ul_textlen, 4) == FAIL) return FAIL; - if (len > 0 && fwrite_crypt(bi, uep->ue_array[i].ul_line, len) == FAIL) + if (uep->ue_array[i].ul_textlen > 0 + && fwrite_crypt(bi, uep->ue_array[i].ul_line, uep->ue_array[i].ul_textlen) == FAIL) return FAIL; } return OK; @@ -1484,6 +1482,7 @@ unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name) } array[i].ul_line = line; array[i].ul_len = line_len + 1; + array[i].ul_textlen = line_len; } return uep; } @@ -1862,6 +1861,7 @@ u_read_undo(char_u *name, char_u *hash, char_u *orig_name UNUSED) CLEAR_FIELD(bi); line_ptr.ul_len = 0; + line_ptr.ul_textlen = 0; line_ptr.ul_line = NULL; if (name == NULL) @@ -1986,6 +1986,7 @@ u_read_undo(char_u *name, char_u *hash, char_u *orig_name UNUSED) { line_ptr.ul_line = read_string_decrypt(&bi, str_len); line_ptr.ul_len = str_len + 1; + line_ptr.ul_textlen = str_len; } line_lnum = (linenr_T)undo_read_4c(&bi); line_colnr = (colnr_T)undo_read_4c(&bi); @@ -3098,7 +3099,7 @@ ex_undolist(exarg_T *eap UNUSED) int mark; int nomark; int changes = 1; - int i; + int len; /* * 1: walk the tree to find all leafs, put the info in "ga". @@ -3117,18 +3118,20 @@ ex_undolist(exarg_T *eap UNUSED) { if (ga_grow(&ga, 1) == FAIL) break; - vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", + len = vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", uhp->uh_seq, changes); - add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), - uhp->uh_time); + add_time(IObuff + len, IOSIZE - len, uhp->uh_time); + + // we have to call STRLEN() here because add_time() does not report + // the number of characters added. + len += STRLEN(IObuff + len); if (uhp->uh_save_nr > 0) { - while (STRLEN(IObuff) < 33) - STRCAT(IObuff, " "); - vim_snprintf_add((char *)IObuff, IOSIZE, - " %3ld", uhp->uh_save_nr); + int n = (len >= 33) ? 0 : 33 - len; + + len += vim_snprintf((char *)IObuff + len, IOSIZE - len, "%*.*s %3ld", n, n, " ", uhp->uh_save_nr); } - ((char_u **)(ga.ga_data))[ga.ga_len++] = vim_strsave(IObuff); + ((char_u **)(ga.ga_data))[ga.ga_len++] = vim_strnsave(IObuff, len); } uhp->uh_walk = mark; @@ -3175,6 +3178,8 @@ ex_undolist(exarg_T *eap UNUSED) msg(_("Nothing to undo")); else { + int i; + sort_strings((char_u **)ga.ga_data, ga.ga_len); msg_start(); @@ -3481,6 +3486,7 @@ u_clearall(buf_T *buf) buf->b_u_numhead = 0; buf->b_u_line_ptr.ul_line = NULL; buf->b_u_line_ptr.ul_len = 0; + buf->b_u_line_ptr.ul_textlen = 0; buf->b_u_line_lnum = 0; } @@ -3540,6 +3546,7 @@ u_clearline(void) VIM_CLEAR(curbuf->b_u_line_ptr.ul_line); curbuf->b_u_line_ptr.ul_len = 0; + curbuf->b_u_line_ptr.ul_textlen = 0; curbuf->b_u_line_lnum = 0; } diff --git a/src/version.c b/src/version.c index 7d02e6cf7d..7e95a46a77 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 */ +/**/ + 843, /**/ 842, /**/ From ea19e7856b6c7850eab7ce74aa209e09e2c6eae3 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 6 Nov 2024 21:50:05 +0100 Subject: [PATCH 037/106] patch 9.1.0844: if_python: no way to pass local vars to python Problem: if_python: no way to pass local vars to python Solution: Add locals argument to py3eval(), pyeval() and pyxeval() (Ben Jackson) fixes: #8573 closes: #10594 Signed-off-by: Ben Jackson Signed-off-by: Christian Brabandt --- runtime/doc/builtin.txt | 22 ++++++++----- runtime/doc/if_pyth.txt | 10 +++++- runtime/doc/version9.txt | 3 +- src/evalfunc.c | 52 ++++++++++++++++++++++++++----- src/if_py_both.h | 11 ++++--- src/if_python.c | 10 ++++-- src/if_python3.c | 14 +++++++-- src/proto/if_python.pro | 2 +- src/proto/if_python3.pro | 2 +- src/testdir/Make_all.mak | 2 ++ src/testdir/test_python2.vim | 43 +++++++++++++++++++++++++ src/testdir/test_python3.vim | 46 +++++++++++++++++++++++++++ src/testdir/test_pyx2.vim | 43 +++++++++++++++++++++++++ src/testdir/test_pyx3.vim | 42 +++++++++++++++++++++++++ src/testdir/test_vim9_python3.vim | 17 ++++++++++ src/version.c | 2 ++ 16 files changed, 291 insertions(+), 30 deletions(-) create mode 100644 src/testdir/test_vim9_python3.vim diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index edc425a5ab..70d6f47a51 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 01 +*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -467,9 +467,9 @@ prop_type_get({name} [, {props}]) prop_type_list([{props}]) List get list of property types pum_getpos() Dict position and size of pum if visible pumvisible() Number whether popup menu is visible -py3eval({expr}) any evaluate |python3| expression -pyeval({expr}) any evaluate |Python| expression -pyxeval({expr}) any evaluate |python_x| expression +py3eval({expr}[, {locals}]) any evaluate |python3| expression +pyeval({expr}[, {locals}]) any evaluate |Python| expression +pyxeval({expr}[, {locals}]) any evaluate |python_x| expression rand([{expr}]) Number get pseudo-random number range({expr} [, {max} [, {stride}]]) List items from {expr} to {max} @@ -8127,9 +8127,14 @@ pumvisible() *pumvisible()* Return type: |Number| -py3eval({expr}) *py3eval()* +py3eval({expr}[, {locals}]) *py3eval()* Evaluate Python expression {expr} and return its result converted to Vim data structures. + If a {locals} |Dictionary| is given, it defines set of local + variables available in the expression. The keys are variable + names and the values are the variable values. |Dictionary| and + |List| values are referenced, and may be updated by the + expression (as if |python-bindeval| was used). Numbers and strings are returned as they are (strings are copied though, Unicode strings are additionally converted to 'encoding'). @@ -8141,15 +8146,17 @@ py3eval({expr}) *py3eval()* Can also be used as a |method|: > GetExpr()->py3eval() + 'b",".join(l)'->py3eval({'l': ['a', 'b', 'c']}) < Return type: any, depending on {expr} {only available when compiled with the |+python3| feature} *E858* *E859* -pyeval({expr}) *pyeval()* +pyeval({expr}[, {locals}]) *pyeval()* Evaluate Python expression {expr} and return its result converted to Vim data structures. + For {locals} see |py3eval()|. Numbers and strings are returned as they are (strings are copied though). Lists are represented as Vim |List| type. @@ -8165,9 +8172,10 @@ pyeval({expr}) *pyeval()* {only available when compiled with the |+python| feature} -pyxeval({expr}) *pyxeval()* +pyxeval({expr}[, {locals}]) *pyxeval()* Evaluate Python expression {expr} and return its result converted to Vim data structures. + For {locals} see |py3eval()|. Uses Python 2 or 3, see |python_x| and 'pyxversion'. See also: |pyeval()|, |py3eval()| diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt index 623684152b..0b6140f252 100644 --- a/runtime/doc/if_pyth.txt +++ b/runtime/doc/if_pyth.txt @@ -1,4 +1,4 @@ -*if_pyth.txt* For Vim version 9.1. Last change: 2024 May 16 +*if_pyth.txt* For Vim version 9.1. Last change: 2024 Nov 06 VIM REFERENCE MANUAL by Paul Moore @@ -201,6 +201,10 @@ vim.eval(str) *python-eval* [{'cmd': '/^eval_expr(arg, nextcmd)$/', 'static': 0, 'name': ~ 'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}] ~ + NOTE: In vim9script, local variables in def functions are not visible + to to python evaluations. To pass local variables to python evaluations, + use the {locals} dict when calling |py3eval()| and friends. + vim.bindeval(str) *python-bindeval* Like |python-eval|, but returns special objects described in |python-bindeval-objects|. These python objects let you modify (|List| @@ -741,6 +745,10 @@ To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()| functions to evaluate Python expressions and pass their values to Vim script. |pyxeval()| is also available. +You can inject local variables into the evaluation using the optional {locals} +dict. This can be particularly useful in vim9script where vim.eval +|python-eval| will not find locals in a def func. + The Python value "None" is converted to v:none. ============================================================================== diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 999a09cfc1..c4022d8882 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2024 Nov 03 +*version9.txt* For Vim version 9.1. Last change: 2024 Nov 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41606,6 +41606,7 @@ Changed~ - an interactive tutor plugin has been included |vim-tutor-mode|, can be started via |:Tutor| - improve the |vimtutor| and add a second chapter for more advanced tips +- allow to pass local Vim script variables to python interpreter |py3eval()| *added-9.2* Added ~ diff --git a/src/evalfunc.c b/src/evalfunc.c index adae129480..2d886682d5 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2487,7 +2487,7 @@ static funcentry_T global_functions[] = ret_dict_number, f_pum_getpos}, {"pumvisible", 0, 0, 0, NULL, ret_number_bool, f_pumvisible}, - {"py3eval", 1, 1, FEARG_1, arg1_string, + {"py3eval", 1, 2, FEARG_1, arg2_string_dict, ret_any, #ifdef FEAT_PYTHON3 f_py3eval @@ -2495,7 +2495,7 @@ static funcentry_T global_functions[] = NULL #endif }, - {"pyeval", 1, 1, FEARG_1, arg1_string, + {"pyeval", 1, 2, FEARG_1, arg2_string_dict, ret_any, #ifdef FEAT_PYTHON f_pyeval @@ -2503,7 +2503,7 @@ static funcentry_T global_functions[] = NULL #endif }, - {"pyxeval", 1, 1, FEARG_1, arg1_string, + {"pyxeval", 1, 2, FEARG_1, arg2_string_dict, ret_any, #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) f_pyxeval @@ -9291,18 +9291,35 @@ f_py3eval(typval_T *argvars, typval_T *rettv) { char_u *str; char_u buf[NUMBUFLEN]; + dict_T *locals; if (check_restricted() || check_secure()) return; - if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || check_for_opt_dict_arg(argvars, 1) == FAIL)) return; if (p_pyx == 0) p_pyx = 3; + if (argvars[1].v_type == VAR_DICT) + { + locals = argvars[1].vval.v_dict; + } + else if (argvars[1].v_type != VAR_UNKNOWN) + { + emsg(_(e_dictionary_required)); + return; + } + else + { + locals = NULL; + } + str = tv_get_string_buf(&argvars[0], buf); - do_py3eval(str, rettv); + do_py3eval(str, locals, rettv); } #endif @@ -9315,18 +9332,35 @@ f_pyeval(typval_T *argvars, typval_T *rettv) { char_u *str; char_u buf[NUMBUFLEN]; + dict_T *locals; if (check_restricted() || check_secure()) return; - if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + if (in_vim9script() && ( + check_for_string_arg(argvars, 0) == FAIL || + check_for_opt_dict_arg(argvars, 1) == FAIL ) ) return; if (p_pyx == 0) p_pyx = 2; + if (argvars[1].v_type == VAR_DICT) + { + locals = argvars[1].vval.v_dict; + } + else if (argvars[1].v_type != VAR_UNKNOWN) + { + emsg( "Invalid argument: must be dict" ); + return; + } + else + { + locals = NULL; + } + str = tv_get_string_buf(&argvars[0], buf); - do_pyeval(str, rettv); + do_pyeval(str, locals, rettv); } #endif @@ -9340,7 +9374,9 @@ f_pyxeval(typval_T *argvars, typval_T *rettv) if (check_restricted() || check_secure()) return; - if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || check_for_opt_dict_arg(argvars, 1) == FAIL)) return; # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) diff --git a/src/if_py_both.h b/src/if_py_both.h index 5ba443b493..5603ac7cc6 100644 --- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -328,7 +328,7 @@ static int Vim_PyRun_SimpleString(const char *str) #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1)) typedef void (*rangeinitializer)(void *); -typedef void (*runner)(const char *, void * +typedef void (*runner)(const char *, dict_T *, void * #ifdef PY_CAN_RECURSE , PyGILState_STATE * #endif @@ -6032,7 +6032,7 @@ init_range_eval(void *rettv UNUSED) } static void -run_cmd(const char *cmd, void *arg UNUSED +run_cmd(const char *cmd, dict_T* locals UNUSED, void *arg UNUSED #ifdef PY_CAN_RECURSE , PyGILState_STATE *pygilstate UNUSED #endif @@ -6057,7 +6057,7 @@ static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n "; static int code_hdr_len = 30; static void -run_do(const char *cmd, void *arg UNUSED +run_do(const char *cmd, dict_T* locals UNUSED, void *arg UNUSED #ifdef PY_CAN_RECURSE , PyGILState_STATE *pygilstate #endif @@ -6180,7 +6180,7 @@ run_do(const char *cmd, void *arg UNUSED } static void -run_eval(const char *cmd, void *arg +run_eval(const char *cmd, dict_T *locals, void *arg #ifdef PY_CAN_RECURSE , PyGILState_STATE *pygilstate UNUSED #endif @@ -6188,8 +6188,9 @@ run_eval(const char *cmd, void *arg { PyObject *run_ret; typval_T *rettv = (typval_T*)arg; + PyObject *pylocals = locals ? NEW_DICTIONARY(locals) : globals; - run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals); + run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, pylocals); if (run_ret == NULL) { if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) diff --git a/src/if_python.c b/src/if_python.c index 461ba52cf2..577807c44f 100644 --- a/src/if_python.c +++ b/src/if_python.c @@ -1009,7 +1009,7 @@ Python_Init(void) * External interface */ static void -DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg) +DoPyCommand(const char *cmd, dict_T* locals, rangeinitializer init_range, runner run, void *arg) { #ifndef PY_CAN_RECURSE static int recursive = 0; @@ -1058,7 +1058,7 @@ DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg) Python_RestoreThread(); // enter python #endif - run((char *) cmd, arg + run((char *) cmd, locals, arg #ifdef PY_CAN_RECURSE , &pygilstate #endif @@ -1103,6 +1103,7 @@ ex_python(exarg_T *eap) p_pyx = 2; DoPyCommand(script == NULL ? (char *) eap->arg : (char *) script, + NULL, init_range_cmd, (runner) run_cmd, (void *) eap); @@ -1154,6 +1155,7 @@ ex_pyfile(exarg_T *eap) // Execute the file DoPyCommand(buffer, + NULL, init_range_cmd, (runner) run_cmd, (void *) eap); @@ -1166,6 +1168,7 @@ ex_pydo(exarg_T *eap) p_pyx = 2; DoPyCommand((char *)eap->arg, + NULL, init_range_cmd, (runner)run_do, (void *)eap); @@ -1521,9 +1524,10 @@ FunctionGetattr(PyObject *self, char *name) } void -do_pyeval(char_u *str, typval_T *rettv) +do_pyeval(char_u *str, dict_T *locals, typval_T *rettv) { DoPyCommand((char *) str, + locals, init_range_eval, (runner) run_eval, (void *) rettv); diff --git a/src/if_python3.c b/src/if_python3.c index 5d45ba15f3..aa934cb7d0 100644 --- a/src/if_python3.c +++ b/src/if_python3.c @@ -1436,7 +1436,11 @@ Python3_Init(void) * External interface */ static void -DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg) +DoPyCommand(const char *cmd, + dict_T* locals, + rangeinitializer init_range, + runner run, + void *arg) { #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) char *saved_locale; @@ -1477,7 +1481,7 @@ DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg) cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", ERRORS_ENCODE_ARG); Py_XDECREF(cmdstr); - run(PyBytes_AsString(cmdbytes), arg, &pygilstate); + run(PyBytes_AsString(cmdbytes), locals, arg, &pygilstate); Py_XDECREF(cmdbytes); PyGILState_Release(pygilstate); @@ -1512,6 +1516,7 @@ ex_py3(exarg_T *eap) p_pyx = 3; DoPyCommand(script == NULL ? (char *) eap->arg : (char *) script, + NULL, init_range_cmd, (runner) run_cmd, (void *) eap); @@ -1578,6 +1583,7 @@ ex_py3file(exarg_T *eap) // Execute the file DoPyCommand(buffer, + NULL, init_range_cmd, (runner) run_cmd, (void *) eap); @@ -1590,6 +1596,7 @@ ex_py3do(exarg_T *eap) p_pyx = 3; DoPyCommand((char *)eap->arg, + NULL, init_range_cmd, (runner)run_do, (void *)eap); @@ -2137,9 +2144,10 @@ LineToString(const char *str) } void -do_py3eval(char_u *str, typval_T *rettv) +do_py3eval(char_u *str, dict_T *locals, typval_T *rettv) { DoPyCommand((char *) str, + locals, init_range_eval, (runner) run_eval, (void *) rettv); diff --git a/src/proto/if_python.pro b/src/proto/if_python.pro index 51054caf2d..ee78990af1 100644 --- a/src/proto/if_python.pro +++ b/src/proto/if_python.pro @@ -8,6 +8,6 @@ void ex_pydo(exarg_T *eap); void python_buffer_free(buf_T *buf); void python_window_free(win_T *win); void python_tabpage_free(tabpage_T *tab); -void do_pyeval(char_u *str, typval_T *rettv); +void do_pyeval(char_u *str, dict_T* locals, typval_T *rettv); int set_ref_in_python(int copyID); /* vim: set ft=c : */ diff --git a/src/proto/if_python3.pro b/src/proto/if_python3.pro index 0e139b9902..63104ab7dc 100644 --- a/src/proto/if_python3.pro +++ b/src/proto/if_python3.pro @@ -8,7 +8,7 @@ void ex_py3do(exarg_T *eap); void python3_buffer_free(buf_T *buf); void python3_window_free(win_T *win); void python3_tabpage_free(tabpage_T *tab); -void do_py3eval(char_u *str, typval_T *rettv); +void do_py3eval(char_u *str, dict_T* locals, typval_T *rettv); int set_ref_in_python3(int copyID); int python3_version(void); /* vim: set ft=c : */ diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 750c1940ab..6a7f4d3f96 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -47,6 +47,7 @@ TEST_VIM9 = \ test_vim9_fails \ test_vim9_func \ test_vim9_import \ + test_vim9_python3 \ test_vim9_script \ test_vim9_typealias @@ -61,6 +62,7 @@ TEST_VIM9_RES = \ test_vim9_fails.res \ test_vim9_func.res \ test_vim9_import.res \ + test_vim9_python3.res \ test_vim9_script.res \ test_vim9_typealias.res diff --git a/src/testdir/test_python2.vim b/src/testdir/test_python2.vim index ac43e60530..de5f60794e 100644 --- a/src/testdir/test_python2.vim +++ b/src/testdir/test_python2.vim @@ -809,6 +809,49 @@ func Test_python_pyeval() call AssertException(['let v = pyeval("vim")'], 'E859:') endfunc +" Test for py3eval with locals +func Test_python_pyeval_locals() + let str = 'a string' + let num = 0xbadb33f + let d = {'a': 1, 'b': 2, 'c': str} + let l = [ str, num, d ] + + let locals = #{ + \ s: str, + \ n: num, + \ d: d, + \ l: l, + \ } + + " check basics + call assert_equal('a string', pyeval('s', locals)) + call assert_equal(0xbadb33f, pyeval('n', locals)) + call assert_equal(d, pyeval('d', locals)) + call assert_equal(l, pyeval('l', locals)) + + py << trim EOF + def __UpdateDict(d, upd): + d.update(upd) + return d + + def __ExtendList(l, *args): + l.extend(*args) + return l + EOF + + " check assign to dict member works like bindeval + call assert_equal(3, pyeval('__UpdateDict( d, {"c": 3} )["c"]', locals)) + call assert_equal(3, d['c']) + + " check append lo list + call assert_equal(4, pyeval('len(__ExtendList(l, ["new item"]))', locals)) + call assert_equal("new item", l[-1]) + + " check calling a function + let StrLen = function('strlen') + call assert_equal(3, pyeval('f("abc")', {'f': StrLen})) +endfunc + " Test for vim.bindeval() func Test_python_vim_bindeval() " Float diff --git a/src/testdir/test_python3.vim b/src/testdir/test_python3.vim index 3178cffd6a..5e2b555be4 100644 --- a/src/testdir/test_python3.vim +++ b/src/testdir/test_python3.vim @@ -1027,6 +1027,52 @@ func Test_python3_pyeval() call AssertException(['let v = py3eval("vim")'], 'E859:') endfunc +" Test for py3eval with locals +func Test_python3_pyeval_locals() + let str = 'a string' + let num = 0xbadb33f + let d = {'a': 1, 'b': 2, 'c': str} + let l = [ str, num, d ] + + let locals = #{ + \ s: str, + \ n: num, + \ d: d, + \ l: l, + \ } + + " check basics + call assert_equal('a string', py3eval('s', locals)) + call assert_equal(0xbadb33f, py3eval('n', locals)) + call assert_equal(d, py3eval('d', locals)) + call assert_equal(l, py3eval('l', locals)) + call assert_equal('a,b,c', py3eval('b",".join(l)', {'l': ['a', 'b', 'c']})) + call assert_equal('hello', 's'->py3eval({'s': 'hello'})) + call assert_equal('a,b,c', 'b",".join(l)'->py3eval({'l': ['a', 'b', 'c']})) + + py3 << trim EOF + def __UpdateDict(d, upd): + d.update(upd) + return d + + def __ExtendList(l, *args): + l.extend(*args) + return l + EOF + + " check assign to dict member works like bindeval + call assert_equal(3, py3eval('__UpdateDict( d, {"c": 3} )["c"]', locals)) + call assert_equal(3, d['c']) + + " check append lo list + call assert_equal(4, py3eval('len(__ExtendList(l, ["new item"]))', locals)) + call assert_equal("new item", l[-1]) + + " check calling a function + let StrLen = function('strlen') + call assert_equal(3, py3eval('f("abc")', {'f': StrLen})) +endfunc + " Test for vim.bindeval() func Test_python3_vim_bindeval() " Float diff --git a/src/testdir/test_pyx2.vim b/src/testdir/test_pyx2.vim index 7432ceba4a..781bb41788 100644 --- a/src/testdir/test_pyx2.vim +++ b/src/testdir/test_pyx2.vim @@ -38,6 +38,49 @@ func Test_pyxeval() endfunc +" Test for pyxeval with locals +func Test_python_pyeval_locals() + let str = 'a string' + let num = 0xbadb33f + let d = {'a': 1, 'b': 2, 'c': str} + let l = [ str, num, d ] + + let locals = #{ + \ s: str, + \ n: num, + \ d: d, + \ l: l, + \ } + + " check basics + call assert_equal('a string', pyxeval('s', locals)) + call assert_equal(0xbadb33f, pyxeval('n', locals)) + call assert_equal(d, pyxeval('d', locals)) + call assert_equal(l, pyxeval('l', locals)) + + py << trim EOF + def __UpdateDict(d, upd): + d.update(upd) + return d + + def __ExtendList(l, *args): + l.extend(*args) + return l + EOF + + " check assign to dict member works like bindeval + call assert_equal(3, pyxeval('__UpdateDict( d, {"c": 3} )["c"]', locals)) + call assert_equal(3, d['c']) + + " check append lo list + call assert_equal(4, pyxeval('len(__ExtendList(l, ["new item"]))', locals)) + call assert_equal("new item", l[-1]) + + " check calling a function + let StrLen = function('strlen') + call assert_equal(3, pyxeval('f("abc")', {'f': StrLen})) +endfunc + func Test_pyxfile() " No special comments nor shebangs redir => var diff --git a/src/testdir/test_pyx3.vim b/src/testdir/test_pyx3.vim index 5d38420dc2..b34fdcbd7e 100644 --- a/src/testdir/test_pyx3.vim +++ b/src/testdir/test_pyx3.vim @@ -37,6 +37,48 @@ func Test_pyxeval() call assert_match(s:py3pattern, split(pyxeval('sys.version'))[0]) endfunc +" Test for pyxeval with locals +func Test_python_pyeval_locals() + let str = 'a string' + let num = 0xbadb33f + let d = {'a': 1, 'b': 2, 'c': str} + let l = [ str, num, d ] + + let locals = #{ + \ s: str, + \ n: num, + \ d: d, + \ l: l, + \ } + + " check basics + call assert_equal('a string', pyxeval('s', locals)) + call assert_equal(0xbadb33f, pyxeval('n', locals)) + call assert_equal(d, pyxeval('d', locals)) + call assert_equal(l, pyxeval('l', locals)) + + py3 << trim EOF + def __UpdateDict(d, upd): + d.update(upd) + return d + + def __ExtendList(l, *args): + l.extend(*args) + return l + EOF + + " check assign to dict member works like bindeval + call assert_equal(3, pyxeval('__UpdateDict( d, {"c": 3} )["c"]', locals)) + call assert_equal(3, d['c']) + + " check append lo list + call assert_equal(4, pyxeval('len(__ExtendList(l, ["new item"]))', locals)) + call assert_equal("new item", l[-1]) + + " check calling a function + let StrLen = function('strlen') + call assert_equal(3, pyxeval('f("abc")', {'f': StrLen})) +endfunc func Test_pyxfile() " No special comments nor shebangs diff --git a/src/testdir/test_vim9_python3.vim b/src/testdir/test_vim9_python3.vim new file mode 100644 index 0000000000..697b368035 --- /dev/null +++ b/src/testdir/test_vim9_python3.vim @@ -0,0 +1,17 @@ + +source check.vim +import './vim9.vim' as v9 +CheckFeature python3 + +def Test_python3_py3eval_locals() + var lines =<< trim EOF + var s = 'string' + var d = {'s': s} + assert_equal('string', py3eval('s', {'s': s})) + py3eval('d.update({"s": "new"})', {'d': d}) + assert_equal('new', d['s']) + EOF + v9.CheckDefAndScriptSuccess(lines) +enddef + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 7e95a46a77..3c42059260 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 */ +/**/ + 844, /**/ 843, /**/ From 715a58fda6ea719c1006348579bc545c6fde026a Mon Sep 17 00:00:00 2001 From: Aliaksei Budavei <0x000c70@gmail.com> Date: Wed, 6 Nov 2024 21:58:53 +0100 Subject: [PATCH 038/106] patch 9.1.0845: vimtutor shell script can be improved Problem: vimtutor shell script can be improved Solution: further improve the vimtutor shell script (Aliaksei Budavei) - Rewrite the script usage note. - Reconcile the usage help output with the manual page entry that describes the implementation in that: * a language code argument can be used alone or with its option key, e.g. "vimtutor -l nl" or "vimtutor nl"; * a chapter number argument cannot be used without its option key, e.g. "vimtutor -c 2". - Accept only chapters 1 or 2 as valid chapter arguments. - Double-quote instances of shell parameter expansion where neither pathname expansion nor field splitting is desired. - Prefer "$(foo)" to "`foo`" for command substitution. - Follow a single indentation style (see the modeline). closes: #15992 Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com> Signed-off-by: Christian Brabandt --- src/version.c | 2 + src/vimtutor | 194 +++++++++++++++++++++++++++----------------------- 2 files changed, 107 insertions(+), 89 deletions(-) diff --git a/src/version.c b/src/version.c index 3c42059260..22d1d2616d 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 */ +/**/ + 845, /**/ 844, /**/ diff --git a/src/vimtutor b/src/vimtutor index 6e29a76023..409c10c047 100755 --- a/src/vimtutor +++ b/src/vimtutor @@ -2,12 +2,13 @@ # Start Vim on a copy of the tutor file. -# Usage: vimtutor [-g] [xx] -# Where optional argument -g starts vimtutor in gvim (GUI) instead of vim. -# and xx is a language code like "es" or "nl". -# When an argument is given, it tries loading that tutor. -# When this fails or no argument was given, it tries using 'v:lang' -# When that also fails, it uses the English version. +# Type "man vimtutor" (or "vimtutor --help") to learn more about the supported +# command-line options. +# +# Tutors in several human languages are distributed. Type "vimtutor" to use +# a tutor in the language of the current locale (:help v:lang), if available; +# otherwise fall back to using the English tutor. To request any bundled +# tutor, specify its ISO639 name as an argument, e.g. "vimtutor nl". # Vim could be called "vim" or "vi". Also check for "vimN", for people who # have Vim installed with its version number. @@ -16,13 +17,13 @@ seq="vim vim91 vim90 vim81 vim80 vim8 vim74 vim73 vim72 vim71 vim70 vim7 vim6 vi usage() { echo "==USAGE=========================================================================================" - echo "${0##*/} [-(-l)anguage ISO639] [-(-c)hapter) NUMBER] [-(-g)ui] | [-(-h)elp] | [--list]" + echo "${0##*/} [[-(-l)anguage] ISO639] [-(-c)hapter NUMBER] [-(-g)ui] | [-(-h)elp] | [--list]" printf "\twhere:\n" printf "\t\tISO639 (default=en) is a 2 or 3 character language code\n" - printf "\t\tNUMBER (default=01) is one or two digits representing the chapter number\n" + printf "\t\tNUMBER (default=1) is a chapter number (1 or 2)\n" printf "\texamples:\n" printf "\t\tvimtutor -l es -c 2 -g\n" - printf "\t\tvimtutor --language de --chapter 02\n" + printf "\t\tvimtutor --language de --chapter 2\n" printf "\t\tvimtutor fr\n" echo "More information at 'man vimtutor'" echo "================================================================================================" @@ -72,111 +73,124 @@ en English\(default\) validateLang() { - case "$xx" in - '' | *[!a-z]* ) - echo "Error: iso639 code must contain only [a-z]" - exit 1 - esac - - case "${#xx}" in - [23] ) - ;; - * ) - echo "Error: iso639 code must be 2 or 3 characters only" - exit 1 - esac - - export xx + case "$xx" in + '' | *[!a-z]* ) + echo "Error: iso639 code must contain only [a-z]" + exit 1 + esac + + case "${#xx}" in + [23] ) + ;; + * ) + echo "Error: iso639 code must be 2 or 3 characters only" + exit 1 + esac + + export xx } validateChapter() { - case "$cc" in - '' | *[!0-9]* ) - echo "Error: chapter argument must contain digits only" - exit 1 - ;; - 0 | 00 ) - echo "Error: chapter must be non-zero" - exit 1 - esac - - export CHAPTER="$cc" + case "$cc" in + '' | *[!0-9]* ) + echo "Error: chapter argument must contain digits only" + exit 1 + ;; + [12] ) + ;; + * ) + echo "Error: invalid chapter number: [12]" + exit 1 + esac + + export CHAPTER="$cc" } while [ "$1" != "" ]; do - case "$1" in - -g | --gui ) seq="gvim gvim91 gvim90 gvim81 gvim80 gvim8 gvim74 gvim73 gvim72 gvim71 gvim70 gvim7 gvim6 $seq" - ;; - -l | --language ) shift - xx="$1" - validateLang - ;; - -l[a-z][a-z][a-z] | -l[a-z][a-z] ) - export xx="${1#*l}" - ;; - --language[a-z][a-z][a-z] | --language[a-z][a-z] ) - export xx="${1#*e}" - ;; - [a-z][a-z][a-z] | [a-z][a-z] ) export xx="$1" - ;; - -c | --chapter ) shift - cc="$1" - validateChapter - ;; - -c[1-9][0-9] | -c[1-9] ) export CHAPTER="${1#*c}" - ;; - --chapter[1-9][0-9] | --chapter[1-9] ) - export CHAPTER="${1#*r}" - ;; - -h | --help ) usage - exit - ;; - --list ) listOptions - exit - ;; - "" ) ;; - * ) usage - exit 1 - esac - shift + case "$1" in + -g | --gui ) + seq="gvim gvim91 gvim90 gvim81 gvim80 gvim8 gvim74 gvim73 gvim72 gvim71 gvim70 gvim7 gvim6 $seq" + ;; + -l | --language ) + shift + xx="$1" + validateLang + ;; + -l[a-z][a-z][a-z] | -l[a-z][a-z] ) + export xx="${1#*l}" + ;; + --language[a-z][a-z][a-z] | --language[a-z][a-z] ) + export xx="${1#*e}" + ;; + [a-z][a-z][a-z] | [a-z][a-z] ) + export xx="$1" + ;; + -c | --chapter ) + shift + cc="$1" + validateChapter + ;; + -c[12] ) + export CHAPTER="${1#*c}" + ;; + --chapter[12] ) + export CHAPTER="${1#*r}" + ;; + -h | --help ) + usage + exit + ;; + --list ) + listOptions + exit + ;; + "" ) + ;; + * ) + usage + exit 1 + esac + + shift done # We need a temp file for the copy. First try using a standard command. tmp="${TMPDIR-/tmp}" -TUTORCOPY=`mktemp $tmp/tutorXXXXXX || tempfile -p tutor || echo none` +# shellcheck disable=SC2186 +TUTORCOPY=$(mktemp "$tmp/tutorXXXXXX" || tempfile -p tutor || echo none) # If the standard commands failed then create a directory to put the copy in. # That is a secure way to make a temp file. if test "$TUTORCOPY" = none; then - tmpdir=$tmp/vimtutor$$ - OLD_UMASK=`umask` - umask 077 - getout=no - mkdir $tmpdir || getout=yes - umask $OLD_UMASK - if test $getout = yes; then - echo "Could not create directory for tutor copy, exiting." - exit 1 - fi - TUTORCOPY=$tmpdir/tutorcopy - touch $TUTORCOPY - TODELETE=$tmpdir + tmpdir="$tmp/vimtutor$$" + OLD_UMASK=$(umask) + umask 077 + getout=no + mkdir "$tmpdir" || getout=yes + umask "$OLD_UMASK" + if test "$getout" = yes; then + echo "Could not create directory for tutor copy, exiting." + exit 1 + fi + TUTORCOPY="$tmpdir/tutorcopy" + touch "$TUTORCOPY" + TODELETE="$tmpdir" else - TODELETE=$TUTORCOPY + TODELETE="$TUTORCOPY" fi export TUTORCOPY # remove the copy of the tutor on exit -trap "rm -rf $TODELETE" EXIT HUP INT QUIT SEGV PIPE TERM +trap 'rm -rf "$TODELETE"' EXIT HUP INT QUIT SEGV PIPE TERM for i in $seq; do testvim=$(command -v "$i" 2>/dev/null) if test -f "$testvim"; then - VIM=$i - break + VIM="$i" + break fi done @@ -189,7 +203,9 @@ fi # Use Vim to copy the tutor, it knows the value of $VIMRUNTIME # The script tutor.vim tells Vim which file to copy -$VIM -f -u NONE -c 'so $VIMRUNTIME/tutor/tutor.vim' +$VIM -f -u NONE -c "so \$VIMRUNTIME/tutor/tutor.vim" # Start vim without any .vimrc, set 'nocompatible' and 'showcmd' $VIM -f -u NONE -c "set nocp showcmd" "$TUTORCOPY" + +# vim:sw=4:ts=8:noet:nosta: From a063b22b3bbc1c7ad9d985b14d6e3c5b7c6e3eca Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Thu, 7 Nov 2024 14:30:30 +0100 Subject: [PATCH 039/106] runtime(netrw): prevent polluting the search history Signed-off-by: Christian Brabandt --- runtime/autoload/netrw.vim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index f8554c9dee..a15ca1c924 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -32,6 +32,7 @@ " 2024 Oct 30 by Vim Project: fix x mapping on cygwin (#13687) " 2024 Oct 31 by Vim Project: add netrw#Launch() and netrw#Open() (#15962) " 2024 Oct 31 by Vim Project: fix E874 when browsing remote dir (#15964) +" 2024 Nov 07 by Vim Project: use keeppatterns to prevent polluting the search history " }}} " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim @@ -9601,7 +9602,7 @@ fun! s:NetrwTreeListing(dirname) endif " update the dictionary for the current directory - exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$g@^\.\.\=/$@d _' + exe "sil! NetrwKeepj keepp ".w:netrw_bannercnt.',$g@^\.\.\=/$@d _' let w:netrw_treedict[a:dirname]= getline(w:netrw_bannercnt,line("$")) exe "sil! NetrwKeepj ".w:netrw_bannercnt.",$d _" @@ -10028,7 +10029,7 @@ fun! s:PerformListing(islocal) " resolve symbolic links if local and (thin or tree) if a:islocal && (w:netrw_liststyle == s:THINLIST || (exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST)) " call Decho("--resolve symbolic links if local and thin|tree",'~'.expand("")) - sil! g/@$/call s:ShowLink() + sil! keepp g/@$/call s:ShowLink() endif if exists("w:netrw_bannercnt") && (line("$") >= w:netrw_bannercnt || !g:netrw_banner) From 64a536d4fa17ec176f574a01543e483a163622eb Mon Sep 17 00:00:00 2001 From: Tom Benham Date: Thu, 7 Nov 2024 21:15:03 +0100 Subject: [PATCH 040/106] runtime(netrw): fix several bugs in netrw tree listing fixes: #5630 fixes: #9807 fixes: #14623 closes: #15996 Signed-off-by: Tom Benham Signed-off-by: Christian Brabandt --- runtime/autoload/netrw.vim | 1081 +++++------------------------------- 1 file changed, 141 insertions(+), 940 deletions(-) diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index a15ca1c924..6799a3444b 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -33,6 +33,7 @@ " 2024 Oct 31 by Vim Project: add netrw#Launch() and netrw#Open() (#15962) " 2024 Oct 31 by Vim Project: fix E874 when browsing remote dir (#15964) " 2024 Nov 07 by Vim Project: use keeppatterns to prevent polluting the search history +" 2024 Nov 07 by Vim Project: fix a few issues with netrw tree listing (#15996) " }}} " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim @@ -683,11 +684,8 @@ endif " == 4: Vexplore style == 5: Vexplore! " == 6: Texplore fun! netrw#Explore(indx,dosplit,style,...) -" call Dfunc("netrw#Explore(indx=".a:indx." dosplit=".a:dosplit." style=".a:style.",a:1<".a:1.">) &modified=".&modified." modifiable=".&modifiable." a:0=".a:0." win#".winnr()." buf#".bufnr("%")." ft=".&ft) -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("")) if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() -" call Decho("set b:netrw_curdir<".b:netrw_curdir."> (used getcwd)",'~'.expand("")) endif " record current file for Rexplore's benefit @@ -701,17 +699,11 @@ fun! netrw#Explore(indx,dosplit,style,...) if !exists("g:netrw_cygwin") && has("win32") let curdir= substitute(curdir,'\','/','g') endif -" call Decho("curdir<".curdir."> curfiledir<".curfiledir.">",'~'.expand("")) " using completion, directories with spaces in their names (thanks, Bill Gates, for a truly dumb idea) " will end up with backslashes here. Solution: strip off backslashes that precede white space and " try Explore again. if a:0 > 0 -" call Decho('considering retry: a:1<'.a:1.'>: '. - \ ((a:1 =~ "\\\s")? 'has backslash whitespace' : 'does not have backslash whitespace').', '. - \ ((filereadable(s:NetrwFile(a:1)))? 'is readable' : 'is not readable').', '. - \ ((isdirectory(s:NetrwFile(a:1))))? 'is a directory' : 'is not a directory', - \ '~'.expand("")) if a:1 =~ "\\\s" && !filereadable(s:NetrwFile(a:1)) && !isdirectory(s:NetrwFile(a:1)) let a1 = substitute(a:1, '\\\(\s\)', '\1', 'g') if a1 != a:1 @@ -779,64 +771,45 @@ fun! netrw#Explore(indx,dosplit,style,...) NetrwKeepj norm! 0 if a:0 > 0 -" call Decho("case [a:0=".a:0."] > 0: a:1<".a:1.">",'~'.expand("")) if a:1 =~ '^\~' && (has("unix") || (exists("g:netrw_cygwin") && g:netrw_cygwin)) -" call Decho("..case a:1<".a:1.">: starts with ~ and unix or cygwin",'~'.expand("")) let dirname= simplify(substitute(a:1,'\~',expand("$HOME"),'')) -" call Decho("..using dirname<".dirname."> (case: ~ && unix||cygwin)",'~'.expand("")) elseif a:1 == '.' -" call Decho("..case a:1<".a:1.">: matches .",'~'.expand("")) let dirname= simplify(exists("b:netrw_curdir")? b:netrw_curdir : getcwd()) if dirname !~ '/$' let dirname= dirname."/" endif -" call Decho("..using dirname<".dirname."> (case: ".(exists("b:netrw_curdir")? "b:netrw_curdir" : "getcwd()").")",'~'.expand("")) elseif a:1 =~ '\$' -" call Decho("..case a:1<".a:1.">: matches ending $",'~'.expand("")) let dirname= simplify(expand(a:1)) -" call Decho("..using user-specified dirname<".dirname."> with $env-var",'~'.expand("")) elseif a:1 !~ '^\*\{1,2}/' && a:1 !~ '^\a\{3,}://' -" call Decho("..case a:1<".a:1.">: other, not pattern or filepattern",'~'.expand("")) let dirname= simplify(a:1) -" call Decho("..using user-specified dirname<".dirname.">",'~'.expand("")) else -" call Decho("..case a:1: pattern or filepattern",'~'.expand("")) let dirname= a:1 endif else " clear explore -" call Decho("case a:0=".a:0.": clearing Explore list",'~'.expand("")) call s:NetrwClearExplore() -" call Dret("netrw#Explore : cleared list") return endif -" call Decho("dirname<".dirname.">",'~'.expand("")) if dirname =~ '\.\./\=$' let dirname= simplify(fnamemodify(dirname,':p:h')) elseif dirname =~ '\.\.' || dirname == '.' let dirname= simplify(fnamemodify(dirname,':p')) endif -" call Decho("dirname<".dirname."> (after simplify)",'~'.expand("")) if dirname =~ '^\*//' " starpat=1: Explore *//pattern (current directory only search for files containing pattern) -" call Decho("case starpat=1: Explore *//pattern",'~'.expand("")) let pattern= substitute(dirname,'^\*//\(.*\)$','\1','') let starpat= 1 -" call Decho("..Explore *//pat: (starpat=".starpat.") dirname<".dirname."> -> pattern<".pattern.">",'~'.expand("")) if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif elseif dirname =~ '^\*\*//' " starpat=2: Explore **//pattern (recursive descent search for files containing pattern) -" call Decho("case starpat=2: Explore **//pattern",'~'.expand("")) let pattern= substitute(dirname,'^\*\*//','','') let starpat= 2 -" call Decho("..Explore **//pat: (starpat=".starpat.") dirname<".dirname."> -> pattern<".pattern.">",'~'.expand("")) elseif dirname =~ '/\*\*/' " handle .../**/.../filepat -" call Decho("case starpat=4: Explore .../**/.../filepat",'~'.expand("")) let prefixdir= substitute(dirname,'^\(.\{-}\)\*\*.*$','\1','') if prefixdir =~ '^/' || (prefixdir =~ '^\a:/' && has("win32")) let b:netrw_curdir = prefixdir @@ -845,30 +818,23 @@ fun! netrw#Explore(indx,dosplit,style,...) endif let dirname= substitute(dirname,'^.\{-}\(\*\*/.*\)$','\1','') let starpat= 4 -" call Decho("..pwd<".getcwd()."> dirname<".dirname.">",'~'.expand("")) -" call Decho("..case Explore ../**/../filepat (starpat=".starpat.")",'~'.expand("")) elseif dirname =~ '^\*/' " case starpat=3: Explore */filepat (search in current directory for filenames matching filepat) let starpat= 3 -" call Decho("case starpat=3: Explore */filepat (starpat=".starpat.")",'~'.expand("")) elseif dirname=~ '^\*\*/' " starpat=4: Explore **/filepat (recursive descent search for filenames matching filepat) let starpat= 4 -" call Decho("case starpat=4: Explore **/filepat (starpat=".starpat.")",'~'.expand("")) else let starpat= 0 -" call Decho("case starpat=0: default",'~'.expand("")) endif if starpat == 0 && a:indx >= 0 " [Explore Hexplore Vexplore Sexplore] [dirname] -" call Decho("case starpat==0 && a:indx=".a:indx.": dirname<".dirname.">, handles Explore Hexplore Vexplore Sexplore",'~'.expand("")) if dirname == "" let dirname= curfiledir -" call Decho("..empty dirname, using current file's directory<".dirname.">",'~'.expand("")) endif if dirname =~# '^scp://' || dirname =~ '^ftp://' call netrw#Nread(2,dirname) @@ -884,10 +850,7 @@ fun! netrw#Explore(indx,dosplit,style,...) elseif dirname !~ '^/' let dirname= b:netrw_curdir."/".dirname endif -" call Decho("..calling LocalBrowseCheck(dirname<".dirname.">)",'~'.expand("")) call netrw#LocalBrowseCheck(dirname) -" call Decho(" modified=".&modified." modifiable=".&modifiable." readonly=".&readonly,'~'.expand("")) -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("")) endif if exists("w:netrw_bannercnt") " done to handle P08-Ingelrest. :Explore will _Always_ go to the line just after the banner. @@ -895,15 +858,6 @@ fun! netrw#Explore(indx,dosplit,style,...) exe w:netrw_bannercnt endif -" call Decho("curdir<".curdir.">",'~'.expand("")) - " --------------------------------------------------------------------- - " Jan 24, 2013: not sure why the following was present. See P08-Ingelrest -" if has("win32") || has("win95") || has("win64") || has("win16") -" NetrwKeepj call search('\<'.substitute(curdir,'^.*[/\\]','','e').'\>','cW') -" else -" NetrwKeepj call search('\<'.substitute(curdir,'^.*/','','e').'\>','cW') -" endif - " --------------------------------------------------------------------- " starpat=1: Explore *//pattern (current directory only search for files containing pattern) " starpat=2: Explore **//pattern (recursive descent search for files containing pattern) @@ -911,96 +865,75 @@ fun! netrw#Explore(indx,dosplit,style,...) " starpat=4: Explore **/filepat (recursive descent search for filenames matching filepat) elseif a:indx <= 0 " Nexplore, Pexplore, Explore: handle starpat -" call Decho("case a:indx<=0: Nexplore, Pexplore, , starpat=".starpat." a:indx=".a:indx,'~'.expand("")) if !mapcheck("","n") && !mapcheck("","n") && exists("b:netrw_curdir") -" call Decho("..set up and maps",'~'.expand("")) let s:didstarstar= 1 nnoremap :Pexplore nnoremap :Nexplore endif if has("path_extra") -" call Decho("..starpat=".starpat.": has +path_extra",'~'.expand("")) if !exists("w:netrw_explore_indx") let w:netrw_explore_indx= 0 endif let indx = a:indx -" call Decho("..starpat=".starpat.": set indx= [a:indx=".indx."]",'~'.expand("")) if indx == -1 " Nexplore -" call Decho("..case Nexplore with starpat=".starpat.": (indx=".indx.")",'~'.expand("")) if !exists("w:netrw_explore_list") " sanity check NetrwKeepj call netrw#ErrorMsg(s:WARNING,"using Nexplore or improperly; see help for netrw-starstar",40) if has("clipboard") && g:netrw_clipboard -" call Decho("(netrw#Explore) restore @* and @+",'~'.expand("")) if @* != keepregstar | sil! let @* = keepregstar | endif if @+ != keepregplus | sil! let @+ = keepregplus | endif endif sil! let @/ = keepregslash -" call Dret("netrw#Explore") return endif let indx= w:netrw_explore_indx if indx < 0 | let indx= 0 | endif if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif let curfile= w:netrw_explore_list[indx] -" call Decho("....indx=".indx." curfile<".curfile.">",'~'.expand("")) while indx < w:netrw_explore_listlen && curfile == w:netrw_explore_list[indx] let indx= indx + 1 -" call Decho("....indx=".indx." (Nexplore while loop)",'~'.expand("")) endwhile if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif -" call Decho("....Nexplore: indx= [w:netrw_explore_indx=".w:netrw_explore_indx."]=".indx,'~'.expand("")) elseif indx == -2 " Pexplore -" call Decho("case Pexplore with starpat=".starpat.": (indx=".indx.")",'~'.expand("")) if !exists("w:netrw_explore_list") " sanity check NetrwKeepj call netrw#ErrorMsg(s:WARNING,"using Pexplore or improperly; see help for netrw-starstar",41) if has("clipboard") && g:netrw_clipboard -" call Decho("(netrw#Explore) restore @* and @+",'~'.expand("")) if @* != keepregstar | sil! let @* = keepregstar | endif if @+ != keepregplus | sil! let @+ = keepregplus | endif endif sil! let @/ = keepregslash -" call Dret("netrw#Explore") return endif let indx= w:netrw_explore_indx if indx < 0 | let indx= 0 | endif if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif let curfile= w:netrw_explore_list[indx] -" call Decho("....indx=".indx." curfile<".curfile.">",'~'.expand("")) while indx >= 0 && curfile == w:netrw_explore_list[indx] let indx= indx - 1 -" call Decho("....indx=".indx." (Pexplore while loop)",'~'.expand("")) endwhile if indx < 0 | let indx= 0 | endif -" call Decho("....Pexplore: indx= [w:netrw_explore_indx=".w:netrw_explore_indx."]=".indx,'~'.expand("")) else " Explore -- initialize " build list of files to Explore with Nexplore/Pexplore -" call Decho("..starpat=".starpat.": case Explore: initialize (indx=".indx.")",'~'.expand("")) NetrwKeepj keepalt call s:NetrwClearExplore() let w:netrw_explore_indx= 0 if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() endif -" call Decho("....starpat=".starpat.": b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("")) " switch on starpat to build the w:netrw_explore_list of files if starpat == 1 " starpat=1: Explore *//pattern (current directory only search for files containing pattern) -" call Decho("..case starpat=".starpat.": build *//pattern list (curdir-only srch for files containing pattern) &hls=".&hls,'~'.expand("")) -" call Decho("....pattern<".pattern.">",'~'.expand("")) try exe "NetrwKeepj noautocmd vimgrep /".pattern."/gj ".fnameescape(b:netrw_curdir)."/*" catch /^Vim\%((\a\+)\)\=:E480/ keepalt call netrw#ErrorMsg(s:WARNING,"no match with pattern<".pattern.">",76) -" call Dret("netrw#Explore : unable to find pattern<".pattern.">") return endtry let w:netrw_explore_list = s:NetrwExploreListUniq(map(getqflist(),'bufname(v:val.bufnr)')) @@ -1008,20 +941,16 @@ fun! netrw#Explore(indx,dosplit,style,...) elseif starpat == 2 " starpat=2: Explore **//pattern (recursive descent search for files containing pattern) -" call Decho("..case starpat=".starpat.": build **//pattern list (recursive descent files containing pattern)",'~'.expand("")) -" call Decho("....pattern<".pattern.">",'~'.expand("")) try exe "sil NetrwKeepj noautocmd keepalt vimgrep /".pattern."/gj "."**/*" catch /^Vim\%((\a\+)\)\=:E480/ keepalt call netrw#ErrorMsg(s:WARNING,'no files matched pattern<'.pattern.'>',45) if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif if has("clipboard") && g:netrw_clipboard -" call Decho("(netrw#Explore) restore @* and @+",'~'.expand("")) if @* != keepregstar | sil! let @* = keepregstar | endif if @+ != keepregplus | sil! let @+ = keepregplus | endif endif sil! let @/ = keepregslash -" call Dret("netrw#Explore : no files matched pattern") return endtry let s:netrw_curdir = b:netrw_curdir @@ -1031,56 +960,43 @@ fun! netrw#Explore(indx,dosplit,style,...) elseif starpat == 3 " starpat=3: Explore */filepat (search in current directory for filenames matching filepat) -" call Decho("..case starpat=".starpat.": build */filepat list (curdir-only srch filenames matching filepat) &hls=".&hls,'~'.expand("")) let filepat= substitute(dirname,'^\*/','','') let filepat= substitute(filepat,'^[%#<]','\\&','') -" call Decho("....b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("")) -" call Decho("....filepat<".filepat.">",'~'.expand("")) let w:netrw_explore_list= s:NetrwExploreListUniq(split(expand(b:netrw_curdir."/".filepat),'\n')) if &hls | let keepregslash= s:ExplorePatHls(filepat) | endif elseif starpat == 4 " starpat=4: Explore **/filepat (recursive descent search for filenames matching filepat) -" call Decho("..case starpat=".starpat.": build **/filepat list (recursive descent srch filenames matching filepat) &hls=".&hls,'~'.expand("")) let w:netrw_explore_list= s:NetrwExploreListUniq(split(expand(b:netrw_curdir."/".dirname),'\n')) if &hls | let keepregslash= s:ExplorePatHls(dirname) | endif endif " switch on starpat to build w:netrw_explore_list let w:netrw_explore_listlen = len(w:netrw_explore_list) -" call Decho("....w:netrw_explore_list<".string(w:netrw_explore_list).">",'~'.expand("")) -" call Decho("....w:netrw_explore_listlen=".w:netrw_explore_listlen,'~'.expand("")) if w:netrw_explore_listlen == 0 || (w:netrw_explore_listlen == 1 && w:netrw_explore_list[0] =~ '\*\*\/') keepalt NetrwKeepj call netrw#ErrorMsg(s:WARNING,"no files matched",42) if has("clipboard") && g:netrw_clipboard -" call Decho("(netrw#Explore) restore @* and @+",'~'.expand("")) if @* != keepregstar | sil! let @* = keepregstar | endif if @+ != keepregplus | sil! let @+ = keepregplus | endif endif sil! let @/ = keepregslash -" call Dret("netrw#Explore : no files matched") return endif endif " if indx ... endif " NetrwStatusLine support - for exploring support let w:netrw_explore_indx= indx -" call Decho("....w:netrw_explore_list<".join(w:netrw_explore_list,',')."> len=".w:netrw_explore_listlen,'~'.expand("")) " wrap the indx around, but issue a note if indx >= w:netrw_explore_listlen || indx < 0 -" call Decho("....wrap indx (indx=".indx." listlen=".w:netrw_explore_listlen.")",'~'.expand("")) let indx = (indx < 0)? ( w:netrw_explore_listlen - 1 ) : 0 let w:netrw_explore_indx= indx keepalt NetrwKeepj call netrw#ErrorMsg(s:NOTE,"no more files match Explore pattern",43) endif exe "let dirfile= w:netrw_explore_list[".indx."]" -" call Decho("....dirfile=w:netrw_explore_list[indx=".indx."]= <".dirfile.">",'~'.expand("")) let newdir= substitute(dirfile,'/[^/]*$','','e') -" call Decho("....newdir<".newdir.">",'~'.expand("")) -" call Decho("....calling LocalBrowseCheck(newdir<".newdir.">)",'~'.expand("")) call netrw#LocalBrowseCheck(newdir) if !exists("w:netrw_liststyle") let w:netrw_liststyle= g:netrw_liststyle @@ -1094,25 +1010,20 @@ fun! netrw#Explore(indx,dosplit,style,...) let w:netrw_explore_bufnr = bufnr("%") let w:netrw_explore_line = line(".") keepalt NetrwKeepj call s:SetupNetrwStatusLine('%f %h%m%r%=%9*%{NetrwStatusLine()}') -" call Decho("....explore: mtchcnt=".w:netrw_explore_mtchcnt." bufnr=".w:netrw_explore_bufnr." line#".w:netrw_explore_line,'~'.expand("")) else -" call Decho("..your vim does not have +path_extra",'~'.expand("")) if !exists("g:netrw_quiet") keepalt NetrwKeepj call netrw#ErrorMsg(s:WARNING,"your vim needs the +path_extra feature for Exploring with **!",44) endif if has("clipboard") && g:netrw_clipboard -" call Decho("(netrw#Explore) restore @* and @+",'~'.expand("")) if @* != keepregstar | sil! let @* = keepregstar | endif if @+ != keepregplus | sil! let @+ = keepregplus | endif endif sil! let @/ = keepregslash -" call Dret("netrw#Explore : missing +path_extra") return endif else -" call Decho("..default case: Explore newdir<".dirname.">",'~'.expand("")) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && dirname =~ '/' sil! unlet w:netrw_treedict sil! unlet w:netrw_treetop @@ -1121,18 +1032,14 @@ fun! netrw#Explore(indx,dosplit,style,...) if !exists("b:netrw_curdir") NetrwKeepj call netrw#LocalBrowseCheck(getcwd()) else - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,newdir)) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,newdir,0)) endif endif " visual display of **/ **// */ Exploration files -" call Decho("w:netrw_explore_indx=".(exists("w:netrw_explore_indx")? w:netrw_explore_indx : "doesn't exist"),'~'.expand("")) -" call Decho("b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "n/a").">",'~'.expand("")) if exists("w:netrw_explore_indx") && exists("b:netrw_curdir") -" call Decho("s:explore_prvdir<".(exists("s:explore_prvdir")? s:explore_prvdir : "-doesn't exist-"),'~'.expand("")) if !exists("s:explore_prvdir") || s:explore_prvdir != b:netrw_curdir " only update match list when current directory isn't the same as before -" call Decho("only update match list when current directory not the same as before",'~'.expand("")) let s:explore_prvdir = b:netrw_curdir let s:explore_match = "" let dirlen = strlen(b:netrw_curdir) @@ -1141,7 +1048,6 @@ fun! netrw#Explore(indx,dosplit,style,...) endif let prvfname= "" for fname in w:netrw_explore_list -" call Decho("fname<".fname.">",'~'.expand("")) if fname =~ '^'.b:netrw_curdir if s:explore_match == "" let s:explore_match= '\<'.escape(strpart(fname,dirlen),g:netrw_markfileesc).'\>' @@ -1157,7 +1063,6 @@ fun! netrw#Explore(indx,dosplit,style,...) endif let prvfname= fname endfor -" call Decho("explore_match<".s:explore_match.">",'~'.expand("")) if has("syntax") && exists("g:syntax_on") && g:syntax_on exe "2match netrwMarkFile /".s:explore_match."/" endif @@ -1167,7 +1072,6 @@ fun! netrw#Explore(indx,dosplit,style,...) 2match none if exists("s:explore_match") | unlet s:explore_match | endif if exists("s:explore_prvdir") | unlet s:explore_prvdir | endif -" call Decho("cleared explore match list",'~'.expand("")) endif " since Explore may be used to initialize netrw's browser, @@ -1175,12 +1079,10 @@ fun! netrw#Explore(indx,dosplit,style,...) " Consequently, set s:netrw_events to 2. let s:netrw_events= 2 if has("clipboard") && g:netrw_clipboard -" call Decho("(netrw#Explore) restore @* and @+",'~'.expand("")) if @* != keepregstar | sil! let @* = keepregstar | endif if @+ != keepregplus | sil! let @+ = keepregplus | endif endif sil! let @/ = keepregslash -" call Dret("netrw#Explore : @/<".@/.">") endfun " --------------------------------------------------------------------- @@ -2819,36 +2721,27 @@ endfun " netrw#SetTreetop: resets the tree top to the current directory/specified directory {{{2 " (implements the :Ntree command) fun! netrw#SetTreetop(iscmd,...) -" call Dfunc("netrw#SetTreetop(iscmd=".a:iscmd." ".((a:0 > 0)? a:1 : "").") a:0=".a:0) -" call Decho("w:netrw_treetop<".w:netrw_treetop.">") " iscmd==0: netrw#SetTreetop called using gn mapping " iscmd==1: netrw#SetTreetop called using :Ntree from the command line -" call Decho("(iscmd=".a:iscmd.": called using :Ntree from command line",'~'.expand("")) " clear out the current tree if exists("w:netrw_treetop") -" call Decho("clearing out current tree",'~'.expand("")) let inittreetop= w:netrw_treetop unlet w:netrw_treetop endif if exists("w:netrw_treedict") -" call Decho("freeing w:netrw_treedict",'~'.expand("")) unlet w:netrw_treedict endif -" call Decho("inittreetop<".(exists("inittreetop")? inittreetop : "n/a").">") if (a:iscmd == 0 || a:1 == "") && exists("inittreetop") let treedir = s:NetrwTreePath(inittreetop) -" call Decho("treedir<".treedir.">",'~'.expand("")) else if isdirectory(s:NetrwFile(a:1)) -" call Decho("a:1<".a:1."> is a directory",'~'.expand("")) let treedir = a:1 let s:netrw_treetop = treedir elseif exists("b:netrw_curdir") && (isdirectory(s:NetrwFile(b:netrw_curdir."/".a:1)) || a:1 =~ '^\a\{3,}://') let treedir = b:netrw_curdir."/".a:1 let s:netrw_treetop = treedir -" call Decho("a:1<".a:1."> is NOT a directory, using treedir<".treedir.">",'~'.expand("")) else " normally the cursor is left in the message window. " However, here this results in the directory being listed in the message window, which is not wanted. @@ -2859,20 +2752,17 @@ fun! netrw#SetTreetop(iscmd,...) let s:netrw_treetop = getcwd() endif endif -" call Decho("treedir<".treedir.">",'~'.expand("")) " determine if treedir is remote or local let islocal= expand("%") !~ '^\a\{3,}://' -" call Decho("islocal=".islocal,'~'.expand("")) " browse the resulting directory if islocal - call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(islocal,treedir)) + call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(islocal,treedir,0)) else - call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,treedir)) + call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,treedir,0)) endif -" call Dret("netrw#SetTreetop") endfun " =========================================== @@ -3730,16 +3620,11 @@ endfun " Often called via: Explore/e dirname/etc -> netrw#LocalBrowseCheck() -> s:NetrwBrowse() fun! s:NetrwBrowse(islocal,dirname) if !exists("w:netrw_liststyle")|let w:netrw_liststyle= g:netrw_liststyle|endif -" call Dfunc("s:NetrwBrowse(islocal=".a:islocal." dirname<".a:dirname.">) liststyle=".w:netrw_liststyle." ".g:loaded_netrw." buf#".bufnr("%")."<".bufname("%")."> win#".winnr()) -" call Decho("fyi: modified=".&modified." modifiable=".&modifiable." readonly=".&readonly,'~'.expand("")) -" call Decho("fyi: tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("")) -" call Dredir("ls!","s:NetrwBrowse") " save alternate-file's filename if w:netrw_rexlocal doesn't exist " This is useful when one edits a local file, then :e ., then :Rex if a:islocal && !exists("w:netrw_rexfile") && bufname("#") != "" let w:netrw_rexfile= bufname("#") -" call Decho("setting w:netrw_rexfile<".w:netrw_rexfile."> win#".winnr(),'~'.expand("")) endif " s:NetrwBrowse : initialize history {{{3 @@ -3750,32 +3635,26 @@ fun! s:NetrwBrowse(islocal,dirname) " s:NetrwBrowse : simplify the dirname (especially for ".."s in dirnames) {{{3 if a:dirname !~ '^\a\{3,}://' let dirname= simplify(a:dirname) -" call Decho("simplified dirname<".dirname.">") else let dirname= a:dirname endif " repoint t:netrw_lexbufnr if appropriate if exists("t:netrw_lexbufnr") && bufnr("%") == t:netrw_lexbufnr -" call Decho("set repointlexbufnr to true!") let repointlexbufnr= 1 endif " s:NetrwBrowse : sanity checks: {{{3 if exists("s:netrw_skipbrowse") unlet s:netrw_skipbrowse -" call Decho(" ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." filename<".expand("%")."> win#".winnr()." ft<".&ft.">",'~'.expand("")) -" call Dret("s:NetrwBrowse : s:netrw_skipbrowse existed") return endif if !exists("*shellescape") NetrwKeepj call netrw#ErrorMsg(s:ERROR,"netrw can't run -- your vim is missing shellescape()",69) -" call Dret("s:NetrwBrowse : missing shellescape()") return endif if !exists("*fnameescape") NetrwKeepj call netrw#ErrorMsg(s:ERROR,"netrw can't run -- your vim is missing fnameescape()",70) -" call Dret("s:NetrwBrowse : missing fnameescape()") return endif @@ -3785,53 +3664,39 @@ fun! s:NetrwBrowse(islocal,dirname) " s:NetrwBrowse : re-instate any marked files {{{3 if has("syntax") && exists("g:syntax_on") && g:syntax_on if exists("s:netrwmarkfilelist_{bufnr('%')}") -" call Decho("clearing marked files",'~'.expand("")) exe "2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/" endif endif if a:islocal && exists("w:netrw_acdkeep") && w:netrw_acdkeep " s:NetrwBrowse : set up "safe" options for local directory/file {{{3 -" call Decho("handle w:netrw_acdkeep:",'~'.expand("")) -" call Decho("NetrwKeepj lcd ".fnameescape(dirname)." (due to w:netrw_acdkeep=".w:netrw_acdkeep." - acd=".&acd.")",'~'.expand("")) if s:NetrwLcd(dirname) -" call Dret("s:NetrwBrowse : lcd failure") return endif - " call s:NetrwOptionsSafe() " tst952 failed with this enabled. -" call Decho("getcwd<".getcwd().">",'~'.expand("")) elseif !a:islocal && dirname !~ '[\/]$' && dirname !~ '^"' " s:NetrwBrowse : remote regular file handler {{{3 -" call Decho("handle remote regular file: dirname<".dirname.">",'~'.expand("")) if bufname(dirname) != "" -" call Decho("edit buf#".bufname(dirname)." in win#".winnr(),'~'.expand("")) exe "NetrwKeepj b ".bufname(dirname) else " attempt transfer of remote regular file -" call Decho("attempt transfer as regular file<".dirname.">",'~'.expand("")) " remove any filetype indicator from end of dirname, except for the " "this is a directory" indicator (/). " There shouldn't be one of those here, anyway. let path= substitute(dirname,'[*=@|]\r\=$','','e') -" call Decho("new path<".path.">",'~'.expand("")) call s:RemotePathAnalysis(dirname) " s:NetrwBrowse : remote-read the requested file into current buffer {{{3 call s:NetrwEnew(dirname) call s:NetrwOptionsSafe(a:islocal) setl ma noro -" call Decho("setl ma noro",'~'.expand("")) let b:netrw_curdir = dirname let url = s:method."://".((s:user == "")? "" : s:user."@").s:machine.(s:port ? ":".s:port : "")."/".s:path call s:NetrwBufRename(url) exe "sil! NetrwKeepj keepalt doau BufReadPre ".fnameescape(s:fname) sil call netrw#NetRead(2,url) " netrw.vim and tar.vim have already handled decompression of the tarball; avoiding gzip.vim error -" call Decho("url<".url.">",'~'.expand("")) -" call Decho("s:path<".s:path.">",'~'.expand("")) -" call Decho("s:fname<".s:fname.">",'~'.expand("")) if s:path =~ '.bz2' exe "sil NetrwKeepj keepalt doau BufReadPost ".fnameescape(substitute(s:fname,'\.bz2$','','')) elseif s:path =~ '.gz' @@ -3846,11 +3711,7 @@ fun! s:NetrwBrowse(islocal,dirname) " s:NetrwBrowse : save certain window-oriented variables into buffer-oriented variables {{{3 call s:SetBufWinVars() call s:NetrwOptionsRestore("w:") -" call Decho("setl ma nomod",'~'.expand("")) setl ma nomod noro -" call Decho(" ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) - -" call Dret("s:NetrwBrowse : file<".s:fname.">") return endif @@ -3866,33 +3727,31 @@ fun! s:NetrwBrowse(islocal,dirname) NetrwKeepj call s:NetrwMenu(1) " get/set-up buffer {{{3 -" call Decho("saving position across a buffer refresh",'~'.expand("")) let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) + + " NetrwGetBuffer might change buffers but s:rexposn_X was set for the + " previous buffer + let prevbufnr = bufnr('%') let reusing= s:NetrwGetBuffer(a:islocal,dirname) + if exists("s:rexposn_".prevbufnr) + let s:rexposn_{bufnr('%')} = s:rexposn_{prevbufnr} + endif " maintain markfile highlighting if has("syntax") && exists("g:syntax_on") && g:syntax_on if exists("s:netrwmarkfilemtch_{bufnr('%')}") && s:netrwmarkfilemtch_{bufnr("%")} != "" -" " call Decho("bufnr(%)=".bufnr('%'),'~'.expand("")) -" " call Decho("exe 2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/",'~'.expand("")) exe "2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/" else -" " call Decho("2match none",'~'.expand("")) 2match none endif endif if reusing && line("$") > 1 call s:NetrwOptionsRestore("w:") -" call Decho("setl noma nomod nowrap",'~'.expand("")) setl noma nomod nowrap -" call Decho("(set noma nomod nowrap) ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) -" call Dret("s:NetrwBrowse : re-using not-cleared buffer") return endif " set b:netrw_curdir to the new directory name {{{3 -" call Decho("set b:netrw_curdir to the new directory name<".dirname."> (buf#".bufnr("%").")",'~'.expand("")) let b:netrw_curdir= dirname if b:netrw_curdir =~ '[/\\]$' let b:netrw_curdir= substitute(b:netrw_curdir,'[/\\]$','','e') @@ -3913,24 +3772,18 @@ fun! s:NetrwBrowse(islocal,dirname) if !a:islocal && b:netrw_curdir !~ '/$' let b:netrw_curdir= b:netrw_curdir.'/' endif -" call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("")) " ------------ " (local only) {{{3 " ------------ if a:islocal -" call Decho("local only:",'~'.expand("")) - " Set up ShellCmdPost handling. Append current buffer to browselist call s:LocalFastBrowser() " handle g:netrw_keepdir: set vim's current directory to netrw's notion of the current directory {{{3 if !g:netrw_keepdir -" call Decho("handle g:netrw_keepdir=".g:netrw_keepdir.": getcwd<".getcwd()."> acd=".&acd,'~'.expand("")) -" call Decho("l:acd".(exists("&l:acd")? "=".&l:acd : " doesn't exist"),'~'.expand("")) if !exists("&l:acd") || !&l:acd if s:NetrwLcd(b:netrw_curdir) -" call Dret("s:NetrwBrowse : lcd failure") return endif endif @@ -3940,23 +3793,18 @@ fun! s:NetrwBrowse(islocal,dirname) " remote handling: {{{3 " -------------------------------- else -" call Decho("remote only:",'~'.expand("")) " analyze dirname and g:netrw_list_cmd {{{3 -" call Decho("b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "doesn't exist")."> dirname<".dirname.">",'~'.expand("")) if dirname =~# "^NetrwTreeListing\>" let dirname= b:netrw_curdir -" call Decho("(dirname was ) dirname<".dirname.">",'~'.expand("")) elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("b:netrw_curdir") let dirname= substitute(b:netrw_curdir,'\\','/','g') if dirname !~ '/$' let dirname= dirname.'/' endif let b:netrw_curdir = dirname -" call Decho("(liststyle is TREELIST) dirname<".dirname.">",'~'.expand("")) else let dirname = substitute(dirname,'\\','/','g') -" call Decho("(normal) dirname<".dirname.">",'~'.expand("")) endif let dirpat = '^\(\w\{-}\)://\(\w\+@\)\=\([^/]\+\)/\(.*\)$' @@ -3965,14 +3813,10 @@ fun! s:NetrwBrowse(islocal,dirname) NetrwKeepj call netrw#ErrorMsg(s:ERROR,"netrw doesn't understand your dirname<".dirname.">",20) endif NetrwKeepj call s:NetrwOptionsRestore("w:") -" call Decho("setl noma nomod nowrap",'~'.expand("")) setl noma nomod nowrap -" call Decho(" ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) -" call Dret("s:NetrwBrowse : badly formatted dirname<".dirname.">") return endif let b:netrw_curdir= dirname -" call Decho("b:netrw_curdir<".b:netrw_curdir."> (remote)",'~'.expand("")) endif " (additional remote handling) " ------------------------------- @@ -3984,12 +3828,10 @@ fun! s:NetrwBrowse(islocal,dirname) " restore option(s) call s:NetrwOptionsRestore("w:") -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("")) " If there is a rexposn: restore position with rexposn " Otherwise : set rexposn if exists("s:rexposn_".bufnr("%")) -" call Decho("restoring posn to s:rexposn_".bufnr('%')."<".string(s:rexposn_{bufnr('%')}).">",'~'.expand("")) NetrwKeepj call winrestview(s:rexposn_{bufnr('%')}) if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt NetrwKeepj exe w:netrw_bannercnt @@ -3999,28 +3841,22 @@ fun! s:NetrwBrowse(islocal,dirname) endif if v:version >= 700 && has("balloon_eval") && &beval == 0 && &l:bexpr == "" && !exists("g:netrw_nobeval") let &l:bexpr= "netrw#BalloonHelp()" -" call Decho("set up balloon help: l:bexpr=".&l:bexpr,'~'.expand("")) setl beval endif " repoint t:netrw_lexbufnr if appropriate if exists("repointlexbufnr") let t:netrw_lexbufnr= bufnr("%") -" call Decho("repoint t:netrw_lexbufnr to #".t:netrw_lexbufnr) endif " restore position if reusing -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) call winrestview(svpos) endif " The s:LocalBrowseRefresh() function is called by an autocmd " installed by s:LocalFastBrowser() when g:netrw_fastbrowse <= 1 (ie. slow or medium speed). " However, s:NetrwBrowse() causes the FocusGained event to fire the first time. -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("")) -" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) -" call Dret("s:NetrwBrowse : did PerformListing ft<".&ft.">") return endfun @@ -4513,41 +4349,30 @@ endfun " islocal=0: remote browsing " =1: local browsing fun! s:NetrwListStyle(islocal) -" call Dfunc("NetrwListStyle(islocal=".a:islocal.") w:netrw_liststyle=".w:netrw_liststyle) - let ykeep = @@ let fname = s:NetrwGetWord() if !exists("w:netrw_liststyle")|let w:netrw_liststyle= g:netrw_liststyle|endif let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let w:netrw_liststyle = (w:netrw_liststyle + 1) % s:MAXLIST -" call Decho("fname<".fname.">",'~'.expand("")) -" call Decho("chgd w:netrw_liststyle to ".w:netrw_liststyle,'~'.expand("")) -" call Decho("b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "doesn't exist").">",'~'.expand("")) " repoint t:netrw_lexbufnr if appropriate if exists("t:netrw_lexbufnr") && bufnr("%") == t:netrw_lexbufnr -" call Decho("set repointlexbufnr to true!") let repointlexbufnr= 1 endif if w:netrw_liststyle == s:THINLIST " use one column listing -" call Decho("use one column list",'~'.expand("")) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') elseif w:netrw_liststyle == s:LONGLIST " use long list -" call Decho("use long list",'~'.expand("")) let g:netrw_list_cmd = g:netrw_list_cmd." -l" elseif w:netrw_liststyle == s:WIDELIST " give wide list -" call Decho("use wide list",'~'.expand("")) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST -" call Decho("use tree list",'~'.expand("")) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') else @@ -4557,25 +4382,19 @@ fun! s:NetrwListStyle(islocal) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') endif setl ma noro -" call Decho("setl ma noro",'~'.expand("")) " clear buffer - this will cause NetrwBrowse/LocalBrowseCheck to do a refresh -" call Decho("clear buffer<".expand("%")."> with :%d",'~'.expand("")) sil! NetrwKeepj %d _ " following prevents tree listing buffer from being marked "modified" -" call Decho("setl nomod",'~'.expand("")) setl nomod -" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) " refresh the listing -" call Decho("refresh the listing",'~'.expand("")) - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call s:NetrwCursor(0) " repoint t:netrw_lexbufnr if appropriate if exists("repointlexbufnr") let t:netrw_lexbufnr= bufnr("%") -" call Decho("repoint t:netrw_lexbufnr to #".t:netrw_lexbufnr) endif " restore position; keep cursor on the filename @@ -4583,22 +4402,18 @@ fun! s:NetrwListStyle(islocal) NetrwKeepj call winrestview(svpos) let @@= ykeep -" call Dret("NetrwListStyle".(exists("w:netrw_liststyle")? ' : w:netrw_liststyle='.w:netrw_liststyle : "")) endfun " --------------------------------------------------------------------- " s:NetrwBannerCtrl: toggles the display of the banner {{{2 fun! s:NetrwBannerCtrl(islocal) -" call Dfunc("s:NetrwBannerCtrl(islocal=".a:islocal.") g:netrw_banner=".g:netrw_banner) - let ykeep= @@ " toggle the banner (enable/suppress) let g:netrw_banner= !g:netrw_banner " refresh the listing let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) " keep cursor on the filename if g:netrw_banner && exists("w:netrw_bannercnt") && line(".") >= w:netrw_bannercnt @@ -4626,24 +4441,20 @@ endfun " " With bang: deletes files/directories from Netrw's bookmark system fun! s:NetrwBookmark(del,...) -" call Dfunc("s:NetrwBookmark(del=".a:del.",...) a:0=".a:0) if a:0 == 0 if &ft == "netrw" let curbufnr = bufnr("%") if exists("s:netrwmarkfilelist_{curbufnr}") " for every filename in the marked list -" call Decho("bookmark every filename in marked list",'~'.expand("")) let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let islocal= expand("%") !~ '^\a\{3,}://' for fname in s:netrwmarkfilelist_{curbufnr} if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif endfor let curdir = exists("b:netrw_curdir")? b:netrw_curdir : getcwd() call s:NetrwUnmarkList(curbufnr,curdir) - NetrwKeepj call s:NetrwRefresh(islocal,s:NetrwBrowseChgDir(islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(islocal,s:NetrwBrowseChgDir(islocal,'./',0)) NetrwKeepj call winrestview(svpos) else let fname= s:NetrwGetWord() @@ -4652,7 +4463,6 @@ fun! s:NetrwBookmark(del,...) else " bookmark currently open file -" call Decho("bookmark currently open file",'~'.expand("")) let fname= expand("%") if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif endif @@ -4663,7 +4473,6 @@ fun! s:NetrwBookmark(del,...) " by deciding if the current file begins with an url " Globbing cannot be done remotely. let islocal= expand("%") !~ '^\a\{3,}://' -" call Decho("bookmark specified file".((a:0>1)? "s" : ""),'~'.expand("")) let i = 1 while i <= a:0 if islocal @@ -4675,9 +4484,7 @@ fun! s:NetrwBookmark(del,...) else let mbfiles= [a:{i}] endif -" call Decho("mbfiles".string(mbfiles),'~'.expand("")) for mbfile in mbfiles -" call Decho("mbfile<".mbfile.">",'~'.expand("")) if a:del|call s:DeleteBookmark(mbfile)|else|call s:MakeBookmark(mbfile)|endif endfor let i= i + 1 @@ -4686,8 +4493,6 @@ fun! s:NetrwBookmark(del,...) " update the menu call s:NetrwBookmarkMenu() - -" call Dret("s:NetrwBookmark") endfun " --------------------------------------------------------------------- @@ -4759,58 +4564,55 @@ endfun " directory and a new directory name. Also, if the " "new directory name" is actually a file, " NetrwBrowseChgDir() edits the file. -fun! s:NetrwBrowseChgDir(islocal,newdir,...) -" call Dfunc("s:NetrwBrowseChgDir(islocal=".a:islocal."> newdir<".a:newdir.">) a:0=".a:0." win#".winnr()." curpos<".string(getpos("."))."> b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "").">") -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("")) - +" cursor=0: newdir is relative to b:netrw_curdir +" =1: newdir is relative to the path to the word under the cursor in +" tree view +fun! s:NetrwBrowseChgDir(islocal,newdir,cursor,...) let ykeep= @@ if !exists("b:netrw_curdir") " Don't try to change-directory: this can happen, for example, when netrw#ErrorMsg has been called " and the current window is the NetrwMessage window. let @@= ykeep -" call Decho("b:netrw_curdir doesn't exist!",'~'.expand("")) -" call Decho("getcwd<".getcwd().">",'~'.expand("")) -" call Dredir("ls!","s:NetrwBrowseChgDir") -" call Dret("s:NetrwBrowseChgDir") return endif -" call Decho("b:netrw_curdir<".b:netrw_curdir.">") " NetrwBrowseChgDir; save options and initialize {{{3 -" call Decho("saving options",'~'.expand("")) call s:SavePosn(s:netrw_posn) NetrwKeepj call s:NetrwOptionsSave("s:") NetrwKeepj call s:NetrwOptionsSafe(a:islocal) - if has("win32") - let dirname = substitute(b:netrw_curdir,'\\','/','ge') + + let newdir = a:newdir + if a:cursor && exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treetop") + " dirname is the path to the word under the cursor + let dirname = s:NetrwTreePath(w:netrw_treetop) + " Remove trailing "/" + let dirname = substitute(dirname, "/$", "", "") + + " If the word under the cursor is a directory (except for ../), NetrwTreePath + " returns the full path, including the word under the cursor, remove it + if newdir =~ "/$" && newdir != "../" + let dirname = fnamemodify(dirname, ":h") + endif else let dirname = b:netrw_curdir endif - let newdir = a:newdir + if has("win32") + let dirname = substitute(dirname,'\\','/','ge') + endif let dolockout = 0 let dorestore = 1 -" call Decho("win#".winnr(),'~'.expand("")) -" call Decho("dirname<".dirname.">",'~'.expand("")) -" call Decho("newdir<".newdir.">",'~'.expand("")) " ignore s when done in the banner -" call Decho('(s:NetrwBrowseChgDir) ignore [return]s when done in banner (g:netrw_banner='.g:netrw_banner.")",'~'.expand("")) if g:netrw_banner -" call Decho("win#".winnr()." w:netrw_bannercnt=".(exists("w:netrw_bannercnt")? w:netrw_bannercnt : 'n/a')." line(.)#".line('.')." line($)#".line("#"),'~'.expand("")) if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt && line("$") >= w:netrw_bannercnt if getline(".") =~# 'Quick Help' -" call Decho("#1: quickhelp=".g:netrw_quickhelp." ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) let g:netrw_quickhelp= (g:netrw_quickhelp + 1)%len(s:QuickHelp) -" call Decho("#2: quickhelp=".g:netrw_quickhelp." ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) setl ma noro nowrap NetrwKeepj call setline(line('.'),'" Quick Help: :help '.s:QuickHelp[g:netrw_quickhelp]) setl noma nomod nowrap NetrwKeepj call s:NetrwOptionsRestore("s:") -" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) endif endif -" else " Decho -" call Decho("g:netrw_banner=".g:netrw_banner." (no banner)",'~'.expand("")) endif " set up o/s-dependent directory recognition pattern @@ -4819,69 +4621,45 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) else let dirpat= '[\/]$' endif -" call Decho("set up o/s-dependent directory recognition pattern: dirname<".dirname."> dirpat<".dirpat.">",'~'.expand("")) if dirname !~ dirpat " apparently vim is "recognizing" that it is in a directory and " is removing the trailing "/". Bad idea, so let's put it back. let dirname= dirname.'/' -" call Decho("adjusting dirname<".dirname.'> (put trailing "/" back)','~'.expand("")) endif -" call Decho("[newdir<".newdir."> ".((newdir =~ dirpat)? "=~" : "!~")." dirpat<".dirpat.">] && [islocal=".a:islocal."] && [newdir is ".(isdirectory(s:NetrwFile(newdir))? "" : "not ")."a directory]",'~'.expand("")) if newdir !~ dirpat && !(a:islocal && isdirectory(s:NetrwFile(s:ComposePath(dirname,newdir)))) " ------------------------------ " NetrwBrowseChgDir: edit a file {{{3 " ------------------------------ -" call Decho('edit-a-file: case "handling a file": win#'.winnr().' newdir<'.newdir.'> !~ dirpat<'.dirpat.">",'~'.expand("")) " save position for benefit of Rexplore let s:rexposn_{bufnr("%")}= winsaveview() -" call Decho("edit-a-file: saving posn to s:rexposn_".bufnr("%")."<".string(s:rexposn_{bufnr("%")}).">",'~'.expand("")) -" call Decho("edit-a-file: win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> ft=".&ft,'~'.expand("")) -" call Decho("edit-a-file: w:netrw_liststyle=".(exists("w:netrw_liststyle")? w:netrw_liststyle : 'n/a')." w:netrw_treedict:".(exists("w:netrw_treedict")? "exists" : 'n/a')." newdir<".newdir.">",'~'.expand("")) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") && newdir !~ '^\(/\|\a:\)' -" call Decho("edit-a-file: handle tree listing: w:netrw_treedict<".(exists("w:netrw_treedict")? string(w:netrw_treedict) : 'n/a').">",'~'.expand("")) -" call Decho("edit-a-file: newdir<".newdir.">",'~'.expand("")) -" let newdir = s:NetrwTreePath(s:netrw_treetop) -" call Decho("edit-a-file: COMBAK why doesn't this recognize file1's directory???") - let dirname= s:NetrwTreeDir(a:islocal) - "COMBAK : not working for a symlink -- but what about a regular file? a directory? -" call Decho("COMBAK : not working for a symlink -- but what about a regular file? a directory?") - " Feb 17, 2019: following if-else-endif restored -- wasn't editing a file in tree mode if dirname =~ '/$' let dirname= dirname.newdir else let dirname= dirname."/".newdir endif -" call Decho("edit-a-file: dirname<".dirname.">",'~'.expand("")) -" call Decho("edit-a-file: tree listing",'~'.expand("")) elseif newdir =~ '^\(/\|\a:\)' -" call Decho("edit-a-file: handle an url or path starting with /: <".newdir.">",'~'.expand("")) let dirname= newdir else let dirname= s:ComposePath(dirname,newdir) endif -" call Decho("edit-a-file: handling a file: dirname<".dirname."> (a:0=".a:0.")",'~'.expand("")) " this lets netrw#BrowseX avoid the edit if a:0 < 1 -" call Decho("edit-a-file: (a:0=".a:0."<1) set up windows for editing<".fnameescape(dirname)."> didsplit=".(exists("s:didsplit")? s:didsplit : "doesn't exist"),'~'.expand("")) NetrwKeepj call s:NetrwOptionsRestore("s:") let curdir= b:netrw_curdir if !exists("s:didsplit") -" " call Decho("edit-a-file: s:didsplit does not exist; g:netrw_browse_split=".string(g:netrw_browse_split)." win#".winnr()." g:netrw_chgwin=".g:netrw_chgwin",'~'.expand("")) if type(g:netrw_browse_split) == 3 " open file in server " Note that g:netrw_browse_split is a List: [servername,tabnr,winnr] -" call Decho("edit-a-file: open file in server",'~'.expand("")) call s:NetrwServerEdit(a:islocal,dirname) -" call Dret("s:NetrwBrowseChgDir") return elseif g:netrw_browse_split == 1 " horizontally splitting the window first -" call Decho("edit-a-file: horizontally splitting window prior to edit",'~'.expand("")) let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize exe "keepalt ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s" if !&ea @@ -4891,7 +4669,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) elseif g:netrw_browse_split == 2 " vertically splitting the window first -" call Decho("edit-a-file: vertically splitting window prior to edit",'~'.expand("")) let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize exe "keepalt ".(g:netrw_alto? "top " : "bot ")."vert ".winsz."wincmd s" if !&ea @@ -4901,7 +4678,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) elseif g:netrw_browse_split == 3 " open file in new tab -" call Decho("edit-a-file: opening new tab prior to edit",'~'.expand("")) keepalt tabnew if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() @@ -4910,21 +4686,17 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) elseif g:netrw_browse_split == 4 " act like "P" (ie. open previous window) -" call Decho("edit-a-file: use previous window for edit",'~'.expand("")) if s:NetrwPrevWinOpen(2) == 3 let @@= ykeep -" call Dret("s:NetrwBrowseChgDir") return endif call s:SetRexDir(a:islocal,curdir) else " handling a file, didn't split, so remove menu -" call Decho("edit-a-file: handling a file+didn't split, so remove menu",'~'.expand("")) call s:NetrwMenu(0) " optional change to window if g:netrw_chgwin >= 1 -" call Decho("edit-a-file: changing window to #".g:netrw_chgwin.": (due to g:netrw_chgwin)",'~'.expand("")) if winnr("$")+1 == g:netrw_chgwin " if g:netrw_chgwin is set to one more than the last window, then " vertically split the last window to make that window available. @@ -4948,21 +4720,17 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) let dolockout= 1 endif if a:islocal -" call Decho("edit-a-file: edit local file: exe e! ".fnameescape(dirname),'~'.expand("")) " some like c-^ to return to the last edited file " others like c-^ to return to the netrw buffer " Apr 30, 2020: used to have e! here. That can cause loss of a modified file, " so emit error E37 instead. call s:NetrwEditFile("e","",dirname) -" call Decho("edit-a-file: after e ".dirname.": hidden=".&hidden." bufhidden<".&bufhidden."> mod=".&mod,'~'.expand("")) - " COMBAK -- cuc cul related call s:NetrwCursor(1) if &hidden || &bufhidden == "hide" " file came from vim's hidden storage. Don't "restore" options with it. let dorestore= 0 endif else -" call Decho("edit-a-file: remote file: NetrwBrowse will edit it",'~'.expand("")) endif " handle g:Netrw_funcref -- call external-to-netrw functions @@ -4970,12 +4738,9 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " or as a list of function references. It will ignore anything that's not " a function reference. See :help Funcref for information about function references. if exists("g:Netrw_funcref") -" call Decho("edit-a-file: handle optional Funcrefs",'~'.expand("")) if type(g:Netrw_funcref) == 2 -" call Decho("edit-a-file: handling a g:Netrw_funcref",'~'.expand("")) NetrwKeepj call g:Netrw_funcref() elseif type(g:Netrw_funcref) == 3 -" call Decho("edit-a-file: handling a list of g:Netrw_funcrefs",'~'.expand("")) for Fncref in g:Netrw_funcref if type(Fncref) == 2 NetrwKeepj call Fncref() @@ -4989,7 +4754,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " ---------------------------------------------------- " NetrwBrowseChgDir: just go to the new directory spec {{{3 " ---------------------------------------------------- -" call Decho('goto-newdir: case "just go to new directory spec": newdir<'.newdir.'>','~'.expand("")) let dirname = newdir NetrwKeepj call s:SetRexDir(a:islocal,dirname) NetrwKeepj call s:NetrwOptionsRestore("s:") @@ -4999,7 +4763,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " --------------------------------------------- " NetrwBrowseChgDir: refresh the directory list {{{3 " --------------------------------------------- -" call Decho('(s:NetrwBrowseChgDir)refresh-dirlist: case "refresh directory listing": newdir == "./"','~'.expand("")) NetrwKeepj call s:SetRexDir(a:islocal,dirname) norm! m` @@ -5007,26 +4770,21 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " -------------------------------------- " NetrwBrowseChgDir: go up one directory {{{3 " -------------------------------------- -" call Decho('(s:NetrwBrowseChgDir)go-up: case "go up one directory": newdir == "../"','~'.expand("")) if w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") " force a refresh -" call Decho("go-up: clear buffer<".expand("%")."> with :%d",'~'.expand("")) -" call Decho("go-up: setl noro ma",'~'.expand("")) setl noro ma NetrwKeepj %d _ endif if has("amiga") " amiga -" call Decho('go-up: case "go up one directory": newdir == "../" and amiga','~'.expand("")) if a:islocal let dirname= substitute(dirname,'^\(.*[/:]\)\([^/]\+$\)','\1','') let dirname= substitute(dirname,'/$','','') else let dirname= substitute(dirname,'^\(.*[/:]\)\([^/]\+/$\)','\1','') endif -" call Decho("go-up: amiga: dirname<".dirname."> (go up one dir)",'~'.expand("")) elseif !g:netrw_cygwin && has("win32") " windows @@ -5041,11 +4799,9 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) if dirname =~ '^\a:$' let dirname= dirname.'/' endif -" call Decho("go-up: windows: dirname<".dirname."> (go up one dir)",'~'.expand("")) else " unix or cygwin -" call Decho('(s:NetrwBrowseChgDir)go-up: case "go up one directory": newdir == "../" and unix or cygwin','~'.expand("")) if a:islocal let dirname= substitute(dirname,'^\(.*\)/\([^/]\+\)/$','\1','') if dirname == "" @@ -5054,7 +4810,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) else let dirname= substitute(dirname,'^\(\a\{3,}://.\{-}/\{1,2}\)\(.\{-}\)\([^/]\+\)/$','\1\2','') endif -" call Decho("go-up: unix: dirname<".dirname."> (go up one dir)",'~'.expand("")) endif NetrwKeepj call s:SetRexDir(a:islocal,dirname) norm! m` @@ -5063,69 +4818,48 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " -------------------------------------- " NetrwBrowseChgDir: Handle Tree Listing {{{3 " -------------------------------------- -" call Decho('(s:NetrwBrowseChgDir)tree-list: case liststyle is TREELIST and w:netrw_treedict exists','~'.expand("")) " force a refresh (for TREELIST, NetrwTreeDir() will force the refresh) -" call Decho("tree-list: setl noro ma",'~'.expand("")) setl noro ma if !(exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("b:netrw_curdir")) -" call Decho("tree-list: clear buffer<".expand("%")."> with :%d (force refresh)",'~'.expand("")) NetrwKeepj %d _ endif let treedir = s:NetrwTreeDir(a:islocal) -" call Decho("tree-list: treedir<".treedir.">",'~'.expand("")) let s:treecurpos = winsaveview() let haskey = 0 -" call Decho("tree-list: w:netrw_treedict<".string(w:netrw_treedict).">",'~'.expand("")) " search treedict for tree dir as-is -" call Decho("tree-list: search treedict for tree dir as-is",'~'.expand("")) if has_key(w:netrw_treedict,treedir) -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched for treedir<'.treedir.'> : found it!','~'.expand("")) let haskey= 1 else -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched for treedir<'.treedir.'> : not found','~'.expand("")) endif " search treedict for treedir with a [/@] appended -" call Decho("tree-list: search treedict for treedir with a [/@] appended",'~'.expand("")) if !haskey && treedir !~ '[/@]$' if has_key(w:netrw_treedict,treedir."/") let treedir= treedir."/" -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched.for treedir<'.treedir.'> found it!','~'.expand("")) let haskey = 1 else -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched for treedir<'.treedir.'/> : not found','~'.expand("")) endif endif " search treedict for treedir with any trailing / elided -" call Decho("tree-list: search treedict for treedir with any trailing / elided",'~'.expand("")) if !haskey && treedir =~ '/$' let treedir= substitute(treedir,'/$','','') if has_key(w:netrw_treedict,treedir) -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched.for treedir<'.treedir.'> found it!','~'.expand("")) let haskey = 1 else -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched for treedir<'.treedir.'> : not found','~'.expand("")) endif endif -" call Decho("haskey=".haskey,'~'.expand("")) if haskey " close tree listing for selected subdirectory -" call Decho("tree-list: closing selected subdirectory<".dirname.">",'~'.expand("")) call remove(w:netrw_treedict,treedir) -" call Decho("tree-list: removed entry<".treedir."> from treedict",'~'.expand("")) -" call Decho("tree-list: yielding treedict<".string(w:netrw_treedict).">",'~'.expand("")) let dirname= w:netrw_treetop else " go down one directory let dirname= substitute(treedir,'/*$','/','') -" call Decho("tree-list: go down one dir: treedir<".treedir.">",'~'.expand("")) -" call Decho("tree-list: ... : dirname<".dirname.">",'~'.expand("")) endif NetrwKeepj call s:SetRexDir(a:islocal,dirname) -" call Decho("setting s:treeforceredraw to true",'~'.expand("")) let s:treeforceredraw = 1 else @@ -5133,7 +4867,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " NetrwBrowseChgDir: Go down one directory {{{3 " ---------------------------------------- let dirname = s:ComposePath(dirname,newdir) -" call Decho("go down one dir: dirname<".dirname."> newdir<".newdir.">",'~'.expand("")) NetrwKeepj call s:SetRexDir(a:islocal,dirname) norm! m` endif @@ -5144,29 +4877,18 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) if dorestore " dorestore is zero'd when a local file was hidden or bufhidden; " in such a case, we want to keep whatever settings it may have. -" call Decho("doing option restore (dorestore=".dorestore.")",'~'.expand("")) NetrwKeepj call s:NetrwOptionsRestore("s:") -" else " Decho -" call Decho("skipping option restore (dorestore==0): hidden=".&hidden." bufhidden=".&bufhidden." mod=".&mod,'~'.expand("")) endif if dolockout && dorestore -" call Decho("restore: filewritable(dirname<".dirname.">)=".filewritable(dirname),'~'.expand("")) if filewritable(dirname) -" call Decho("restore: doing modification lockout settings: ma nomod noro",'~'.expand("")) -" call Decho("restore: setl ma nomod noro",'~'.expand("")) setl ma noro nomod -" call Decho("restore: ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) else -" call Decho("restore: doing modification lockout settings: ma nomod ro",'~'.expand("")) -" call Decho("restore: setl ma nomod noro",'~'.expand("")) setl ma ro nomod -" call Decho("restore: ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) endif endif call s:RestorePosn(s:netrw_posn) let @@= ykeep -" call Dret("s:NetrwBrowseChgDir <".dirname."> : curpos<".string(getpos(".")).">") return dirname endfun @@ -5175,19 +4897,16 @@ endfun " for thin, long, and wide: cursor placed just after banner " for tree, keeps cursor on current filename fun! s:NetrwBrowseUpDir(islocal) -" call Dfunc("s:NetrwBrowseUpDir(islocal=".a:islocal.")") if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt-1 " this test needed because occasionally this function seems to be incorrectly called " when multiple leftmouse clicks are taken when atop the one line help in the banner. " I'm allowing the very bottom line to permit a "-" exit so that one may escape empty " directories. -" call Dret("s:NetrwBrowseUpDir : cursor not in file area") return endif norm! 0 if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") -" call Decho("case: treestyle",'~'.expand("")) let curline= getline(".") let swwline= winline() - 1 if exists("w:netrw_treetop") @@ -5201,22 +4920,18 @@ fun! s:NetrwBrowseUpDir(islocal) let curfile = getline(".") let curpath = s:NetrwTreePath(w:netrw_treetop) if a:islocal - call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../')) + call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../',0)) else - call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../')) + call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../',0)) endif -" call Decho("looking for curfile<^".s:treedepthstring.curfile.">",'~'.expand("")) -" call Decho("having curpath<".curpath.">",'~'.expand("")) if w:netrw_treetop == '/' keepj call search('^\M'.curfile,"w") elseif curfile == '../' keepj call search('^\M'.curfile,"wb") else -" call Decho("search(^\\M".s:treedepthstring.curfile.") backwards")) while 1 keepj call search('^\M'.s:treedepthstring.curfile,"wb") let treepath= s:NetrwTreePath(w:netrw_treetop) -" call Decho("..current treepath<".treepath.">",'~'.expand("")) if treepath == curpath break endif @@ -5224,7 +4939,6 @@ fun! s:NetrwBrowseUpDir(islocal) endif else -" call Decho("case: not treestyle",'~'.expand("")) call s:SavePosn(s:netrw_posn) if exists("b:netrw_curdir") let curdir= b:netrw_curdir @@ -5232,16 +4946,15 @@ fun! s:NetrwBrowseUpDir(islocal) let curdir= expand(getcwd()) endif if a:islocal - call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../')) + call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../',0)) else - call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../')) + call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../',0)) endif call s:RestorePosn(s:netrw_posn) let curdir= substitute(curdir,'^.*[\/]','','') let curdir= '\<'. escape(curdir, '~'). '/' call search(curdir,'wc') endif -" call Dret("s:NetrwBrowseUpDir") endfun func s:redir() @@ -5574,23 +5287,20 @@ endfun " --------------------------------------------------------------------- " s:NetrwChgPerm: (implements "gp") change file permission {{{2 fun! s:NetrwChgPerm(islocal,curdir) -" call Dfunc("s:NetrwChgPerm(islocal=".a:islocal." curdir<".a:curdir.">)") let ykeep = @@ call inputsave() let newperm= input("Enter new permission: ") call inputrestore() let chgperm= substitute(g:netrw_chgperm,'\',s:ShellEscape(expand("")),'') let chgperm= substitute(chgperm,'\',s:ShellEscape(newperm),'') -" call Decho("chgperm<".chgperm.">",'~'.expand("")) call system(chgperm) if v:shell_error != 0 NetrwKeepj call netrw#ErrorMsg(1,"changing permission on file<".expand("")."> seems to have failed",75) endif if a:islocal - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) endif let @@= ykeep -" call Dret("s:NetrwChgPerm") endfun " --------------------------------------------------------------------- @@ -5671,8 +5381,6 @@ endfun " --------------------------------------------------------------------- " s:NetrwExploreListUniq: {{{2 fun! s:NetrwExploreListUniq(explist) -" call Dfunc("s:NetrwExploreListUniq(explist<".string(a:explist).">)") - " this assumes that the list is already sorted let newexplist= [] for member in a:explist @@ -5681,15 +5389,12 @@ fun! s:NetrwExploreListUniq(explist) let newexplist = newexplist + [ member ] endif endfor - -" call Dret("s:NetrwExploreListUniq newexplist<".string(newexplist).">") return newexplist endfun " --------------------------------------------------------------------- " s:NetrwForceChgDir: (gd support) Force treatment as a directory {{{2 fun! s:NetrwForceChgDir(islocal,newdir) -" call Dfunc("s:NetrwForceChgDir(islocal=".a:islocal." newdir<".a:newdir.">)") let ykeep= @@ if a:newdir !~ '/$' " ok, looks like force is needed to get directory-style treatment @@ -5700,15 +5405,13 @@ fun! s:NetrwForceChgDir(islocal,newdir) else let newdir= a:newdir.'/' endif -" call Decho("adjusting newdir<".newdir."> due to gd",'~'.expand("")) else " should already be getting treatment as a directory let newdir= a:newdir endif - let newdir= s:NetrwBrowseChgDir(a:islocal,newdir) + let newdir= s:NetrwBrowseChgDir(a:islocal,newdir,0) call s:NetrwBrowse(a:islocal,newdir) let @@= ykeep -" call Dret("s:NetrwForceChgDir") endfun " --------------------------------------------------------------------- @@ -5754,18 +5457,16 @@ endfun " --------------------------------------------------------------------- " s:NetrwForceFile: (gf support) Force treatment as a file {{{2 fun! s:NetrwForceFile(islocal,newfile) -" call Dfunc("s:NetrwForceFile(islocal=".a:islocal." newdir<".a:newfile.">)") if a:newfile =~ '[/@*=|\\]$' let newfile= substitute(a:newfile,'.$','','') else let newfile= a:newfile endif if a:islocal - call s:NetrwBrowseChgDir(a:islocal,newfile) + call s:NetrwBrowseChgDir(a:islocal,newfile,0) else - call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,newfile)) + call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,newfile,0)) endif -" call Dret("s:NetrwForceFile") endfun " --------------------------------------------------------------------- @@ -5776,24 +5477,18 @@ endfun " 1: show not-hidden files " 2: show hidden files only fun! s:NetrwHide(islocal) -" call Dfunc("NetrwHide(islocal=".a:islocal.") g:netrw_hide=".g:netrw_hide) let ykeep= @@ let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) if exists("s:netrwmarkfilelist_{bufnr('%')}") -" call Decho("((g:netrw_hide == 1)? "unhide" : "hide")." files in markfilelist<".string(s:netrwmarkfilelist_{bufnr("%")}).">",'~'.expand("")) -" call Decho("g:netrw_list_hide<".g:netrw_list_hide.">",'~'.expand("")) " hide the files in the markfile list for fname in s:netrwmarkfilelist_{bufnr("%")} -" call Decho("match(g:netrw_list_hide<".g:netrw_list_hide.'> fname<\<'.fname.'\>>)='.match(g:netrw_list_hide,'\<'.fname.'\>')." l:isk=".&l:isk,'~'.expand("")) if match(g:netrw_list_hide,'\<'.fname.'\>') != -1 " remove fname from hiding list let g:netrw_list_hide= substitute(g:netrw_list_hide,'..\<'.escape(fname,g:netrw_fname_escape).'\>..','','') let g:netrw_list_hide= substitute(g:netrw_list_hide,',,',',','g') let g:netrw_list_hide= substitute(g:netrw_list_hide,'^,\|,$','','') -" call Decho("unhide: g:netrw_list_hide<".g:netrw_list_hide.">",'~'.expand("")) else " append fname to hiding list if exists("g:netrw_list_hide") && g:netrw_list_hide != "" @@ -5801,7 +5496,6 @@ fun! s:NetrwHide(islocal) else let g:netrw_list_hide= '\<'.escape(fname,g:netrw_fname_escape).'\>' endif -" call Decho("hide: g:netrw_list_hide<".g:netrw_list_hide.">",'~'.expand("")) endif endfor NetrwKeepj call s:NetrwUnmarkList(bufnr("%"),b:netrw_curdir) @@ -5815,64 +5509,49 @@ fun! s:NetrwHide(islocal) if g:netrw_hide && g:netrw_list_hide == "" NetrwKeepj call netrw#ErrorMsg(s:WARNING,"your hiding list is empty!",49) let @@= ykeep -" call Dret("NetrwHide") return endif endif - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep -" call Dret("NetrwHide") endfun " --------------------------------------------------------------------- " s:NetrwHideEdit: allows user to edit the file/directory hiding list {{{2 fun! s:NetrwHideEdit(islocal) -" call Dfunc("NetrwHideEdit(islocal=".a:islocal.")") - let ykeep= @@ " save current cursor position let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) " get new hiding list from user call inputsave() let newhide= input("Edit Hiding List: ",g:netrw_list_hide) call inputrestore() let g:netrw_list_hide= newhide -" call Decho("new g:netrw_list_hide<".g:netrw_list_hide.">",'~'.expand("")) " refresh the listing - sil NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,"./")) + sil NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,"./",0)) " restore cursor position -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) call winrestview(svpos) let @@= ykeep - -" call Dret("NetrwHideEdit") endfun " --------------------------------------------------------------------- " s:NetrwHidden: invoked by "gh" {{{2 fun! s:NetrwHidden(islocal) -" call Dfunc("s:NetrwHidden()") let ykeep= @@ " save current position let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) if g:netrw_list_hide =~ '\(^\|,\)\\(^\\|\\s\\s\\)\\zs\\.\\S\\+' " remove .file pattern from hiding list -" call Decho("remove .file pattern from hiding list",'~'.expand("")) let g:netrw_list_hide= substitute(g:netrw_list_hide,'\(^\|,\)\\(^\\|\\s\\s\\)\\zs\\.\\S\\+','','') elseif s:Strlen(g:netrw_list_hide) >= 1 -" call Decho("add .file pattern from hiding list",'~'.expand("")) let g:netrw_list_hide= g:netrw_list_hide . ',\(^\|\s\s\)\zs\.\S\+' else -" call Decho("set .file pattern as hiding list",'~'.expand("")) let g:netrw_list_hide= '\(^\|\s\s\)\zs\.\S\+' endif if g:netrw_list_hide =~ '^,' @@ -5880,11 +5559,9 @@ fun! s:NetrwHidden(islocal) endif " refresh screen and return to saved position - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep -" call Dret("s:NetrwHidden") endfun " --------------------------------------------------------------------- @@ -5934,7 +5611,6 @@ fun! s:NetrwLeftmouse(islocal) if &ft != "netrw" return endif -" call Dfunc("s:NetrwLeftmouse(islocal=".a:islocal.")") let ykeep= @@ " check if the status bar was clicked on instead of a file/directory name @@ -5946,36 +5622,30 @@ fun! s:NetrwLeftmouse(islocal) let mouse_lnum = v:mouse_lnum let wlastline = line('w$') let lastline = line('$') -" call Decho("v:mouse_lnum=".mouse_lnum." line(w$)=".wlastline." line($)=".lastline." v:mouse_win=".v:mouse_win." winnr#".winnr(),'~'.expand("")) -" call Decho("v:mouse_col =".v:mouse_col." col=".col(".")." wincol =".wincol()." winwidth =".winwidth(0),'~'.expand("")) if mouse_lnum >= wlastline + 1 || v:mouse_win != winnr() " appears to be a status bar leftmouse click let @@= ykeep -" call Dret("s:NetrwLeftmouse : detected a status bar leftmouse click") return endif " Dec 04, 2013: following test prevents leftmouse selection/deselection of directories and files in treelist mode " Windows are separated by vertical separator bars - but the mouse seems to be doing what it should when dragging that bar " without this test when its disabled. " May 26, 2014: edit file, :Lex, resize window -- causes refresh. Reinstated a modified test. See if problems develop. -" call Decho("v:mouse_col=".v:mouse_col." col#".col('.')." virtcol#".virtcol('.')." col($)#".col("$")." virtcol($)#".virtcol("$"),'~'.expand("")) if v:mouse_col > virtcol('.') let @@= ykeep -" call Dret("s:NetrwLeftmouse : detected a vertical separator bar leftmouse click") return endif if a:islocal if exists("b:netrw_curdir") - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord())) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1)) endif else if exists("b:netrw_curdir") - NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord())) + NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)) endif endif let @@= ykeep -" call Dret("s:NetrwLeftmouse") endfun " --------------------------------------------------------------------- @@ -5984,9 +5654,7 @@ fun! s:NetrwCLeftmouse(islocal) if &ft != "netrw" return endif -" call Dfunc("s:NetrwCLeftmouse(islocal=".a:islocal.")") call s:NetrwMarkFileTgt(a:islocal) -" call Dret("s:NetrwCLeftmouse") endfun " --------------------------------------------------------------------- @@ -5999,39 +5667,30 @@ fun! s:NetrwServerEdit(islocal,fname) " call Dfunc("s:NetrwServerEdit(islocal=".a:islocal.",fname<".a:fname.">)") let islocal = a:islocal%2 " =0: remote =1: local let ctrlr = a:islocal >= 2 " =0: not used =1: used -" call Decho("islocal=".islocal." ctrlr=".ctrlr,'~'.expand("")) if (islocal && isdirectory(s:NetrwFile(a:fname))) || (!islocal && a:fname =~ '/$') " handle directories in the local window -- not in the remote vim server " user must have closed the NETRWSERVER window. Treat as normal editing from netrw. -" call Decho("handling directory in client window",'~'.expand("")) let g:netrw_browse_split= 0 if exists("s:netrw_browse_split") && exists("s:netrw_browse_split_".winnr()) let g:netrw_browse_split= s:netrw_browse_split_{winnr()} unlet s:netrw_browse_split_{winnr()} endif - call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname)) -" call Dret("s:NetrwServerEdit") + call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname,0)) return endif -" call Decho("handling file in server window",'~'.expand("")) if has("clientserver") && executable("gvim") -" call Decho("has clientserver and gvim",'~'.expand("")) if exists("g:netrw_browse_split") && type(g:netrw_browse_split) == 3 -" call Decho("g:netrw_browse_split=".string(g:netrw_browse_split),'~'.expand("")) let srvrname = g:netrw_browse_split[0] let tabnum = g:netrw_browse_split[1] let winnum = g:netrw_browse_split[2] if serverlist() !~ '\<'.srvrname.'\>' -" call Decho("server not available; ctrlr=".ctrlr,'~'.expand("")) - if !ctrlr " user must have closed the server window and the user did not use , but " used something like . -" call Decho("user must have closed server AND did not use ctrl-r",'~'.expand("")) if exists("g:netrw_browse_split") unlet g:netrw_browse_split endif @@ -6039,50 +5698,40 @@ fun! s:NetrwServerEdit(islocal,fname) if exists("s:netrw_browse_split_".winnr()) let g:netrw_browse_split= s:netrw_browse_split_{winnr()} endif - call s:NetrwBrowseChgDir(islocal,a:fname) -" call Dret("s:NetrwServerEdit") + call s:NetrwBrowseChgDir(islocal,a:fname,0) return elseif has("win32") && executable("start") " start up remote netrw server under windows -" call Decho("starting up gvim server<".srvrname."> for windows",'~'.expand("")) call system("start gvim --servername ".srvrname) else " start up remote netrw server under linux -" call Decho("starting up gvim server<".srvrname.">",'~'.expand("")) call system("gvim --servername ".srvrname) endif endif -" call Decho("srvrname<".srvrname."> tabnum=".tabnum." winnum=".winnum." server-editing<".a:fname.">",'~'.expand("")) call remote_send(srvrname,":tabn ".tabnum."\") call remote_send(srvrname,":".winnum."wincmd w\") call remote_send(srvrname,":e ".fnameescape(s:NetrwFile(a:fname))."\") - else if serverlist() !~ '\<'.g:netrw_servername.'\>' if !ctrlr -" call Decho("server<".g:netrw_servername."> not available and ctrl-r not used",'~'.expand("")) if exists("g:netrw_browse_split") unlet g:netrw_browse_split endif let g:netrw_browse_split= 0 - call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname)) -" call Dret("s:NetrwServerEdit") + call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname,0)) return else -" call Decho("server<".g:netrw_servername."> not available but ctrl-r used",'~'.expand("")) if has("win32") && executable("start") " start up remote netrw server under windows -" call Decho("starting up gvim server<".g:netrw_servername."> for windows",'~'.expand("")) call system("start gvim --servername ".g:netrw_servername) else " start up remote netrw server under linux -" call Decho("starting up gvim server<".g:netrw_servername.">",'~'.expand("")) call system("gvim --servername ".g:netrw_servername) endif endif @@ -6090,7 +5739,6 @@ fun! s:NetrwServerEdit(islocal,fname) while 1 try -" call Decho("remote-send: e ".a:fname,'~'.expand("")) call remote_send(g:netrw_servername,":e ".fnameescape(s:NetrwFile(a:fname))."\") break catch /^Vim\%((\a\+)\)\=:E241/ @@ -6111,7 +5759,6 @@ fun! s:NetrwServerEdit(islocal,fname) call netrw#ErrorMsg(s:ERROR,"you need a gui-capable vim and client-server to use ",98) endif -" call Dret("s:NetrwServerEdit") endfun " --------------------------------------------------------------------- @@ -6235,7 +5882,6 @@ endfun " s:NetrwMakeDir: this function makes a directory (both local and remote) {{{2 " implements the "d" mapping. fun! s:NetrwMakeDir(usrhost) -" call Dfunc("s:NetrwMakeDir(usrhost<".a:usrhost.">)") let ykeep= @@ " get name of new directory from user. A bare will skip. @@ -6244,27 +5890,22 @@ fun! s:NetrwMakeDir(usrhost) call inputsave() let newdirname= input("Please give directory name: ") call inputrestore() -" call Decho("newdirname<".newdirname.">",'~'.expand("")) if newdirname == "" let @@= ykeep -" call Dret("s:NetrwMakeDir : user aborted with bare ") return endif if a:usrhost == "" -" call Decho("local mkdir",'~'.expand("")) " Local mkdir: " sanity checks let fullnewdir= b:netrw_curdir.'/'.newdirname -" call Decho("fullnewdir<".fullnewdir.">",'~'.expand("")) if isdirectory(s:NetrwFile(fullnewdir)) if !exists("g:netrw_quiet") NetrwKeepj call netrw#ErrorMsg(s:WARNING,"<".newdirname."> is already a directory!",24) endif let @@= ykeep -" call Dret("s:NetrwMakeDir : directory<".newdirname."> exists previously") return endif if s:FileReadable(fullnewdir) @@ -6272,7 +5913,6 @@ fun! s:NetrwMakeDir(usrhost) NetrwKeepj call netrw#ErrorMsg(s:WARNING,"<".newdirname."> is already a file!",25) endif let @@= ykeep -" call Dret("s:NetrwMakeDir : file<".newdirname."> exists previously") return endif @@ -6287,21 +5927,16 @@ fun! s:NetrwMakeDir(usrhost) else let netrw_origdir= s:NetrwGetcwd(1) if s:NetrwLcd(b:netrw_curdir) -" call Dret("s:NetrwMakeDir : lcd failure") return endif -" call Decho("netrw_origdir<".netrw_origdir.">: lcd b:netrw_curdir<".fnameescape(b:netrw_curdir).">",'~'.expand("")) call s:NetrwExe("sil! !".g:netrw_localmkdir.g:netrw_localmkdiropt.' '.s:ShellEscape(newdirname,1)) if v:shell_error != 0 let @@= ykeep call netrw#ErrorMsg(s:ERROR,"consider setting g:netrw_localmkdir<".g:netrw_localmkdir."> to something that works",80) -" call Dret("s:NetrwMakeDir : failed: sil! !".g:netrw_localmkdir.' '.s:ShellEscape(newdirname,1)) return endif if !g:netrw_keepdir -" call Decho("restoring netrw_origdir since g:netrw_keepdir=".g:netrw_keepdir,'~'.expand("")) if s:NetrwLcd(netrw_origdir) -" call Dret("s:NetrwBrowse : lcd failure") return endif endif @@ -6309,126 +5944,95 @@ fun! s:NetrwMakeDir(usrhost) if v:shell_error == 0 " refresh listing -" call Decho("refresh listing",'~'.expand("")) let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) - call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) call winrestview(svpos) elseif !exists("g:netrw_quiet") call netrw#ErrorMsg(s:ERROR,"unable to make directory<".newdirname.">",26) endif -" redraw! elseif !exists("b:netrw_method") || b:netrw_method == 4 " Remote mkdir: using ssh -" call Decho("remote mkdir",'~'.expand("")) let mkdircmd = s:MakeSshCmd(g:netrw_mkdir_cmd) let newdirname= substitute(b:netrw_curdir,'^\%(.\{-}/\)\{3}\(.*\)$','\1','').newdirname call s:NetrwExe("sil! !".mkdircmd." ".s:ShellEscape(newdirname,1)) if v:shell_error == 0 " refresh listing let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) elseif !exists("g:netrw_quiet") NetrwKeepj call netrw#ErrorMsg(s:ERROR,"unable to make directory<".newdirname.">",27) endif -" redraw! elseif b:netrw_method == 2 " Remote mkdir: using ftp+.netrc let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) -" call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("")) if exists("b:netrw_fname") -" call Decho("b:netrw_fname<".b:netrw_fname.">",'~'.expand("")) let remotepath= b:netrw_fname else let remotepath= "" endif call s:NetrwRemoteFtpCmd(remotepath,g:netrw_remote_mkdir.' "'.newdirname.'"') - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) elseif b:netrw_method == 3 " Remote mkdir: using ftp + machine, id, passwd, and fname (ie. no .netrc) let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) -" call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("")) if exists("b:netrw_fname") -" call Decho("b:netrw_fname<".b:netrw_fname.">",'~'.expand("")) let remotepath= b:netrw_fname else let remotepath= "" endif call s:NetrwRemoteFtpCmd(remotepath,g:netrw_remote_mkdir.' "'.newdirname.'"') - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) endif let @@= ykeep -" call Dret("s:NetrwMakeDir") endfun " --------------------------------------------------------------------- " s:TreeSqueezeDir: allows a shift-cr (gvim only) to squeeze the current tree-listing directory {{{2 fun! s:TreeSqueezeDir(islocal) -" call Dfunc("s:TreeSqueezeDir(islocal=".a:islocal.")") if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") " its a tree-listing style let curdepth = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e') let stopline = (exists("w:netrw_bannercnt")? (w:netrw_bannercnt + 1) : 1) let depth = strchars(substitute(curdepth,' ','','g')) let srch = -1 -" call Decho("curdepth<".curdepth.'>','~'.expand("")) -" call Decho("depth =".depth,'~'.expand("")) -" call Decho("stopline#".stopline,'~'.expand("")) -" call Decho("curline#".line(".")."<".getline('.').'>','~'.expand("")) if depth >= 2 NetrwKeepj norm! 0 let curdepthm1= substitute(curdepth,'^'.s:treedepthstring,'','') let srch = search('^'.curdepthm1.'\%('.s:treedepthstring.'\)\@!','bW',stopline) -" call Decho("curdepthm1<".curdepthm1.'>','~'.expand("")) -" call Decho("case depth>=2: srch<".srch.'>','~'.expand("")) elseif depth == 1 NetrwKeepj norm! 0 let treedepthchr= substitute(s:treedepthstring,' ','','') let srch = search('^[^'.treedepthchr.']','bW',stopline) -" call Decho("case depth==1: srch<".srch.'>','~'.expand("")) endif if srch > 0 -" call Decho("squeezing at line#".line(".").": ".getline('.'),'~'.expand("")) - call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,s:NetrwGetWord())) + call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,s:NetrwGetWord(),1)) exe srch endif endif -" call Dret("s:TreeSqueezeDir") endfun " --------------------------------------------------------------------- " s:NetrwMaps: {{{2 fun! s:NetrwMaps(islocal) -" call Dfunc("s:NetrwMaps(islocal=".a:islocal.") b:netrw_curdir<".b:netrw_curdir.">") " mouse maps: {{{3 if g:netrw_mousemaps && g:netrw_retmap " call Decho("set up Rexplore 2-leftmouse",'~'.expand("")) if !hasmapto("NetrwReturn") if maparg("<2-leftmouse>","n") == "" || maparg("<2-leftmouse>","n") =~ '^-$' -" call Decho("making map for 2-leftmouse",'~'.expand("")) nmap <2-leftmouse> NetrwReturn elseif maparg("","n") == "" -" call Decho("making map for c-leftmouse",'~'.expand("")) nmap NetrwReturn endif endif nno NetrwReturn :Rexplore -" call Decho("made NetrwReturn map",'~'.expand("")) endif " generate default maps {{{3 @@ -6444,57 +6048,8 @@ fun! s:NetrwMaps(islocal) if !hasmapto('NetrwServerEdit') |nmap NetrwServerEdit|endif if !hasmapto('NetrwMakeDir') |nmap d NetrwMakeDir|endif if !hasmapto('NetrwBookHistHandler_gb')|nmap gb NetrwBookHistHandler_gb|endif -" --------------------------------------------------------------------- -" if !hasmapto('NetrwForceChgDir') |nmap gd NetrwForceChgDir|endif -" if !hasmapto('NetrwForceFile') |nmap gf NetrwForceFile|endif -" if !hasmapto('NetrwHidden') |nmap gh NetrwHidden|endif -" if !hasmapto('NetrwSetTreetop') |nmap gn NetrwSetTreetop|endif -" if !hasmapto('NetrwChgPerm') |nmap gp NetrwChgPerm|endif -" if !hasmapto('NetrwBannerCtrl') |nmap I NetrwBannerCtrl|endif -" if !hasmapto('NetrwListStyle') |nmap i NetrwListStyle|endif -" if !hasmapto('NetrwMarkMoveMF2Arglist')|nmap ma NetrwMarkMoveMF2Arglist|endif -" if !hasmapto('NetrwMarkMoveArglist2MF')|nmap mA NetrwMarkMoveArglist2MF|endif -" if !hasmapto('NetrwBookHistHandler_mA')|nmap mb NetrwBookHistHandler_mA|endif -" if !hasmapto('NetrwBookHistHandler_mB')|nmap mB NetrwBookHistHandler_mB|endif -" if !hasmapto('NetrwMarkFileCopy') |nmap mc NetrwMarkFileCopy|endif -" if !hasmapto('NetrwMarkFileDiff') |nmap md NetrwMarkFileDiff|endif -" if !hasmapto('NetrwMarkFileEdit') |nmap me NetrwMarkFileEdit|endif -" if !hasmapto('NetrwMarkFile') |nmap mf NetrwMarkFile|endif -" if !hasmapto('NetrwUnmarkList') |nmap mF NetrwUnmarkList|endif -" if !hasmapto('NetrwMarkFileGrep') |nmap mg NetrwMarkFileGrep|endif -" if !hasmapto('NetrwMarkHideSfx') |nmap mh NetrwMarkHideSfx|endif -" if !hasmapto('NetrwMarkFileMove') |nmap mm NetrwMarkFileMove|endif -" if !hasmapto('NetrwMarkFilePrint') |nmap mp NetrwMarkFilePrint|endif -" if !hasmapto('NetrwMarkFileRegexp') |nmap mr NetrwMarkFileRegexp|endif -" if !hasmapto('NetrwMarkFileSource') |nmap ms NetrwMarkFileSource|endif -" if !hasmapto('NetrwMarkFileTag') |nmap mT NetrwMarkFileTag|endif -" if !hasmapto('NetrwMarkFileTgt') |nmap mt NetrwMarkFileTgt|endif -" if !hasmapto('NetrwUnMarkFile') |nmap mu NetrwUnMarkFile|endif -" if !hasmapto('NetrwMarkFileVimCmd') |nmap mv NetrwMarkFileVimCmd|endif -" if !hasmapto('NetrwMarkFileExe_mx') |nmap mx NetrwMarkFileExe_mx|endif -" if !hasmapto('NetrwMarkFileExe_mX') |nmap mX NetrwMarkFileExe_mX|endif -" if !hasmapto('NetrwMarkFileCompress') |nmap mz NetrwMarkFileCompress|endif -" if !hasmapto('NetrwObtain') |nmap O NetrwObtain|endif -" if !hasmapto('NetrwSplit_o') |nmap o NetrwSplit_o|endif -" if !hasmapto('NetrwPreview') |nmap p NetrwPreview|endif -" if !hasmapto('NetrwPrevWinOpen') |nmap P NetrwPrevWinOpen|endif -" if !hasmapto('NetrwBookHistHandler_qb')|nmap qb NetrwBookHistHandler_qb|endif -" if !hasmapto('NetrwFileInfo') |nmap qf NetrwFileInfo|endif -" if !hasmapto('NetrwMarkFileQFEL_qF') |nmap qF NetrwMarkFileQFEL_qF|endif -" if !hasmapto('NetrwMarkFileQFEL_qL') |nmap qL NetrwMarkFileQFEL_qL|endif -" if !hasmapto('NetrwSortStyle') |nmap s NetrwSortStyle|endif -" if !hasmapto('NetSortSequence') |nmap S NetSortSequence|endif -" if !hasmapto('NetrwSetTgt_Tb') |nmap Tb NetrwSetTgt_Tb|endif -" if !hasmapto('NetrwSetTgt_Th') |nmap Th NetrwSetTgt_Th|endif -" if !hasmapto('NetrwSplit_t') |nmap t NetrwSplit_t|endif -" if !hasmapto('NetrwBookHistHandler_u') |nmap u NetrwBookHistHandler_u|endif -" if !hasmapto('NetrwBookHistHandler_U') |nmap U NetrwBookHistHandler_U|endif -" if !hasmapto('NetrwSplit_v') |nmap v NetrwSplit_v|endif -" if !hasmapto('NetrwBrowseX') |nmap x NetrwBrowseX|endif -" if !hasmapto('NetrwLocalExecute') |nmap X NetrwLocalExecute|endif if a:islocal -" call Decho("make local maps",'~'.expand("")) " local normal-mode maps {{{3 nnoremap NetrwHide_a :call NetrwHide(1) nnoremap NetrwBrowseUpDir :call NetrwBrowseUpDir(1) @@ -6503,7 +6058,7 @@ fun! s:NetrwMaps(islocal) nnoremap NetrwBadd_cB :call NetrwBadd(1,1) nnoremap NetrwLcd :call NetrwLcd(b:netrw_curdir) nnoremap NetrwSetChgwin :call NetrwSetChgwin() - nnoremap NetrwLocalBrowseCheck :call netrw#LocalBrowseCheck(NetrwBrowseChgDir(1,NetrwGetWord())) + nnoremap NetrwLocalBrowseCheck :call netrw#LocalBrowseCheck(NetrwBrowseChgDir(1,NetrwGetWord(),1)) nnoremap NetrwServerEdit :call NetrwServerEdit(3,NetrwGetWord()) nnoremap NetrwMakeDir :call NetrwMakeDir("") nnoremap NetrwBookHistHandler_gb :call NetrwBookHistHandler(1,b:netrw_curdir) @@ -6539,7 +6094,7 @@ fun! s:NetrwMaps(islocal) nnoremap mz :call NetrwMarkFileCompress(1) nnoremap O :call NetrwObtain(1) nnoremap o :call NetrwSplit(3) - nnoremap p :call NetrwPreview(NetrwBrowseChgDir(1,NetrwGetWord(),1)) + nnoremap p :call NetrwPreview(NetrwBrowseChgDir(1,NetrwGetWord(),1,1)) nnoremap P :call NetrwPrevWinOpen(1) nnoremap qb :call NetrwBookHistHandler(2,b:netrw_curdir) nnoremap qf :call NetrwFileInfo(1,NetrwGetWord()) @@ -6553,10 +6108,10 @@ fun! s:NetrwMaps(islocal) nnoremap u :call NetrwBookHistHandler(4,expand("%")) nnoremap U :call NetrwBookHistHandler(5,expand("%")) nnoremap v :call NetrwSplit(5) - nnoremap x :call netrw#BrowseX(NetrwBrowseChgDir(1,NetrwGetWord(),0),0)" + nnoremap x :call netrw#BrowseX(NetrwBrowseChgDir(1,NetrwGetWord(),1,0),0)" nnoremap X :call NetrwLocalExecute(expand(""))" - nnoremap r :let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'exe "norm! 0"call NetrwRefresh(1,NetrwBrowseChgDir(1,'./')) + nnoremap r :let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'exe "norm! 0"call NetrwRefresh(1,NetrwBrowseChgDir(1,'./',0)) if !hasmapto('NetrwHideEdit') nmap NetrwHideEdit endif @@ -6564,7 +6119,7 @@ fun! s:NetrwMaps(islocal) if !hasmapto('NetrwRefresh') nmap NetrwRefresh endif - nnoremap NetrwRefresh :call NetrwRefresh(1,NetrwBrowseChgDir(1,(exists("w:netrw_liststyle") && exists("w:netrw_treetop") && w:netrw_liststyle == 3)? w:netrw_treetop : './')) + nnoremap NetrwRefresh :call NetrwRefresh(1,NetrwBrowseChgDir(1,(exists("w:netrw_liststyle") && exists("w:netrw_treetop") && w:netrw_liststyle == 3)? w:netrw_treetop : './',0)) if s:didstarstar || !mapcheck("","n") nnoremap :Nexplore endif @@ -6608,7 +6163,6 @@ fun! s:NetrwMaps(islocal) else " remote normal-mode maps {{{3 -" call Decho("make remote maps",'~'.expand("")) call s:RemotePathAnalysis(b:netrw_curdir) nnoremap NetrwHide_a :call NetrwHide(0) nnoremap NetrwBrowseUpDir :call NetrwBrowseUpDir(0) @@ -6617,8 +6171,8 @@ fun! s:NetrwMaps(islocal) nnoremap NetrwBadd_cB :call NetrwBadd(0,1) nnoremap NetrwLcd :call NetrwLcd(b:netrw_curdir) nnoremap NetrwSetChgwin :call NetrwSetChgwin() - nnoremap NetrwRefresh :call NetrwRefresh(0,NetrwBrowseChgDir(0,'./')) - nnoremap NetrwLocalBrowseCheck :call NetrwBrowse(0,NetrwBrowseChgDir(0,NetrwGetWord())) + nnoremap NetrwRefresh :call NetrwRefresh(0,NetrwBrowseChgDir(0,'./',0)) + nnoremap NetrwLocalBrowseCheck :call NetrwBrowse(0,NetrwBrowseChgDir(0,NetrwGetWord(),1)) nnoremap NetrwServerEdit :call NetrwServerEdit(2,NetrwGetWord()) nnoremap NetrwBookHistHandler_gb :call NetrwBookHistHandler(1,b:netrw_curdir) " --------------------------------------------------------------------- @@ -6652,13 +6206,13 @@ fun! s:NetrwMaps(islocal) nnoremap mz :call NetrwMarkFileCompress(0) nnoremap O :call NetrwObtain(0) nnoremap o :call NetrwSplit(0) - nnoremap p :call NetrwPreview(NetrwBrowseChgDir(1,NetrwGetWord(),1)) + nnoremap p :call NetrwPreview(NetrwBrowseChgDir(1,NetrwGetWord(),1,1)) nnoremap P :call NetrwPrevWinOpen(0) nnoremap qb :call NetrwBookHistHandler(2,b:netrw_curdir) nnoremap qf :call NetrwFileInfo(0,NetrwGetWord()) nnoremap qF :call NetrwMarkFileQFEL(0,getqflist()) nnoremap qL :call NetrwMarkFileQFEL(0,getloclist(v:count)) - nnoremap r :let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'exe "norm! 0"call NetrwBrowse(0,NetrwBrowseChgDir(0,'./')) + nnoremap r :let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'exe "norm! 0"call NetrwBrowse(0,NetrwBrowseChgDir(0,'./',0)) nnoremap s :call NetrwSortStyle(0) nnoremap S :call NetSortSequence(0) nnoremap Tb :call NetrwSetTgt(0,'b',v:count1) @@ -6667,7 +6221,7 @@ fun! s:NetrwMaps(islocal) nnoremap u :call NetrwBookHistHandler(4,b:netrw_curdir) nnoremap U :call NetrwBookHistHandler(5,b:netrw_curdir) nnoremap v :call NetrwSplit(2) - nnoremap x :call netrw#BrowseX(NetrwBrowseChgDir(0,NetrwGetWord()),1) + nnoremap x :call netrw#BrowseX(NetrwBrowseChgDir(0,NetrwGetWord(),1),1) nmap gx x if !hasmapto('NetrwHideEdit') nmap NetrwHideEdit @@ -6684,7 +6238,7 @@ fun! s:NetrwMaps(islocal) let mapsafepath = escape(s:path, s:netrw_map_escape) let mapsafeusermach = escape(((s:user == "")? "" : s:user."@").s:machine, s:netrw_map_escape) - nnoremap NetrwRefresh :call NetrwRefresh(0,NetrwBrowseChgDir(0,'./')) + nnoremap NetrwRefresh :call NetrwRefresh(0,NetrwBrowseChgDir(0,'./',0)) if g:netrw_mousemaps == 1 nmap NetrwLeftmouse nno NetrwLeftmouse :exec "norm! \leftmouse>"call NetrwLeftmouse(0) @@ -6716,8 +6270,6 @@ fun! s:NetrwMaps(islocal) " support user-specified maps call netrw#UserMaps(0) endif " }}}3 - -" call Dret("s:NetrwMaps") endfun " --------------------------------------------------------------------- @@ -6771,7 +6323,6 @@ endfun " --------------------------------------------------------------------- " s:NetrwMarkTarget: implements :MT (mark target) {{{2 fun! s:NetrwMarkTarget(...) -" call Dfunc("s:NetrwMarkTarget() a:0=".a:0) if a:0 == 0 || (a:0 == 1 && a:1 == "") let curdir = s:NetrwGetCurdir(1) let tgt = b:netrw_curdir @@ -6779,16 +6330,12 @@ fun! s:NetrwMarkTarget(...) let curdir = s:NetrwGetCurdir((a:1 =~ '^\a\{3,}://')? 0 : 1) let tgt = a:1 endif -" call Decho("tgt<".tgt.">",'~'.expand("")) let s:netrwmftgt = tgt let s:netrwmftgt_islocal = tgt !~ '^\a\{3,}://' let curislocal = b:netrw_curdir !~ '^\a\{3,}://' let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) - call s:NetrwRefresh(curislocal,s:NetrwBrowseChgDir(curislocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + call s:NetrwRefresh(curislocal,s:NetrwBrowseChgDir(curislocal,'./',0)) call winrestview(svpos) -" call Dret("s:NetrwMarkTarget") endfun " --------------------------------------------------------------------- @@ -6931,10 +6478,7 @@ endfun " mA: move the argument list to marked file list (tomflist=1) " Uses the global marked file list fun! s:NetrwMarkFileArgList(islocal,tomflist) -" call Dfunc("s:NetrwMarkFileArgList(islocal=".a:islocal.",tomflist=".a:tomflist.")") - let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") @@ -6942,7 +6486,6 @@ fun! s:NetrwMarkFileArgList(islocal,tomflist) " mA: move argument list to marked file list while argc() let fname= argv(0) -" call Decho("exe argdel ".fname,'~'.expand("")) exe "argdel ".fnameescape(fname) call s:NetrwMarkFile(a:islocal,fname) endwhile @@ -6953,19 +6496,16 @@ fun! s:NetrwMarkFileArgList(islocal,tomflist) " for every filename in the marked list for fname in s:netrwmarkfilelist -" call Decho("exe argadd ".fname,'~'.expand("")) exe "argadd ".fnameescape(fname) endfor " for every file in the marked list " unmark list and refresh call s:NetrwUnmarkList(curbufnr,curdir) - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) endif endif -" call Dret("s:NetrwMarkFileArgList") endfun " --------------------------------------------------------------------- @@ -6977,30 +6517,24 @@ endfun " g:netrw_compress = "gzip" " g:netrw_decompress = { ".gz" : "gunzip" , ".bz2" : "bunzip2" , ".zip" : "unzip" , ".tar" : "tar -xf", ".xz" : "unxz"} fun! s:NetrwMarkFileCompress(islocal) -" call Dfunc("s:NetrwMarkFileCompress(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) -" call Dret("s:NetrwMarkFileCompress") return endif -" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("")) if exists("s:netrwmarkfilelist_{curbufnr}") && exists("g:netrw_compress") && exists("g:netrw_decompress") " for every filename in the marked list for fname in s:netrwmarkfilelist_{curbufnr} let sfx= substitute(fname,'^.\{-}\(\.\a\+\)$','\1','') -" call Decho("extracted sfx<".sfx.">",'~'.expand("")) if exists("g:netrw_decompress['".sfx."']") " fname has a suffix indicating that its compressed; apply associated decompression routine let exe= g:netrw_decompress[sfx] -" call Decho("fname<".fname."> is compressed so decompress with <".exe.">",'~'.expand("")) let exe= netrw#WinPath(exe) if a:islocal if g:netrw_keepdir @@ -7033,11 +6567,9 @@ fun! s:NetrwMarkFileCompress(islocal) endfor " for every file in the marked list call s:NetrwUnmarkList(curbufnr,curdir) - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) endif -" call Dret("s:NetrwMarkFileCompress") endfun " --------------------------------------------------------------------- @@ -7377,9 +6909,7 @@ endfun " mx enbloc=0: Uses the local marked-file list, applies command to each file individually " mX enbloc=1: Uses the global marked-file list, applies command to entire list fun! s:NetrwMarkFileExe(islocal,enbloc) -" call Dfunc("s:NetrwMarkFileExe(islocal=".a:islocal.",enbloc=".a:enbloc.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") @@ -7388,19 +6918,15 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) -" call Dret("s:NetrwMarkFileExe") return endif -" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("")) if exists("s:netrwmarkfilelist_{curbufnr}") " get the command call inputsave() let cmd= input("Enter command: ","","file") call inputrestore() -" call Decho("cmd<".cmd.">",'~'.expand("")) if cmd == "" -" call Dret("s:NetrwMarkFileExe : early exit, empty command") return endif @@ -7420,10 +6946,8 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) let xcmd= cmd.' '.fname endif if a:islocal -" call Decho("local: xcmd<".xcmd.">",'~'.expand("")) let ret= system(xcmd) else -" call Decho("remote: xcmd<".xcmd.">",'~'.expand("")) let ret= s:RemoteSystem(xcmd) endif if v:shell_error < 0 @@ -7444,8 +6968,7 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) call s:NetrwUnmarkList(curbufnr,curdir) " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) @@ -7456,9 +6979,7 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) call inputsave() let cmd= input("Enter command: ","","file") call inputrestore() -" call Decho("cmd<".cmd.">",'~'.expand("")) if cmd == "" -" call Dret("s:NetrwMarkFileExe : early exit, empty command") return endif if cmd =~ '%' @@ -7477,13 +6998,10 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) call s:NetrwUnmarkAll() " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) endif - -" call Dret("s:NetrwMarkFileExe") endfun " --------------------------------------------------------------------- @@ -7491,16 +7009,13 @@ endfun " as the marked file(s) (toggles suffix presence) " Uses the local marked file list. fun! s:NetrwMarkHideSfx(islocal) -" call Dfunc("s:NetrwMarkHideSfx(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curbufnr = bufnr("%") " s:netrwmarkfilelist_{curbufnr}: the List of marked files if exists("s:netrwmarkfilelist_{curbufnr}") for fname in s:netrwmarkfilelist_{curbufnr} -" call Decho("s:NetrwMarkFileCopy: fname<".fname.">",'~'.expand("")) " construct suffix pattern if fname =~ '\.' let sfxpat= "^.*".substitute(fname,'^.*\(\.[^. ]\+\)$','\1','') @@ -7520,7 +7035,6 @@ fun! s:NetrwMarkHideSfx(islocal) let itemnum= itemnum + 1 endfor endif -" call Decho("fname<".fname."> inhidelist=".inhidelist." sfxpat<".sfxpat.">",'~'.expand("")) if inhidelist " remove sfxpat from list call remove(hidelist,itemnum) @@ -7535,57 +7049,45 @@ fun! s:NetrwMarkHideSfx(islocal) endfor " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif - -" call Dret("s:NetrwMarkHideSfx") endfun " --------------------------------------------------------------------- " s:NetrwMarkFileVimCmd: (invoked by mv) execute arbitrary vim command on marked files, one at a time {{{2 " Uses the local marked-file list. fun! s:NetrwMarkFileVimCmd(islocal) -" call Dfunc("s:NetrwMarkFileVimCmd(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) -" call Dret("s:NetrwMarkFileVimCmd") return endif -" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("")) if exists("s:netrwmarkfilelist_{curbufnr}") " get the command call inputsave() let cmd= input("Enter vim command: ","","file") call inputrestore() -" call Decho("cmd<".cmd.">",'~'.expand("")) if cmd == "" -" " call Dret("s:NetrwMarkFileVimCmd : early exit, empty command") return endif " apply command to marked files. Substitute: filename -> % " If no %, then append a space and the filename to the command for fname in s:netrwmarkfilelist_{curbufnr} -" call Decho("fname<".fname.">",'~'.expand("")) if a:islocal 1split exe "sil! NetrwKeepj keepalt e ".fnameescape(fname) -" call Decho("local<".fname.">: exe ".cmd,'~'.expand("")) exe cmd exe "sil! keepalt wq!" else -" call Decho("remote<".fname.">: exe ".cmd." : NOT SUPPORTED YET",'~'.expand("")) echo "sorry, \"mv\" not supported yet for remote files" endif endfor @@ -7594,14 +7096,11 @@ fun! s:NetrwMarkFileVimCmd(islocal) call s:NetrwUnmarkList(curbufnr,curdir) " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif - -" call Dret("s:NetrwMarkFileVimCmd") endfun " --------------------------------------------------------------------- @@ -7609,16 +7108,13 @@ endfun " as the marked file(s) (toggles suffix presence) " Uses the local marked file list. fun! s:NetrwMarkHideSfx(islocal) -" call Dfunc("s:NetrwMarkHideSfx(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curbufnr = bufnr("%") " s:netrwmarkfilelist_{curbufnr}: the List of marked files if exists("s:netrwmarkfilelist_{curbufnr}") for fname in s:netrwmarkfilelist_{curbufnr} -" call Decho("s:NetrwMarkFileCopy: fname<".fname.">",'~'.expand("")) " construct suffix pattern if fname =~ '\.' let sfxpat= "^.*".substitute(fname,'^.*\(\.[^. ]\+\)$','\1','') @@ -7638,7 +7134,6 @@ fun! s:NetrwMarkHideSfx(islocal) let itemnum= itemnum + 1 endfor endif -" call Decho("fname<".fname."> inhidelist=".inhidelist." sfxpat<".sfxpat.">",'~'.expand("")) if inhidelist " remove sfxpat from list call remove(hidelist,itemnum) @@ -7653,14 +7148,11 @@ fun! s:NetrwMarkHideSfx(islocal) endfor " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif - -" call Dret("s:NetrwMarkHideSfx") endfun " --------------------------------------------------------------------- @@ -8028,28 +7520,22 @@ endfun " s:NetrwMarkFileTag: (invoked by mT) This function applies g:netrw_ctags to marked files {{{2 " Uses the global markfilelist fun! s:NetrwMarkFileTag(islocal) -" call Dfunc("s:NetrwMarkFileTag(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) -" call Dret("s:NetrwMarkFileTag") return endif -" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("")) if exists("s:netrwmarkfilelist") -" call Decho("s:netrwmarkfilelist".string(s:netrwmarkfilelist).">",'~'.expand("")) let netrwmarkfilelist= join(map(deepcopy(s:netrwmarkfilelist), "s:ShellEscape(v:val,".!a:islocal.")")) call s:NetrwUnmarkAll() if a:islocal -" call Decho("call system(".g:netrw_ctags." ".netrwmarkfilelist.")",'~'.expand("")) call system(g:netrw_ctags." ".netrwmarkfilelist) if v:shell_error call netrw#ErrorMsg(s:ERROR,"g:netrw_ctags<".g:netrw_ctags."> is not executable!",51) @@ -8062,18 +7548,14 @@ fun! s:NetrwMarkFileTag(islocal) 1split NetrwKeepj e tags let path= substitute(curdir,'^\(.*\)/[^/]*$','\1/','') -" call Decho("curdir<".curdir."> path<".path.">",'~'.expand("")) exe 'NetrwKeepj %s/\t\(\S\+\)\t/\t'.escape(path,"/\n\r\\").'\1\t/e' call histdel("/",-1) wq! endif 2match none - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) call winrestview(svpos) endif - -" call Dret("s:NetrwMarkFileTag") endfun " --------------------------------------------------------------------- @@ -8083,9 +7565,7 @@ endfun " s:netrwmftgt_islocal : 0=target directory is remote " 1=target directory is local fun! s:NetrwMarkFileTgt(islocal) -" call Dfunc("s:NetrwMarkFileTgt(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curdir = s:NetrwGetCurdir(a:islocal) let hadtgt = exists("s:netrwmftgt") if !exists("w:netrw_bannercnt") @@ -8094,46 +7574,36 @@ fun! s:NetrwMarkFileTgt(islocal) " set up target if line(".") < w:netrw_bannercnt -" call Decho("set up target: line(.) < w:netrw_bannercnt=".w:netrw_bannercnt,'~'.expand("")) " if cursor in banner region, use b:netrw_curdir for the target unless its already the target if exists("s:netrwmftgt") && exists("s:netrwmftgt_islocal") && s:netrwmftgt == b:netrw_curdir -" call Decho("cursor in banner region, and target already is <".b:netrw_curdir.">: removing target",'~'.expand("")) unlet s:netrwmftgt s:netrwmftgt_islocal if g:netrw_fastbrowse <= 1 call s:LocalBrowseRefresh() endif - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) call winrestview(svpos) -" call Dret("s:NetrwMarkFileTgt : removed target") return else let s:netrwmftgt= b:netrw_curdir -" call Decho("inbanner: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("")) endif else " get word under cursor. " * If directory, use it for the target. " * If file, use b:netrw_curdir for the target -" call Decho("get word under cursor",'~'.expand("")) let curword= s:NetrwGetWord() let tgtdir = s:ComposePath(curdir,curword) if a:islocal && isdirectory(s:NetrwFile(tgtdir)) let s:netrwmftgt = tgtdir -" call Decho("local isdir: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("")) elseif !a:islocal && tgtdir =~ '/$' let s:netrwmftgt = tgtdir -" call Decho("remote isdir: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("")) else let s:netrwmftgt = curdir -" call Decho("isfile: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("")) endif endif if a:islocal " simplify the target (eg. /abc/def/../ghi -> /abc/ghi) let s:netrwmftgt= simplify(s:netrwmftgt) -" call Decho("simplify: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("")) endif if g:netrw_cygwin let s:netrwmftgt= substitute(system("cygpath ".s:ShellEscape(s:netrwmftgt)),'\n$','','') @@ -8144,24 +7614,18 @@ fun! s:NetrwMarkFileTgt(islocal) " need to do refresh so that the banner will be updated " s:LocalBrowseRefresh handles all local-browsing buffers when not fast browsing if g:netrw_fastbrowse <= 1 -" call Decho("g:netrw_fastbrowse=".g:netrw_fastbrowse.", so refreshing all local netrw buffers",'~'.expand("")) call s:LocalBrowseRefresh() endif -" call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) +" call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,w:netrw_treetop)) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,w:netrw_treetop,0)) else - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) endif -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) call winrestview(svpos) if !hadtgt sil! NetrwKeepj norm! j endif - -" call Decho("getmatches=".string(getmatches()),'~'.expand("")) -" call Decho("s:netrwmarkfilelist=".(exists("s:netrwmarkfilelist")? string(s:netrwmarkfilelist) : 'n/a'),'~'.expand("")) -" call Dret("s:NetrwMarkFileTgt : netrwmftgt<".(exists("s:netrwmftgt")? s:netrwmftgt : "").">") endfun " --------------------------------------------------------------------- @@ -8295,23 +7759,17 @@ endfun " --------------------------------------------------------------------- " s:NetSortSequence: allows user to edit the sorting sequence {{{2 fun! s:NetSortSequence(islocal) -" call Dfunc("NetSortSequence(islocal=".a:islocal.")") - let ykeep= @@ let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) call inputsave() let newsortseq= input("Edit Sorting Sequence: ",g:netrw_sort_sequence) call inputrestore() " refresh the listing let g:netrw_sort_sequence= newsortseq - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep - -" call Dret("NetSortSequence") endfun " --------------------------------------------------------------------- @@ -8382,9 +7840,7 @@ endfun " Marked files suitable for use with 2match are in: " s:netrwmarkfilemtch_# -- used with 2match to display marked files fun! s:NetrwUnMarkFile(islocal) -" call Dfunc("s:NetrwUnMarkFile(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let curbufnr = bufnr("%") " unmark marked file list @@ -8404,10 +7860,8 @@ fun! s:NetrwUnMarkFile(islocal) endwhile 2match none -" call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -"call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) +" call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) call winrestview(svpos) -" call Dret("s:NetrwUnMarkFile") endfun " --------------------------------------------------------------------- @@ -8542,69 +7996,47 @@ endfun " choice = 2 : didn't save modified file, opened window " choice = 3 : cancel open fun! s:NetrwPrevWinOpen(islocal) -" call Dfunc("s:NetrwPrevWinOpen(islocal=".a:islocal.") win#".winnr()) - let ykeep= @@ " grab a copy of the b:netrw_curdir to pass it along to newly split windows let curdir = b:netrw_curdir -" call Decho("COMBAK#1: mod=".&mod." win#".winnr()) " get last window number and the word currently under the cursor let origwin = winnr() let lastwinnr = winnr("$") -" call Decho("origwin#".origwin." lastwinnr#".lastwinnr) -" call Decho("COMBAK#2: mod=".&mod." win#".winnr()) let curword = s:NetrwGetWord() let choice = 0 let s:prevwinopen= 1 " lets s:NetrwTreeDir() know that NetrwPrevWinOpen called it (s:NetrwTreeDir() will unlet s:prevwinopen) -" call Decho("COMBAK#3: mod=".&mod." win#".winnr()) let s:treedir = s:NetrwTreeDir(a:islocal) -" call Decho("COMBAK#4: mod=".&mod." win#".winnr()) let curdir = s:treedir -" call Decho("COMBAK#5: mod=".&mod." win#".winnr()) -" call Decho("winnr($)#".lastwinnr." curword<".curword.">",'~'.expand("")) -" call Decho("COMBAK#6: mod=".&mod." win#".winnr()) let didsplit = 0 if lastwinnr == 1 " if only one window, open a new one first -" call Decho("only one window, so open a new one (g:netrw_alto=".g:netrw_alto.")",'~'.expand("")) " g:netrw_preview=0: preview window shown in a horizontally split window " g:netrw_preview=1: preview window shown in a vertically split window if g:netrw_preview " vertically split preview window let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize -" call Decho("exe ".(g:netrw_alto? "top " : "bot ")."vert ".winsz."wincmd s",'~'.expand("")) exe (g:netrw_alto? "top " : "bot ")."vert ".winsz."wincmd s" else " horizontally split preview window let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize -" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s",'~'.expand("")) exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s" endif let didsplit = 1 -" call Decho("did split",'~'.expand("")) else -" call Decho("COMBAK#7: mod=".&mod." win#".winnr()) NetrwKeepj call s:SaveBufVars() -" call Decho("COMBAK#8: mod=".&mod." win#".winnr()) let eikeep= &ei -" call Decho("COMBAK#9: mod=".&mod." win#".winnr()) setl ei=all -" call Decho("COMBAK#10: mod=".&mod." win#".winnr()) wincmd p -" call Decho("COMBAK#11: mod=".&mod) -" call Decho("wincmd p (now in win#".winnr().") curdir<".curdir.">",'~'.expand("")) -" call Decho("COMBAK#12: mod=".&mod) if exists("s:lexplore_win") && s:lexplore_win == winnr() " whoops -- user trying to open file in the Lexplore window. " Use Lexplore's opening-file window instead. -" call Decho("whoops -- user trying to open file in Lexplore Window. Use win#".g:netrw_chgwin." instead") " exe g:netrw_chgwin."wincmd w" wincmd p - call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord())) + call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)) endif " prevwinnr: the window number of the "prev" window @@ -8615,28 +8047,20 @@ fun! s:NetrwPrevWinOpen(islocal) let prevbufname = bufname("%") let prevmod = &mod let bnrcnt = 0 -" call Decho("COMBAK#13: mod=".&mod." win#".winnr()) NetrwKeepj call s:RestoreBufVars() -" call Decho("after wincmd p: win#".winnr()." win($)#".winnr("$")." origwin#".origwin." &mod=".&mod." bufname(%)<".bufname("%")."> prevbufnr=".prevbufnr,'~'.expand("")) -" call Decho("COMBAK#14: mod=".&mod." win#".winnr()) " if the previous window's buffer has been changed (ie. its modified flag is set), " and it doesn't appear in any other extant window, then ask the " user if s/he wants to abandon modifications therein. if prevmod -" call Decho("detected that prev window's buffer has been modified: prevbufnr=".prevbufnr." winnr()#".winnr(),'~'.expand("")) windo if winbufnr(0) == prevbufnr | let bnrcnt=bnrcnt+1 | endif -" call Decho("prevbufnr=".prevbufnr." bnrcnt=".bnrcnt." buftype=".&bt." winnr()=".winnr()." prevwinnr#".prevwinnr,'~'.expand("")) exe prevwinnr."wincmd w" -" call Decho("COMBAK#15: mod=".&mod." win#".winnr()) if bnrcnt == 1 && &hidden == 0 " only one copy of the modified buffer in a window, and " hidden not set, so overwriting will lose the modified file. Ask first... let choice = confirm("Save modified buffer<".prevbufname."> first?","&Yes\n&No\n&Cancel") -" call Decho("prevbufname<".prevbufname."> choice=".choice." current-winnr#".winnr(),'~'.expand("")) let &ei= eikeep -" call Decho("COMBAK#16: mod=".&mod." win#".winnr()) if choice == 1 " Yes -- write file & then browse @@ -8647,41 +8071,35 @@ fun! s:NetrwPrevWinOpen(islocal) exe origwin."wincmd w" let &ei = eikeep let @@ = ykeep -" call Dret("s:NetrwPrevWinOpen ".choice." : unable to write <".prevbufname.">") return choice endif elseif choice == 2 " No -- don't worry about changed file, just browse anyway -" call Decho("don't worry about chgd file, just browse anyway (winnr($)#".winnr("$").")",'~'.expand("")) echomsg "**note** changes to ".prevbufname." abandoned" else " Cancel -- don't do this -" call Decho("cancel, don't browse, switch to win#".origwin,'~'.expand("")) exe origwin."wincmd w" let &ei= eikeep let @@ = ykeep -" call Dret("s:NetrwPrevWinOpen ".choice." : cancelled") return choice endif endif endif let &ei= eikeep endif -" call Decho("COMBAK#17: mod=".&mod." win#".winnr()) " restore b:netrw_curdir (window split/enew may have lost it) let b:netrw_curdir= curdir if a:islocal < 2 if a:islocal - call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(a:islocal,curword)) + call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(a:islocal,curword,0)) else - call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,curword)) + call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,curword,0)) endif endif let @@= ykeep -" call Dret("s:NetrwPrevWinOpen ".choice) return choice endfun @@ -8988,32 +8406,25 @@ endfun " Called by NetrwMarkFileCopy() " Interfaces to s:NetrwRefresh() and s:LocalBrowseRefresh() fun! s:NetrwRefreshDir(islocal,dirname) -" call Dfunc("s:NetrwRefreshDir(islocal=".a:islocal." dirname<".a:dirname.">) g:netrw_fastbrowse=".g:netrw_fastbrowse) if g:netrw_fastbrowse == 0 " slowest mode (keep buffers refreshed, local or remote) -" call Decho("slowest mode: keep buffers refreshed, local or remote",'~'.expand("")) let tgtwin= bufwinnr(a:dirname) -" call Decho("tgtwin= bufwinnr(".a:dirname.")=".tgtwin,'~'.expand("")) if tgtwin > 0 " tgtwin is being displayed, so refresh it let curwin= winnr() -" call Decho("refresh tgtwin#".tgtwin." (curwin#".curwin.")",'~'.expand("")) exe tgtwin."wincmd w" - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) exe curwin."wincmd w" elseif bufnr(a:dirname) > 0 let bn= bufnr(a:dirname) -" call Decho("bd bufnr(".a:dirname.")=".bn,'~'.expand("")) exe "sil keepj bd ".bn endif elseif g:netrw_fastbrowse <= 1 -" call Decho("medium-speed mode: refresh local buffers only",'~'.expand("")) NetrwKeepj call s:LocalBrowseRefresh() endif -" call Dret("s:NetrwRefreshDir") endfun " --------------------------------------------------------------------- @@ -9153,18 +8564,13 @@ endfun " ===================================================================== " s:NetrwSortStyle: change sorting style (name - time - size - exten) and refresh display {{{2 fun! s:NetrwSortStyle(islocal) -" call Dfunc("s:NetrwSortStyle(islocal=".a:islocal.") netrw_sort_by<".g:netrw_sort_by.">") NetrwKeepj call s:NetrwSaveWordPosn() let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let g:netrw_sort_by= (g:netrw_sort_by =~# '^n')? 'time' : (g:netrw_sort_by =~# '^t')? 'size' : (g:netrw_sort_by =~# '^siz')? 'exten' : 'name' NetrwKeepj norm! 0 - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) - -" call Dret("s:NetrwSortStyle : netrw_sort_by<".g:netrw_sort_by.">") endfun " --------------------------------------------------------------------- @@ -9176,7 +8582,6 @@ endfun " =4 : local and t " =5 : local and v fun! s:NetrwSplit(mode) -" call Dfunc("s:NetrwSplit(mode=".a:mode.") alto=".g:netrw_alto." altv=".g:netrw_altv) let ykeep= @@ call s:SaveWinVars() @@ -9185,17 +8590,15 @@ fun! s:NetrwSplit(mode) " remote and o let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize if winsz == 0|let winsz= ""|endif -" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s",'~'.expand("")) exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s" let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord())) + NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)) unlet s:didsplit elseif a:mode == 1 " remote and t - let newdir = s:NetrwBrowseChgDir(0,s:NetrwGetWord()) -" call Decho("tabnew",'~'.expand("")) + let newdir = s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1) tabnew let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() @@ -9206,22 +8609,20 @@ fun! s:NetrwSplit(mode) " remote and v let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize if winsz == 0|let winsz= ""|endif -" call Decho("exe ".(g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v",'~'.expand("")) exe (g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v" let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord())) + NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)) unlet s:didsplit elseif a:mode == 3 " local and o let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize if winsz == 0|let winsz= ""|endif -" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s",'~'.expand("")) exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s" let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord())) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1)) unlet s:didsplit elseif a:mode == 4 @@ -9238,12 +8639,11 @@ fun! s:NetrwSplit(mode) exe "NetrwKeepj norm! ".netrw_line."G0".netrw_col."\" let &ei = eikeep let netrw_curdir = s:NetrwTreeDir(0) -" call Decho("tabnew",'~'.expand("")) tabnew let b:netrw_curdir = netrw_curdir let s:didsplit = 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,cursorword)) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,cursorword,0)) if &ft == "netrw" setl ei=all exe "NetrwKeepj norm! ".netrw_hline."G0z\" @@ -9256,11 +8656,10 @@ fun! s:NetrwSplit(mode) " local and v let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize if winsz == 0|let winsz= ""|endif -" call Decho("exe ".(g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v",'~'.expand("")) exe (g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v" let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord())) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1)) unlet s:didsplit else @@ -9268,7 +8667,6 @@ fun! s:NetrwSplit(mode) endif let @@= ykeep -" call Dret("s:NetrwSplit") endfun " --------------------------------------------------------------------- @@ -9338,91 +8736,49 @@ endfun " s:NetrwTreeDir: determine tree directory given current cursor position {{{2 " (full path directory with trailing slash returned) fun! s:NetrwTreeDir(islocal) -" call Dfunc("s:NetrwTreeDir(islocal=".a:islocal.") getline(".line(".").")"."<".getline('.')."> b:netrw_curdir<".b:netrw_curdir."> tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> ft=".&ft) -" call Decho("Determine tree directory given current cursor position") -" call Decho("g:netrw_keepdir =".(exists("g:netrw_keepdir")? g:netrw_keepdir : 'n/a'),'~'.expand("")) -" call Decho("w:netrw_liststyle=".(exists("w:netrw_liststyle")? w:netrw_liststyle : 'n/a'),'~'.expand("")) -" call Decho("w:netrw_treetop =".(exists("w:netrw_treetop")? w:netrw_treetop : 'n/a'),'~'.expand("")) -" call Decho("current line<".getline(".").">") if exists("s:treedir") && exists("s:prevwinopen") " s:NetrwPrevWinOpen opens a "previous" window -- and thus needs to and does call s:NetrwTreeDir early -" call Decho('s:NetrwPrevWinOpen opens a "previous" window -- and thus needs to and does call s:NetrwTreeDir early') let treedir= s:treedir unlet s:treedir unlet s:prevwinopen -" call Dret("s:NetrwTreeDir ".treedir.": early return since s:treedir existed previously") return treedir endif if exists("s:prevwinopen") unlet s:prevwinopen endif -" call Decho("COMBAK#18 : mod=".&mod." win#".winnr()) if !exists("b:netrw_curdir") || b:netrw_curdir == "" let b:netrw_curdir= getcwd() endif let treedir = b:netrw_curdir -" call Decho("set initial treedir<".treedir.">",'~'.expand("")) -" call Decho("COMBAK#19 : mod=".&mod." win#".winnr()) - let s:treecurpos= winsaveview() -" call Decho("saving posn to s:treecurpos<".string(s:treecurpos).">",'~'.expand("")) -" call Decho("COMBAK#20 : mod=".&mod." win#".winnr()) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST -" call Decho("w:netrw_liststyle is TREELIST:",'~'.expand("")) -" call Decho("line#".line(".")." getline(.)<".getline('.')."> treecurpos<".string(s:treecurpos).">",'~'.expand("")) -" call Decho("COMBAK#21 : mod=".&mod." win#".winnr()) " extract tree directory if on a line specifying a subdirectory (ie. ends with "/") let curline= substitute(getline('.'),"\t -->.*$",'','') if curline =~ '/$' -" call Decho("extract tree subdirectory from current line",'~'.expand("")) let treedir= substitute(getline('.'),'^\%('.s:treedepthstring.'\)*\([^'.s:treedepthstring.'].\{-}\)$','\1','e') -" call Decho("treedir<".treedir.">",'~'.expand("")) elseif curline =~ '@$' -" call Decho("handle symbolic link from current line",'~'.expand("")) - let potentialdir= resolve(substitute(substitute(getline('.'),'@.*$','','e'),'^|*\s*','','e')) -" call Decho("treedir<".treedir.">",'~'.expand("")) + let potentialdir= resolve(s:NetrwTreePath(w:netrw_treetop)) else -" call Decho("do not extract tree subdirectory from current line and set treedir to empty",'~'.expand("")) let treedir= "" endif -" call Decho("COMBAK#22 : mod=".&mod." win#".winnr()) " detect user attempting to close treeroot -" call Decho("check if user is attempting to close treeroot",'~'.expand("")) -" call Decho(".win#".winnr()." buf#".bufnr("%")."<".bufname("%").">",'~'.expand("")) -" call Decho(".getline(".line(".").")<".getline('.').'> '.((getline('.') =~# '^'.s:treedepthstring)? '=~#' : '!~').' ^'.s:treedepthstring,'~'.expand("")) if curline !~ '^'.s:treedepthstring && getline('.') != '..' -" call Decho(".user may have attempted to close treeroot",'~'.expand("")) " now force a refresh -" call Decho(".force refresh: clear buffer<".expand("%")."> with :%d",'~'.expand("")) sil! NetrwKeepj %d _ -" call Dret("s:NetrwTreeDir <".treedir."> : (side effect) s:treecurpos<".(exists("s:treecurpos")? string(s:treecurpos) : 'n/a').">") return b:netrw_curdir -" else " Decho -" call Decho(".user not attempting to close treeroot",'~'.expand("")) endif -" call Decho("COMBAK#23 : mod=".&mod." win#".winnr()) - -" call Decho("islocal=".a:islocal." curline<".curline.">",'~'.expand("")) -" call Decho("potentialdir<".potentialdir."> isdir=".isdirectory(potentialdir),'~'.expand("")) -" call Decho("COMBAK#24 : mod=".&mod." win#".winnr()) " COMBAK: a symbolic link may point anywhere -- so it will be used to start a new treetop " if a:islocal && curline =~ '@$' && isdirectory(s:NetrwFile(potentialdir)) " let newdir = w:netrw_treetop.'/'.potentialdir -" " call Decho("apply NetrwTreePath to newdir<".newdir.">",'~'.expand("")) -" let treedir = s:NetrwTreePath(newdir) -" let w:netrw_treetop = newdir -" " call Decho("newdir <".newdir.">",'~'.expand("")) -" else -" call Decho("apply NetrwTreePath to treetop<".w:netrw_treetop.">",'~'.expand("")) if a:islocal && curline =~ '@$' if isdirectory(s:NetrwFile(potentialdir)) - let treedir = w:netrw_treetop.'/'.potentialdir.'/' + let treedir = potentialdir let w:netrw_treetop = treedir endif else @@ -9430,29 +8786,21 @@ fun! s:NetrwTreeDir(islocal) let treedir = s:NetrwTreePath(w:netrw_treetop) endif endif -" call Decho("COMBAK#25 : mod=".&mod." win#".winnr()) " sanity maintenance: keep those //s away... let treedir= substitute(treedir,'//$','/','') -" call Decho("treedir<".treedir.">",'~'.expand("")) -" call Decho("COMBAK#26 : mod=".&mod." win#".winnr()) - -" call Dret("s:NetrwTreeDir <".treedir."> : (side effect) s:treecurpos<".(exists("s:treecurpos")? string(s:treecurpos) : 'n/a').">") return treedir endfun " --------------------------------------------------------------------- " s:NetrwTreeDisplay: recursive tree display {{{2 fun! s:NetrwTreeDisplay(dir,depth) -" call Dfunc("NetrwTreeDisplay(dir<".a:dir."> depth<".a:depth.">)") - - " insure that there are no folds + " ensure that there are no folds setl nofen " install ../ and shortdir if a:depth == "" call setline(line("$")+1,'../') -" call Decho("setline#".line("$")." ../ (depth is zero)",'~'.expand("")) endif if a:dir =~ '^\a\{3,}://' if a:dir == w:netrw_treetop @@ -9465,19 +8813,16 @@ fun! s:NetrwTreeDisplay(dir,depth) let shortdir= substitute(a:dir,'^.*/','','e') call setline(line("$")+1,a:depth.shortdir.'/') endif -" call Decho("setline#".line("$")." shortdir<".a:depth.shortdir.">",'~'.expand("")) " append a / to dir if its missing one let dir= a:dir " display subtrees (if any) let depth= s:treedepthstring.a:depth -" call Decho("display subtrees with depth<".depth."> and current leaves",'~'.expand("")) " implement g:netrw_hide for tree listings (uses g:netrw_list_hide) if g:netrw_hide == 1 " hide given patterns let listhide= split(g:netrw_list_hide,',') -" call Decho("listhide=".string(listhide)) for pat in listhide call filter(w:netrw_treedict[dir],'v:val !~ "'.escape(pat,'\\').'"') endfor @@ -9485,7 +8830,6 @@ fun! s:NetrwTreeDisplay(dir,depth) elseif g:netrw_hide == 2 " show given patterns (only) let listhide= split(g:netrw_list_hide,',') -" call Decho("listhide=".string(listhide)) let entries=[] for entry in w:netrw_treedict[dir] for pat in listhide @@ -9500,77 +8844,57 @@ fun! s:NetrwTreeDisplay(dir,depth) if depth != "" " always remove "." and ".." entries when there's depth call filter(w:netrw_treedict[dir],'v:val !~ "\\.\\.$"') + call filter(w:netrw_treedict[dir],'v:val !~ "\\.\\./$"') call filter(w:netrw_treedict[dir],'v:val !~ "\\.$"') + call filter(w:netrw_treedict[dir],'v:val !~ "\\./$"') endif -" call Decho("for every entry in w:netrw_treedict[".dir."]=".string(w:netrw_treedict[dir]),'~'.expand("")) for entry in w:netrw_treedict[dir] if dir =~ '/$' let direntry= substitute(dir.entry,'[@/]$','','e') else let direntry= substitute(dir.'/'.entry,'[@/]$','','e') endif -" call Decho("dir<".dir."> entry<".entry."> direntry<".direntry.">",'~'.expand("")) if entry =~ '/$' && has_key(w:netrw_treedict,direntry) -" call Decho("<".direntry."> is a key in treedict - display subtree for it",'~'.expand("")) NetrwKeepj call s:NetrwTreeDisplay(direntry,depth) elseif entry =~ '/$' && has_key(w:netrw_treedict,direntry.'/') -" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("")) NetrwKeepj call s:NetrwTreeDisplay(direntry.'/',depth) elseif entry =~ '@$' && has_key(w:netrw_treedict,direntry.'@') -" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("")) - NetrwKeepj call s:NetrwTreeDisplay(direntry.'/',depth) + NetrwKeepj call s:NetrwTreeDisplay(direntry.'@',depth) else -" call Decho("<".entry."> is not a key in treedict (no subtree)",'~'.expand("")) sil! NetrwKeepj call setline(line("$")+1,depth.entry) endif endfor -" call Decho("displaying: ".string(getline(w:netrw_bannercnt,'$'))) - -" call Dret("NetrwTreeDisplay") endfun " --------------------------------------------------------------------- " s:NetrwRefreshTreeDict: updates the contents information for a tree (w:netrw_treedict) {{{2 fun! s:NetrwRefreshTreeDict(dir) -" call Dfunc("s:NetrwRefreshTreeDict(dir<".a:dir.">)") if !exists("w:netrw_treedict") -" call Dret("s:NetrwRefreshTreeDict : w:netrw_treedict doesn't exist") return endif for entry in w:netrw_treedict[a:dir] let direntry= substitute(a:dir.'/'.entry,'[@/]$','','e') -" call Decho("a:dir<".a:dir."> entry<".entry."> direntry<".direntry.">",'~'.expand("")) if entry =~ '/$' && has_key(w:netrw_treedict,direntry) -" call Decho("<".direntry."> is a key in treedict - display subtree for it",'~'.expand("")) NetrwKeepj call s:NetrwRefreshTreeDict(direntry) - let liststar = s:NetrwGlob(direntry,'*',1) - let listdotstar = s:NetrwGlob(direntry,'.*',1) - let w:netrw_treedict[direntry] = liststar + listdotstar -" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("")) + let filelist = s:NetrwLocalListingList(direntry,0) + let w:netrw_treedict[direntry] = sort(filelist) elseif entry =~ '/$' && has_key(w:netrw_treedict,direntry.'/') -" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("")) NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/') - let liststar = s:NetrwGlob(direntry.'/','*',1) - let listdotstar= s:NetrwGlob(direntry.'/','.*',1) - let w:netrw_treedict[direntry]= liststar + listdotstar -" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("")) + let filelist = s:NetrwLocalListingList(direntry.'/',0) + let w:netrw_treedict[direntry] = sort(filelist) elseif entry =~ '@$' && has_key(w:netrw_treedict,direntry.'@') -" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("")) NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/') let liststar = s:NetrwGlob(direntry.'/','*',1) let listdotstar= s:NetrwGlob(direntry.'/','.*',1) -" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("")) else -" call Decho('not updating w:netrw_treedict['.string(direntry).'] with entry<'.string(entry).'> (no subtree)','~'.expand("")) endif endfor -" call Dret("s:NetrwRefreshTreeDict") endfun " --------------------------------------------------------------------- @@ -10478,15 +9802,11 @@ endfun " --------------------------------------------------------------------- " s:NetrwRemoteRm: remove/delete a remote file or directory {{{2 fun! s:NetrwRemoteRm(usrhost,path) range -" call Dfunc("s:NetrwRemoteRm(usrhost<".a:usrhost."> path<".a:path.">) virtcol=".virtcol(".")) -" call Decho("firstline=".a:firstline." lastline=".a:lastline,'~'.expand("")) let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) let all= 0 if exists("s:netrwmarkfilelist_{bufnr('%')}") " remove all marked files -" call Decho("remove all marked files with bufnr#".bufnr("%"),'~'.expand("")) for fname in s:netrwmarkfilelist_{bufnr("%")} let ok= s:NetrwRemoteRmFile(a:path,fname,all) if ok =~# 'q\%[uit]' @@ -10499,7 +9819,6 @@ fun! s:NetrwRemoteRm(usrhost,path) range else " remove files specified by range -" call Decho("remove files specified by range",'~'.expand("")) " preparation for removing multiple files/directories let keepsol = &l:sol @@ -10521,12 +9840,8 @@ fun! s:NetrwRemoteRm(usrhost,path) range endif " refresh the (remote) directory listing -" call Decho("refresh remote directory listing",'~'.expand("")) - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) - -" call Dret("s:NetrwRemoteRm") endfun " --------------------------------------------------------------------- @@ -10652,7 +9967,6 @@ endfun " --------------------------------------------------------------------- " s:NetrwRemoteRename: rename a remote file or directory {{{2 fun! s:NetrwRemoteRename(usrhost,path) range -" call Dfunc("NetrwRemoteRename(usrhost<".a:usrhost."> path<".a:path.">)") " preparation for removing multiple files/directories let svpos = winsaveview() @@ -10663,10 +9977,8 @@ fun! s:NetrwRemoteRename(usrhost,path) range " rename files given by the markfilelist if exists("s:netrwmarkfilelist_{bufnr('%')}") for oldname in s:netrwmarkfilelist_{bufnr("%")} -" call Decho("oldname<".oldname.">",'~'.expand("")) if exists("subfrom") let newname= substitute(oldname,subfrom,subto,'') -" call Decho("subfrom<".subfrom."> subto<".subto."> newname<".newname.">",'~'.expand("")) else call inputsave() let newname= input("Moving ".oldname." to : ",oldname) @@ -10675,7 +9987,6 @@ fun! s:NetrwRemoteRename(usrhost,path) range let subfrom = substitute(newname,'^s/\([^/]*\)/.*/$','\1','') let subto = substitute(newname,'^s/[^/]*/\(.*\)/$','\1','') let newname = substitute(oldname,subfrom,subto,'') -" call Decho("subfrom<".subfrom."> subto<".subto."> newname<".newname.">",'~'.expand("")) endif endif @@ -10684,7 +9995,6 @@ fun! s:NetrwRemoteRename(usrhost,path) range else let oldname= s:ShellEscape(a:path.oldname) let newname= s:ShellEscape(a:path.newname) -" call Decho("system(netrw#WinPath(".rename_cmd.") ".oldname.' '.newname.")",'~'.expand("")) let ret = system(netrw#WinPath(rename_cmd).' '.oldname.' '.newname) endif @@ -10700,7 +10010,6 @@ fun! s:NetrwRemoteRename(usrhost,path) range exe "NetrwKeepj ".ctr let oldname= s:NetrwGetWord() -" call Decho("oldname<".oldname.">",'~'.expand("")) call inputsave() let newname= input("Moving ".oldname." to : ",oldname) @@ -10711,7 +10020,6 @@ fun! s:NetrwRemoteRename(usrhost,path) range else let oldname= s:ShellEscape(a:path.oldname) let newname= s:ShellEscape(a:path.newname) -" call Decho("system(netrw#WinPath(".rename_cmd.") ".oldname.' '.newname.")",'~'.expand("")) let ret = system(netrw#WinPath(rename_cmd).' '.oldname.' '.newname) endif @@ -10721,11 +10029,8 @@ fun! s:NetrwRemoteRename(usrhost,path) range endif " refresh the directory - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) - -" call Dret("NetrwRemoteRename") endfun " ========================================== @@ -10852,17 +10157,11 @@ endfun " buffers to be refreshed after a user has executed some shell command, " on the chance that s/he removed/created a file/directory with it. fun! s:LocalBrowseRefresh() -" call Dfunc("s:LocalBrowseRefresh() tabpagenr($)=".tabpagenr("$")) -" call Decho("s:netrw_browselist =".(exists("s:netrw_browselist")? string(s:netrw_browselist) : ''),'~'.expand("")) -" call Decho("w:netrw_bannercnt =".(exists("w:netrw_bannercnt")? string(w:netrw_bannercnt) : ''),'~'.expand("")) - " determine which buffers currently reside in a tab if !exists("s:netrw_browselist") -" call Dret("s:LocalBrowseRefresh : browselist is empty") return endif if !exists("w:netrw_bannercnt") -" call Dret("s:LocalBrowseRefresh : don't refresh when focus not on netrw window") return endif if !empty(getcmdwintype()) @@ -10872,7 +10171,6 @@ fun! s:LocalBrowseRefresh() if exists("s:netrw_events") && s:netrw_events == 1 " s:LocalFastBrowser gets called (indirectly) from a let s:netrw_events= 2 -" call Dret("s:LocalBrowseRefresh : avoid initial double refresh") return endif let itab = 1 @@ -10883,47 +10181,36 @@ fun! s:LocalBrowseRefresh() let itab = itab + 1 sil! tabn endwhile -" call Decho("buftablist".string(buftablist),'~'.expand("")) -" call Decho("s:netrw_browselist<".(exists("s:netrw_browselist")? string(s:netrw_browselist) : "").">",'~'.expand("")) " GO through all buffers on netrw_browselist (ie. just local-netrw buffers): " | refresh any netrw window " | wipe out any non-displaying netrw buffer let curwinid = win_getid(winnr()) let ibl = 0 for ibuf in s:netrw_browselist -" call Decho("bufwinnr(".ibuf.") index(buftablist,".ibuf.")=".index(buftablist,ibuf),'~'.expand("")) if bufwinnr(ibuf) == -1 && index(buftablist,ibuf) == -1 " wipe out any non-displaying netrw buffer " (ibuf not shown in a current window AND " ibuf not in any tab) -" call Decho("wiping buf#".ibuf,"<".bufname(ibuf).">",'~'.expand("")) exe "sil! keepj bd ".fnameescape(ibuf) call remove(s:netrw_browselist,ibl) -" call Decho("browselist=".string(s:netrw_browselist),'~'.expand("")) continue elseif index(tabpagebuflist(),ibuf) != -1 " refresh any netrw buffer -" call Decho("refresh buf#".ibuf.'-> win#'.bufwinnr(ibuf),'~'.expand("")) exe bufwinnr(ibuf)."wincmd w" if getline(".") =~# 'Quick Help' " decrement g:netrw_quickhelp to prevent refresh from changing g:netrw_quickhelp " (counteracts s:NetrwBrowseChgDir()'s incrementing) let g:netrw_quickhelp= g:netrw_quickhelp - 1 endif -" call Decho("#3: quickhelp=".g:netrw_quickhelp,'~'.expand("")) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST NetrwKeepj call s:NetrwRefreshTreeDict(w:netrw_treetop) endif - NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) + NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) endif let ibl= ibl + 1 -" call Decho("bottom of s:netrw_browselist for loop: ibl=".ibl,'~'.expand("")) endfor -" call Decho("restore window: win_gotoid(".curwinid.")") call win_gotoid(curwinid) let @@= ykeep - -" call Dret("s:LocalBrowseRefresh") endfun " --------------------------------------------------------------------- @@ -10945,22 +10232,15 @@ endfun " If :Explore used: it sets s:netrw_events to 2, so no FocusGained events are ignored. " =2: autocmds installed (doesn't ignore any FocusGained events) fun! s:LocalFastBrowser() -" call Dfunc("s:LocalFastBrowser() g:netrw_fastbrowse=".g:netrw_fastbrowse) -" call Decho("s:netrw_events ".(exists("s:netrw_events")? "exists" : 'n/a'),'~'.expand("")) -" call Decho("autocmd: ShellCmdPost ".(exists("#ShellCmdPost")? "already installed" : "not installed"),'~'.expand("")) -" call Decho("autocmd: FocusGained ".(exists("#FocusGained")? "already installed" : "not installed"),'~'.expand("")) " initialize browselist, a list of buffer numbers that the local browser has used if !exists("s:netrw_browselist") -" call Decho("initialize s:netrw_browselist",'~'.expand("")) let s:netrw_browselist= [] endif " append current buffer to fastbrowse list if empty(s:netrw_browselist) || bufnr("%") > s:netrw_browselist[-1] -" call Decho("appendng current buffer to browselist",'~'.expand("")) call add(s:netrw_browselist,bufnr("%")) -" call Decho("browselist=".string(s:netrw_browselist),'~'.expand("")) endif " enable autocmd events to handle refreshing/removing local browser buffers @@ -10974,10 +10254,8 @@ fun! s:LocalFastBrowser() augroup AuNetrwEvent au! if has("win32") -" call Decho("installing autocmd: ShellCmdPost",'~'.expand("")) au ShellCmdPost * call s:LocalBrowseRefresh() else -" call Decho("installing autocmds: ShellCmdPost FocusGained",'~'.expand("")) au ShellCmdPost,FocusGained * call s:LocalBrowseRefresh() endif augroup END @@ -10985,86 +10263,55 @@ fun! s:LocalFastBrowser() " user must have changed fastbrowse to its fast setting, so remove " the associated autocmd events elseif g:netrw_fastbrowse > 1 && exists("#ShellCmdPost") && exists("s:netrw_events") -" call Decho("remove AuNetrwEvent autcmd group",'~'.expand("")) unlet s:netrw_events augroup AuNetrwEvent au! augroup END augroup! AuNetrwEvent endif - -" call Dret("s:LocalFastBrowser : browselist<".string(s:netrw_browselist).">") endfun -" --------------------------------------------------------------------- -" s:LocalListing: does the job of "ls" for local directories {{{2 -fun! s:LocalListing() -" call Dfunc("s:LocalListing()") -" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("")) -" call Decho("modified=".&modified." modifiable=".&modifiable." readonly=".&readonly,'~'.expand("")) -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("")) - -" if exists("b:netrw_curdir") |call Decho('b:netrw_curdir<'.b:netrw_curdir.">") |else|call Decho("b:netrw_curdir doesn't exist",'~'.expand("")) |endif -" if exists("g:netrw_sort_by")|call Decho('g:netrw_sort_by<'.g:netrw_sort_by.">")|else|call Decho("g:netrw_sort_by doesn't exist",'~'.expand(""))|endif -" call Decho("g:netrw_banner=".g:netrw_banner.": banner ".(g:netrw_banner? "enabled" : "suppressed").": (line($)=".line("$")." byte2line(1)=".byte2line(1)." bannercnt=".w:netrw_bannercnt.")",'~'.expand("")) - +fun! s:NetrwLocalListingList(dirname,setmaxfilenamelen) " get the list of files contained in the current directory - let dirname = b:netrw_curdir - let dirnamelen = strlen(b:netrw_curdir) + let dirname = a:dirname + let dirnamelen = strlen(dirname) let filelist = s:NetrwGlob(dirname,"*",0) let filelist = filelist + s:NetrwGlob(dirname,".*",0) -" call Decho("filelist=".string(filelist),'~'.expand("")) if g:netrw_cygwin == 0 && has("win32") -" call Decho("filelist=".string(filelist),'~'.expand("")) - elseif index(filelist,'..') == -1 && b:netrw_curdir !~ '/' + elseif index(filelist,'..') == -1 && dirname !~ '/' " include ../ in the glob() entry if its missing -" call Decho("forcibly including on \"..\"",'~'.expand("")) - let filelist= filelist+[s:ComposePath(b:netrw_curdir,"../")] -" call Decho("filelist=".string(filelist),'~'.expand("")) + let filelist= filelist+[s:ComposePath(dirname,"../")] endif -" call Decho("before while: dirname <".dirname.">",'~'.expand("")) -" call Decho("before while: dirnamelen<".dirnamelen.">",'~'.expand("")) -" call Decho("before while: filelist =".string(filelist),'~'.expand("")) - - if get(g:, 'netrw_dynamic_maxfilenamelen', 0) + if a:setmaxfilenamelen && get(g:, 'netrw_dynamic_maxfilenamelen', 0) let filelistcopy = map(deepcopy(filelist),'fnamemodify(v:val, ":t")') let g:netrw_maxfilenamelen = max(map(filelistcopy,'len(v:val)')) + 1 -" call Decho("dynamic_maxfilenamelen: filenames =".string(filelistcopy),'~'.expand("")) -" call Decho("dynamic_maxfilenamelen: g:netrw_maxfilenamelen=".g:netrw_maxfilenamelen,'~'.expand("")) endif -" call Decho("g:netrw_banner=".g:netrw_banner.": banner ".(g:netrw_banner? "enabled" : "suppressed").": (line($)=".line("$")." byte2line(1)=".byte2line(1)." bannercnt=".w:netrw_bannercnt.")",'~'.expand("")) + let resultfilelist = [] for filename in filelist -" call Decho(" ",'~'.expand("")) -" call Decho("for filename in filelist: filename<".filename.">",'~'.expand("")) if getftype(filename) == "link" " indicate a symbolic link -" call Decho("indicate <".filename."> is a symbolic link with trailing @",'~'.expand("")) let pfile= filename."@" elseif getftype(filename) == "socket" " indicate a socket -" call Decho("indicate <".filename."> is a socket with trailing =",'~'.expand("")) let pfile= filename."=" elseif getftype(filename) == "fifo" " indicate a fifo -" call Decho("indicate <".filename."> is a fifo with trailing |",'~'.expand("")) let pfile= filename."|" elseif isdirectory(s:NetrwFile(filename)) " indicate a directory -" call Decho("indicate <".filename."> is a directory with trailing /",'~'.expand("")) let pfile= filename."/" elseif exists("b:netrw_curdir") && b:netrw_curdir !~ '^.*://' && !isdirectory(s:NetrwFile(filename)) if has("win32") if filename =~ '\.[eE][xX][eE]$' || filename =~ '\.[cC][oO][mM]$' || filename =~ '\.[bB][aA][tT]$' " indicate an executable -" call Decho("indicate <".filename."> is executable with trailing *",'~'.expand("")) let pfile= filename."*" else " normal file @@ -11072,7 +10319,6 @@ fun! s:LocalListing() endif elseif executable(filename) " indicate an executable -" call Decho("indicate <".filename."> is executable with trailing *",'~'.expand("")) let pfile= filename."*" else " normal file @@ -11083,16 +10329,12 @@ fun! s:LocalListing() " normal file let pfile= filename endif -" call Decho("pfile<".pfile."> (after *@/ appending)",'~'.expand("")) if pfile =~ '//$' let pfile= substitute(pfile,'//$','/','e') -" call Decho("change // to /: pfile<".pfile.">",'~'.expand("")) endif let pfile= strpart(pfile,dirnamelen) let pfile= substitute(pfile,'^[/\\]','','e') -" call Decho("filename<".filename.">",'~'.expand("")) -" call Decho("pfile <".pfile.">",'~'.expand("")) if w:netrw_liststyle == s:LONGLIST let longfile = printf("%-".g:netrw_maxfilenamelen."S",pfile) @@ -11105,47 +10347,46 @@ fun! s:LocalListing() endif let fsz = printf("%".szlen."S",sz) let pfile= longfile." ".fsz." ".strftime(g:netrw_timefmt,getftime(filename)) -" call Decho("longlist support: sz=".sz." fsz=".fsz,'~'.expand("")) endif if g:netrw_sort_by =~# "^t" " sort by time (handles time up to 1 quintillion seconds, US) " Decorate listing by prepending a timestamp/ . Sorting will then be done based on time. -" call Decho("implementing g:netrw_sort_by=".g:netrw_sort_by." (time)") -" call Decho("getftime(".filename.")=".getftime(filename),'~'.expand("")) let t = getftime(filename) let ft = printf("%018d",t) -" call Decho("exe NetrwKeepj put ='".ft.'/'.pfile."'",'~'.expand("")) let ftpfile= ft.'/'.pfile - sil! NetrwKeepj put=ftpfile + let resultfilelist += [ftpfile] elseif g:netrw_sort_by =~ "^s" " sort by size (handles file sizes up to 1 quintillion bytes, US) -" call Decho("implementing g:netrw_sort_by=".g:netrw_sort_by." (size)") -" call Decho("getfsize(".filename.")=".getfsize(filename),'~'.expand("")) let sz = getfsize(filename) let fsz = printf("%018d",sz) -" call Decho("exe NetrwKeepj put ='".fsz.'/'.filename."'",'~'.expand("")) let fszpfile= fsz.'/'.pfile - sil! NetrwKeepj put =fszpfile + let resultfilelist += [fszpfile] else " sort by name -" call Decho("implementing g:netrw_sort_by=".g:netrw_sort_by." (name)") -" call Decho("exe NetrwKeepj put ='".pfile."'",'~'.expand("")) - sil! NetrwKeepj put=pfile + let resultfilelist += [pfile] endif -" call DechoBuf(bufnr("%"),"bufnr(%)") + endfor + + return resultfilelist +endfun + +" --------------------------------------------------------------------- +" s:LocalListing: does the job of "ls" for local directories {{{2 +fun! s:LocalListing() + + let filelist = s:NetrwLocalListingList(b:netrw_curdir, 1) + for filename in filelist + sil! NetrwKeepj put =filename endfor " cleanup any windows mess at end-of-line sil! NetrwKeepj g/^$/d sil! NetrwKeepj %s/\r$//e call histdel("/",-1) -" call Decho("exe setl ts=".(g:netrw_maxfilenamelen+1),'~'.expand("")) exe "setl ts=".(g:netrw_maxfilenamelen+1) - -" call Dret("s:LocalListing") endfun " --------------------------------------------------------------------- @@ -11179,7 +10420,6 @@ endfun " --------------------------------------------------------------------- " s:NetrwLocalRename: rename a local file or directory {{{2 fun! s:NetrwLocalRename(path) range -" call Dfunc("NetrwLocalRename(path<".a:path.">)") if !exists("w:netrw_bannercnt") let w:netrw_bannercnt= b:netrw_bannercnt @@ -11190,15 +10430,12 @@ fun! s:NetrwLocalRename(path) range let ctr = a:firstline let svpos = winsaveview() let all = 0 -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) " rename files given by the markfilelist if exists("s:netrwmarkfilelist_{bufnr('%')}") for oldname in s:netrwmarkfilelist_{bufnr("%")} -" call Decho("oldname<".oldname.">",'~'.expand("")) if exists("subfrom") let newname= substitute(oldname,subfrom,subto,'') -" call Decho("subfrom<".subfrom."> subto<".subto."> newname<".newname.">",'~'.expand("")) else call inputsave() let newname= input("Moving ".oldname." to : ",oldname,"file") @@ -11213,7 +10450,6 @@ fun! s:NetrwLocalRename(path) range if newname =~ '^s/' let subfrom = substitute(newname,'^s/\([^/]*\)/.*/$','\1','') let subto = substitute(newname,'^s/[^/]*/\(.*\)/$','\1','') -" call Decho("subfrom<".subfrom."> subto<".subto."> newname<".newname.">",'~'.expand("")) let newname = substitute(oldname,subfrom,subto,'') endif endif @@ -11225,12 +10461,9 @@ fun! s:NetrwLocalRename(path) range let all= 1 elseif response != "y" && response != "yes" " refresh the directory -" call Decho("refresh the directory listing",'~'.expand("")) - NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep -" call Dret("NetrwLocalRename") return endif endif @@ -11257,35 +10490,25 @@ fun! s:NetrwLocalRename(path) range NetrwKeepj norm! 0 let oldname= s:ComposePath(a:path,curword) -" call Decho("oldname<".oldname.">",'~'.expand("")) call inputsave() let newname= input("Moving ".oldname." to : ",substitute(oldname,'/*$','','e')) call inputrestore() call rename(oldname,newname) -" call Decho("renaming <".oldname."> to <".newname.">",'~'.expand("")) - let ctr= ctr + 1 endwhile endif " refresh the directory -" call Decho("refresh the directory listing",'~'.expand("")) - NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep - -" call Dret("NetrwLocalRename") endfun " --------------------------------------------------------------------- " s:NetrwLocalRm: {{{2 fun! s:NetrwLocalRm(path) range -" call Dfunc("s:NetrwLocalRm(path<".a:path.">)") -" call Decho("firstline=".a:firstline." lastline=".a:lastline,'~'.expand("")) - if !exists("w:netrw_bannercnt") let w:netrw_bannercnt= b:netrw_bannercnt endif @@ -11295,11 +10518,9 @@ fun! s:NetrwLocalRm(path) range let ret = 0 let all = 0 let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) if exists("s:netrwmarkfilelist_{bufnr('%')}") " remove all marked files -" call Decho("remove all marked files",'~'.expand("")) for fname in s:netrwmarkfilelist_{bufnr("%")} let ok= s:NetrwLocalRmFile(a:path,fname,all) if ok =~# 'q\%[uit]' || ok == "no" @@ -11312,7 +10533,6 @@ fun! s:NetrwLocalRm(path) range else " remove (multiple) files and directories -" call Decho("remove files in range [".a:firstline.",".a:lastline."]",'~'.expand("")) let keepsol= &l:sol setl nosol @@ -11342,15 +10562,11 @@ fun! s:NetrwLocalRm(path) range endif " refresh the directory -" call Decho("bufname<".bufname("%").">",'~'.expand("")) if bufname("%") != "NetrwMessage" - NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) NetrwKeepj call winrestview(svpos) endif let @@= ykeep - -" call Dret("s:NetrwLocalRm") endfun " --------------------------------------------------------------------- @@ -12519,29 +11735,24 @@ endfun " --------------------------------------------------------------------- " s:ShowLink: used to modify thin and tree listings to show links {{{2 fun! s:ShowLink() -" " call Dfunc("s:ShowLink()") -" " call Decho("b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "doesn't exist").">",'~'.expand("")) -" " call Decho(printf("line#%4d: %s",line("."),getline(".")),'~'.expand("")) if exists("b:netrw_curdir") norm! $?\a - let fname = b:netrw_curdir.'/'.s:NetrwGetWord() + if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treetop") + let basedir = s:NetrwTreePath(w:netrw_treetop) + else + let basedir = b:netrw_curdir.'/' + endif + let fname = basedir.s:NetrwGetWord() let resname = resolve(fname) -" " call Decho("fname <".fname.">",'~'.expand("")) -" " call Decho("resname <".resname.">",'~'.expand("")) -" " call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("")) - if resname =~ '^\M'.b:netrw_curdir.'/' - let dirlen = strlen(b:netrw_curdir) - let resname = strpart(resname,dirlen+1) -" " call Decho("resname<".resname."> (b:netrw_curdir elided)",'~'.expand("")) + if resname =~ '^\M'.basedir + let dirlen = strlen(basedir) + let resname = strpart(resname,dirlen) endif let modline = getline(".")."\t --> ".resname -" " call Decho("fname <".fname.">",'~'.expand("")) -" " call Decho("modline<".modline.">",'~'.expand("")) setl noro ma call setline(".",modline) setl ro noma nomod endif -" " call Dret("s:ShowLink".((exists("fname")? ' : '.fname : 'n/a'))) endfun " --------------------------------------------------------------------- @@ -12702,8 +11913,6 @@ endfun " * interprets result " See netrw#UserMaps() fun! s:UserMaps(islocal,funcname) -" call Dfunc("s:UserMaps(islocal=".a:islocal.",funcname<".a:funcname.">)") - if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() endif @@ -12712,30 +11921,22 @@ fun! s:UserMaps(islocal,funcname) if type(result) == 1 " if result from user's funcref is a string... -" call Decho("result string from user funcref<".result.">",'~'.expand("")) if result == "refresh" -" call Decho("refreshing display",'~'.expand("")) - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) elseif result != "" -" call Decho("executing result<".result.">",'~'.expand("")) exe result endif elseif type(result) == 3 " if result from user's funcref is a List... -" call Decho("result List from user funcref<".string(result).">",'~'.expand("")) for action in result if action == "refresh" -" call Decho("refreshing display",'~'.expand("")) - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) elseif action != "" -" call Decho("executing action<".action.">",'~'.expand("")) exe action endif endfor endif - -" call Dret("s:UserMaps") endfun " ========================== From 6d9a145d719857fe461d045adf3b61ec4b4bb53f Mon Sep 17 00:00:00 2001 From: Konfekt Date: Thu, 7 Nov 2024 21:40:22 +0100 Subject: [PATCH 041/106] runtime(compiler): add mypy and ruff compiler; update pylint linter mypy and ruff come from https://github.com/Konfekt/vim-compilers/tree/master/compiler and the former was added by @pbnj-dragon closes: #16007 Signed-off-by: Konfekt Signed-off-by: Christian Brabandt --- runtime/compiler/mypy.vim | 19 +++++++++++++++++++ runtime/compiler/pylint.vim | 26 +++++++++++++++++--------- runtime/compiler/ruff.vim | 19 +++++++++++++++++++ runtime/doc/quickfix.txt | 29 ++++++++++++++++++++++++++++- runtime/doc/tags | 3 +++ 5 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 runtime/compiler/mypy.vim create mode 100644 runtime/compiler/ruff.vim diff --git a/runtime/compiler/mypy.vim b/runtime/compiler/mypy.vim new file mode 100644 index 0000000000..891488626a --- /dev/null +++ b/runtime/compiler/mypy.vim @@ -0,0 +1,19 @@ +" Vim compiler file +" Compiler: Mypy (Python static checker) +" Maintainer: @Konfekt +" Last Change: 2024 Nov 07 + +if exists("current_compiler") | finish | endif +let current_compiler = "mypy" + +let s:cpo_save = &cpo +set cpo&vim + +" CompilerSet makeprg=mypy +let &l:makeprg = 'mypy --show-column-numbers ' + \ ..get(b:, 'mypy_makeprg_params', get(g:, 'mypy_makeprg_params', '--strict --ignore-missing-imports')) +exe 'CompilerSet makeprg='..escape(&l:makeprg, ' "') +CompilerSet errorformat=%f:%l:%c:\ %t%*[^:]:\ %m + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/compiler/pylint.vim b/runtime/compiler/pylint.vim index 14e9696dbb..59408b4750 100644 --- a/runtime/compiler/pylint.vim +++ b/runtime/compiler/pylint.vim @@ -1,13 +1,21 @@ " Vim compiler file -" Compiler: Pylint for Python -" Maintainer: Daniel Moch -" Last Change: 2016 May 20 -" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) - -if exists("current_compiler") - finish -endif +" Compiler: Pylint for Python +" Maintainer: Daniel Moch +" Last Change: 2024 Nov 07 by The Vim Project (added params variable) + +if exists("current_compiler") | finish | endif let current_compiler = "pylint" -CompilerSet makeprg=pylint\ --output-format=text\ --msg-template=\"{path}:{line}:{column}:{C}:\ [{symbol}]\ {msg}\"\ --reports=no +let s:cpo_save = &cpo +set cpo&vim + +" CompilerSet makeprg=ruff +let &l:makeprg = 'pylint ' . + \ '--output-format=text --msg-template="{path}:{line}:{column}:{C}: [{symbol}] {msg}" --reports=no ' . + \ get(b:, "pylint_makeprg_params", get(g:, "pylint_makeprg_params", + \ (executable('getconf') ? '--jobs='..systemlist('getconf _NPROCESSORS_ONLN')[0] : ''))) +exe 'CompilerSet makeprg='..escape(&l:makeprg, ' "') CompilerSet errorformat=%A%f:%l:%c:%t:\ %m,%A%f:%l:\ %m,%A%f:(%l):\ %m,%-Z%p^%.%#,%-G%.%# + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/compiler/ruff.vim b/runtime/compiler/ruff.vim new file mode 100644 index 0000000000..11a69740d8 --- /dev/null +++ b/runtime/compiler/ruff.vim @@ -0,0 +1,19 @@ +" Vim compiler file +" Compiler: Ruff (Python linter) +" Maintainer: @pbnj-dragon +" Last Change: 2024 Nov 07 + +if exists("current_compiler") | finish | endif +let current_compiler = "ruff" + +let s:cpo_save = &cpo +set cpo&vim + +" CompilerSet makeprg=ruff +let &l:makeprg= 'ruff check --output-format=concise ' + \ ..get(b:, 'ruff_makeprg_params', get(g:, 'ruff_makeprg_params', '--preview')) +exe 'CompilerSet makeprg='..escape(&l:makeprg, ' "') +CompilerSet errorformat=%f:%l:%c:\ %m,%f:%l:\ %m,%f:%l:%c\ -\ %m,%f: + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index e7536446b2..37f0a181d1 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1,4 +1,4 @@ -*quickfix.txt* For Vim version 9.1. Last change: 2024 Oct 05 +*quickfix.txt* For Vim version 9.1. Last change: 2024 Nov 07 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1405,6 +1405,33 @@ being checked. To disable this set g:perl_compiler_force_warnings to a zero value. For example: > let g:perl_compiler_force_warnings = 0 +MYPY TYPE CHECKER *compiler-mypy* + +Commonly used compiler options can be added to 'makeprg' by setting the +b/g:mypy_makeprg_params variable. For example: > + + let b:mypy_makeprg_params = "--warn-unused-ignores" + +The global default is "--strict --ignore-missing-imports". + +RUFF LINTER *compiler-ruff* + +Commonly used compiler options can be added to 'makeprg' by setting the +b/g:ruff_makeprg_params variable. For example: > + + let b:ruff_makeprg_params = "--max-line-length"..&textwidth + +The global default is "--preview". + +PYLINT LINTER *compiler-pylint* + +Commonly used compiler options can be added to 'makeprg' by setting the +b/g:pylint_makeprg_params variable. For example: > + + let b:pylint_makeprg_params = "--max-line-length"..&textwidth + +The global default is "--jobs=n" where n is the number of cores as reported +by getconf, if executable. Otherwise it defaults to "". PYUNIT COMPILER *compiler-pyunit* diff --git a/runtime/doc/tags b/runtime/doc/tags index 37a8e266d5..82a01e2d73 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -6560,9 +6560,12 @@ compiler-hpada ft_ada.txt /*compiler-hpada* compiler-javac quickfix.txt /*compiler-javac* compiler-make quickfix.txt /*compiler-make* compiler-manx quickfix.txt /*compiler-manx* +compiler-mypy quickfix.txt /*compiler-mypy* compiler-pandoc quickfix.txt /*compiler-pandoc* compiler-perl quickfix.txt /*compiler-perl* +compiler-pylint quickfix.txt /*compiler-pylint* compiler-pyunit quickfix.txt /*compiler-pyunit* +compiler-ruff quickfix.txt /*compiler-ruff* compiler-select quickfix.txt /*compiler-select* compiler-tex quickfix.txt /*compiler-tex* compiler-typst quickfix.txt /*compiler-typst* From c9e8640476e0e3df8584ccaa03411b58489a8837 Mon Sep 17 00:00:00 2001 From: h-east Date: Thu, 7 Nov 2024 21:53:45 +0100 Subject: [PATCH 042/106] runtime(doc): Add pi_tutor.txt to help TOC closes: #16006 Signed-off-by: h-east Signed-off-by: Christian Brabandt --- runtime/doc/help.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index faa5f32715..77ea273ec6 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -1,4 +1,4 @@ -*help.txt* For Vim version 9.1. Last change: 2024 May 27 +*help.txt* For Vim version 9.1. Last change: 2024 Nov 07 VIM - main help file k @@ -232,6 +232,7 @@ Standard plugins ~ |pi_paren.txt| Highlight matching parens |pi_spec.txt| Filetype plugin to work with rpm spec files |pi_tar.txt| Tar file explorer +|pi_tutor.txt| Interactive tutorial for Vim |pi_vimball.txt| Create a self-installing Vim script |pi_zip.txt| Zip archive explorer From 6e410c9112497206c12330ab8a827b9d061579a9 Mon Sep 17 00:00:00 2001 From: Ron Aaron Date: Thu, 7 Nov 2024 21:59:44 +0100 Subject: [PATCH 043/106] runtime(8th): updated 8th syntax closes: #16005 Signed-off-by: Ron Aaron Signed-off-by: Christian Brabandt --- runtime/syntax/8th.vim | 501 +++++++++++++++++++++-------------------- 1 file changed, 258 insertions(+), 243 deletions(-) diff --git a/runtime/syntax/8th.vim b/runtime/syntax/8th.vim index a88a5a294a..e53c185df1 100644 --- a/runtime/syntax/8th.vim +++ b/runtime/syntax/8th.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: 8th -" Version: 23.09.01 -" Last Change: 2023 Dec 19 +" Version: 24.08 +" Last Change: 2024 Nov 07 " Maintainer: Ron Aaron " URL: https://8th-dev.com/ " Filetypes: *.8th @@ -36,16 +36,16 @@ com! -nargs=+ Builtin syn keyword eighthBuiltin Builtin gen-secret 2fa:gen-secret gen-url 2fa:gen-url validate-code 2fa:validate-code cb AWS:cb cli AWS:cli -Builtin cmd AWS:cmd cp AWS:cp rc AWS:rc call DBUS:call init DBUS:init + DOM:+ - DOM:- attr! DOM:attr! -Builtin attr@ DOM:attr@ attrs DOM:attrs children DOM:children css-parse DOM:css-parse each DOM:each -Builtin find DOM:find new DOM:new type DOM:type ! G:! !if G:!if #! G:#! ## G:## #if G:#if ' G:' ( G:( -Builtin (* G:(* (:) G:(:) (code) G:(code) (defer) G:(defer) (dump) G:(dump) (getc) G:(getc) (gets) G:(gets) +Builtin cmd AWS:cmd cp AWS:cp rc AWS:rc LIBS DBUS:LIBS call DBUS:call init DBUS:init + DOM:+ - DOM:- +Builtin attr! DOM:attr! attr@ DOM:attr@ attrs DOM:attrs children DOM:children css-parse DOM:css-parse +Builtin each DOM:each find DOM:find new DOM:new type DOM:type ! G:! !if G:!if #! G:#! ## G:## #if G:#if +Builtin ' G:' ( G:( (:) G:(:) (code) G:(code) (defer) G:(defer) (dump) G:(dump) (getc) G:(getc) (gets) G:(gets) Builtin (interp) G:(interp) (log) G:(log) (needs) G:(needs) (parseln) G:(parseln) (putc) G:(putc) (puts) G:(puts) -Builtin (stat) G:(stat) (with) G:(with) ) G:) +hook G:+hook +ref G:+ref ,# G:,# -- G:-- -----BEGIN G:-----BEGIN +Builtin (stat) G:(stat) (with) G:(with) ) G:) +hook G:+hook +ref G:+ref ,# G:,# -----BEGIN G:-----BEGIN Builtin -Inf G:-Inf -Inf? G:-Inf? -hook G:-hook -ref G:-ref -rot G:-rot . G:. .# G:.# .hook G:.hook Builtin .needs G:.needs .r G:.r .s G:.s .s-truncate G:.s-truncate .stats G:.stats .ver G:.ver .with G:.with Builtin 0; G:0; 2dip G:2dip 2drop G:2drop 2dup G:2dup 2nip G:2nip 2over G:2over 2swap G:2swap 2tuck G:2tuck -Builtin 3drop G:3drop 3drop G:3drop 3dup G:3dup 3rev G:3rev 4drop G:4drop 8thdt? G:8thdt? 8thsku G:8thsku +Builtin 3drop G:3drop 3drop G:3drop 3dup G:3dup 3rev G:3rev 4drop G:4drop 8thdt? G:8thdt? 8thsku? G:8thsku? Builtin 8thver? G:8thver? 8thvernum? G:8thvernum? : G:: ; G:; ;; G:;; ;;; G:;;; ;with G:;with >clip G:>clip Builtin >json G:>json >kind G:>kind >n G:>n >r G:>r >s G:>s ?: G:?: ?@ G:?@ @ G:@ BITMAP: G:BITMAP: Builtin ENUM: G:ENUM: FLAG: G:FLAG: I G:I Inf G:Inf Inf? G:Inf? J G:J K G:K NaN G:NaN NaN? G:NaN? SED-CHECK G:SED-CHECK @@ -59,16 +59,17 @@ Builtin counting-allocations G:counting-allocations cr G:cr critical: G:critica Builtin curlang G:curlang curry G:curry curry: G:curry: decimal G:decimal default: G:default: defer: G:defer: Builtin deferred: G:deferred: deg>rad G:deg>rad depth G:depth die G:die dip G:dip drop G:drop dstack G:dstack Builtin dump G:dump dup G:dup dup>r G:dup>r dup? G:dup? e# G:e# enum: G:enum: error? G:error? eval G:eval -Builtin eval! G:eval! eval0 G:eval0 expect G:expect extra! G:extra! extra@ G:extra@ false G:false fnv G:fnv -Builtin fourth G:fourth free G:free func: G:func: getc G:getc getcwd G:getcwd getenv G:getenv gets G:gets -Builtin handler G:handler header G:header help G:help hex G:hex i: G:i: i; G:i; isa? G:isa? items-used G:items-used -Builtin jcall G:jcall jclass G:jclass jmethod G:jmethod json! G:json! json-8th> G:json-8th> json-nesting G:json-nesting -Builtin json-pretty G:json-pretty json-throw G:json-throw json> G:json> json@ G:json@ k32 G:k32 keep G:keep -Builtin l: G:l: last G:last lib G:lib libbin G:libbin libc G:libc literal G:literal locals: G:locals: -Builtin lock G:lock lock-to G:lock-to locked? G:locked? log G:log log-syslog G:log-syslog log-task G:log-task -Builtin log-time G:log-time log-time-local G:log-time-local long-days G:long-days long-months G:long-months -Builtin longjmp G:longjmp lookup G:lookup loop G:loop loop- G:loop- map? G:map? mark G:mark mark? G:mark? -Builtin mobile? G:mobile? n# G:n# name>os G:name>os name>sem G:name>sem ndrop G:ndrop needs G:needs +Builtin eval! G:eval! eval0 G:eval0 exit G:exit expect G:expect extra! G:extra! extra@ G:extra@ false G:false +Builtin fnv G:fnv fourth G:fourth free G:free func: G:func: getc G:getc getcwd G:getcwd getenv G:getenv +Builtin gets G:gets goto G:goto handler G:handler header G:header help G:help help_db G:help_db here G:here +Builtin hex G:hex i: G:i: i; G:i; isa? G:isa? items-used G:items-used jcall G:jcall jclass G:jclass +Builtin jmethod G:jmethod json! G:json! json-8th> G:json-8th> json-nesting G:json-nesting json-pretty G:json-pretty +Builtin json-throw G:json-throw json> G:json> json@ G:json@ k32 G:k32 keep G:keep l: G:l: last G:last +Builtin lib G:lib libbin G:libbin libc G:libc libimg G:libimg literal G:literal locals: G:locals: lock G:lock +Builtin lock-to G:lock-to locked? G:locked? log G:log log-syslog G:log-syslog log-task G:log-task log-time G:log-time +Builtin log-time-local G:log-time-local long-days G:long-days long-months G:long-months longjmp G:longjmp +Builtin lookup G:lookup loop G:loop loop- G:loop- map? G:map? mark G:mark mark? G:mark? mobile? G:mobile? +Builtin n# G:n# name>os G:name>os name>sem G:name>sem ndrop G:ndrop needs G:needs needs-throws G:needs-throws Builtin new G:new next-arg G:next-arg nip G:nip noop G:noop not G:not nothrow G:nothrow ns G:ns ns: G:ns: Builtin ns>ls G:ns>ls ns>s G:ns>s ns? G:ns? null G:null null; G:null; null? G:null? nullvar G:nullvar Builtin number? G:number? of: G:of: off G:off on G:on onexit G:onexit only G:only op! G:op! or G:or @@ -76,128 +77,132 @@ Builtin os G:os os-names G:os-names os>long-name G:os>long-name os>name G:os>na Builtin pack G:pack parse G:parse parse-csv G:parse-csv parse-date G:parse-date parsech G:parsech parseln G:parseln Builtin parsews G:parsews pick G:pick poke G:poke pool-clear G:pool-clear pool-clear-all G:pool-clear-all Builtin prior G:prior private G:private process-args G:process-args process-args-fancy G:process-args-fancy -Builtin process-args-help G:process-args-help process-args-vars G:process-args-vars prompt G:prompt -Builtin public G:public putc G:putc puts G:puts quote G:quote r! G:r! r> G:r> r@ G:r@ rad>deg G:rad>deg -Builtin rand-jit G:rand-jit rand-jsf G:rand-jsf rand-native G:rand-native rand-normal G:rand-normal -Builtin rand-pcg G:rand-pcg rand-pcg-seed G:rand-pcg-seed rand-range G:rand-range rand-select G:rand-select -Builtin randbuf-pcg G:randbuf-pcg random G:random rdrop G:rdrop recurse G:recurse recurse-stack G:recurse-stack -Builtin ref@ G:ref@ reg! G:reg! reg@ G:reg@ regbin@ G:regbin@ remaining-args G:remaining-args repeat G:repeat -Builtin required? G:required? requires G:requires reset G:reset roll G:roll rop! G:rop! rot G:rot rpick G:rpick -Builtin rreset G:rreset rroll G:rroll rstack G:rstack rswap G:rswap rusage G:rusage s>ns G:s>ns same? G:same? -Builtin scriptdir G:scriptdir scriptfile G:scriptfile sem G:sem sem-post G:sem-post sem-rm G:sem-rm -Builtin sem-wait G:sem-wait sem-wait? G:sem-wait? sem>name G:sem>name semi-throw G:semi-throw set-wipe G:set-wipe -Builtin setenv G:setenv setjmp G:setjmp settings! G:settings! settings![] G:settings![] settings@ G:settings@ -Builtin settings@? G:settings@? settings@[] G:settings@[] sh G:sh sh$ G:sh$ short-days G:short-days -Builtin short-months G:short-months sleep G:sleep sleep-msec G:sleep-msec sleep-until G:sleep-until -Builtin slog G:slog space G:space stack-check G:stack-check stack-size G:stack-size step G:step sthrow G:sthrow -Builtin string? G:string? struct: G:struct: swap G:swap tab-hook G:tab-hook tell-conflict G:tell-conflict -Builtin tempdir G:tempdir tempfilename G:tempfilename third G:third throw G:throw thrownull G:thrownull -Builtin times G:times tlog G:tlog tri G:tri true G:true tuck G:tuck type-check G:type-check typeassert G:typeassert -Builtin uid G:uid uname G:uname unlock G:unlock unpack G:unpack until G:until until! G:until! while G:while -Builtin while! G:while! with: G:with: word? G:word? words G:words words-like G:words-like words/ G:words/ -Builtin xchg G:xchg xor G:xor >auth HTTP:>auth (curry) I:(curry) notimpl I:notimpl sh I:sh trace-word I:trace-word -Builtin call JSONRPC:call auth-string OAuth:auth-string gen-nonce OAuth:gen-nonce params OAuth:params -Builtin call SOAP:call ! a:! + a:+ - a:- / a:/ 2each a:2each 2map a:2map 2map+ a:2map+ 2map= a:2map= -Builtin <> a:<> = a:= @ a:@ @? a:@? _@ a:_@ all a:all any a:any bsearch a:bsearch centroid a:centroid -Builtin clear a:clear close a:close cmp a:cmp diff a:diff dot a:dot each a:each each! a:each! each-par a:each-par -Builtin each-slice a:each-slice exists? a:exists? filter a:filter filter-par a:filter-par generate a:generate -Builtin group a:group indexof a:indexof insert a:insert intersect a:intersect join a:join len a:len -Builtin map a:map map+ a:map+ map-par a:map-par map= a:map= maxlen a:maxlen mean a:mean mean&variance a:mean&variance -Builtin merge a:merge new a:new op! a:op! open a:open pigeon a:pigeon pivot a:pivot pop a:pop push a:push +Builtin process-args-help G:process-args-help prompt G:prompt public G:public putc G:putc puts G:puts +Builtin quote G:quote r! G:r! r> G:r> r@ G:r@ rad>deg G:rad>deg rand-jit G:rand-jit rand-jsf G:rand-jsf +Builtin rand-native G:rand-native rand-normal G:rand-normal rand-pcg G:rand-pcg rand-pcg-seed G:rand-pcg-seed +Builtin rand-range G:rand-range rand-select G:rand-select randbuf-pcg G:randbuf-pcg random G:random +Builtin rdrop G:rdrop recurse G:recurse recurse-stack G:recurse-stack ref@ G:ref@ reg! G:reg! reg@ G:reg@ +Builtin regbin@ G:regbin@ remaining-args G:remaining-args repeat G:repeat requires G:requires reset G:reset +Builtin roll G:roll rop! G:rop! rot G:rot rpick G:rpick rreset G:rreset rroll G:rroll rstack G:rstack +Builtin rswap G:rswap rusage G:rusage s>ns G:s>ns same? G:same? scriptdir G:scriptdir scriptfile G:scriptfile +Builtin sem G:sem sem-post G:sem-post sem-rm G:sem-rm sem-wait G:sem-wait sem-wait? G:sem-wait? sem>name G:sem>name +Builtin semi-throw G:semi-throw set-wipe G:set-wipe setenv G:setenv setjmp G:setjmp settings! G:settings! +Builtin settings![] G:settings![] settings@ G:settings@ settings@? G:settings@? settings@[] G:settings@[] +Builtin sh G:sh sh$ G:sh$ short-days G:short-days short-months G:short-months sleep G:sleep sleep-msec G:sleep-msec +Builtin sleep-until G:sleep-until slog G:slog space G:space stack-check G:stack-check stack-size G:stack-size +Builtin step G:step sthrow G:sthrow string? G:string? struct: G:struct: swap G:swap tab-hook G:tab-hook +Builtin tell-conflict G:tell-conflict tempdir G:tempdir tempfilename G:tempfilename third G:third throw G:throw +Builtin thrownull G:thrownull times G:times tlog G:tlog toggle G:toggle tri G:tri true G:true tuck G:tuck +Builtin type-check G:type-check typeassert G:typeassert uid G:uid uname G:uname unlock G:unlock unpack G:unpack +Builtin until G:until until! G:until! while G:while while! G:while! with: G:with: word? G:word? words G:words +Builtin words-like G:words-like words/ G:words/ xchg G:xchg xor G:xor >auth HTTP:>auth (curry) I:(curry) +Builtin appopts I:appopts notimpl I:notimpl sh I:sh trace-word I:trace-word call JSONRPC:call auth-string OAuth:auth-string +Builtin gen-nonce OAuth:gen-nonce params OAuth:params call SOAP:call ! a:! + a:+ - a:- / a:/ 2each a:2each +Builtin 2len a:2len 2map a:2map 2map+ a:2map+ 2map= a:2map= <> a:<> = a:= @ a:@ @? a:@? _@ a:_@ _len a:_len +Builtin all a:all any a:any bsearch a:bsearch centroid a:centroid clear a:clear close a:close cmp a:cmp +Builtin diff a:diff dot a:dot each a:each each! a:each! each-par a:each-par each-slice a:each-slice +Builtin exists? a:exists? filter a:filter filter-par a:filter-par generate a:generate group a:group +Builtin indexof a:indexof insert a:insert intersect a:intersect join a:join len a:len map a:map map+ a:map+ +Builtin map-par a:map-par map= a:map= maxlen a:maxlen mean a:mean mean&variance a:mean&variance merge a:merge +Builtin new a:new op! a:op! open a:open pigeon a:pigeon pivot a:pivot pop a:pop push a:push push' a:push' Builtin qsort a:qsort randeach a:randeach reduce a:reduce reduce+ a:reduce+ remove a:remove rev a:rev Builtin rindexof a:rindexof shift a:shift shuffle a:shuffle slice a:slice slice+ a:slice+ slide a:slide Builtin smear a:smear sort a:sort split a:split squash a:squash switch a:switch union a:union uniq a:uniq Builtin unzip a:unzip x a:x x-each a:x-each xchg a:xchg y a:y zip a:zip 8thdir app:8thdir asset app:asset Builtin atrun app:atrun atrun app:atrun atrun app:atrun basedir app:basedir basename app:basename config-file-name app:config-file-name Builtin current app:current datadir app:datadir display-moved app:display-moved exename app:exename -Builtin localechanged app:localechanged lowmem app:lowmem main app:main name app:name oncrash app:oncrash -Builtin opts! app:opts! opts@ app:opts@ orientation app:orientation orientation! app:orientation! pid app:pid -Builtin post-main app:post-main pre-main app:pre-main privdir app:privdir raise app:raise read-config app:read-config -Builtin read-config-map app:read-config-map read-config-var app:read-config-var request-perm app:request-perm -Builtin restart app:restart resumed app:resumed signal app:signal standalone app:standalone subdir app:subdir -Builtin suspended app:suspended sysquit app:sysquit terminated app:terminated timeout app:timeout trap app:trap -Builtin dawn astro:dawn do-dawn astro:do-dawn do-dusk astro:do-dusk do-rise astro:do-rise dusk astro:dusk -Builtin latitude astro:latitude location! astro:location! longitude astro:longitude sunrise astro:sunrise -Builtin genkeys auth:genkeys secret auth:secret session-id auth:session-id session-key auth:session-key +Builtin localechanged app:localechanged lowmem app:lowmem main app:main name app:name onback app:onback +Builtin oncrash app:oncrash opts! app:opts! opts@ app:opts@ orientation app:orientation orientation! app:orientation! +Builtin pid app:pid post-main app:post-main pre-main app:pre-main privdir app:privdir raise app:raise +Builtin read-config app:read-config read-config-map app:read-config-map read-config-var app:read-config-var +Builtin request-perm app:request-perm restart app:restart resumed app:resumed signal app:signal standalone app:standalone +Builtin standalone! app:standalone! subdir app:subdir suspended app:suspended sysquit app:sysquit terminated app:terminated +Builtin ticks app:ticks timeout app:timeout trap app:trap dawn astro:dawn do-dawn astro:do-dawn do-dusk astro:do-dusk +Builtin do-rise astro:do-rise dusk astro:dusk latitude astro:latitude location! astro:location! longitude astro:longitude +Builtin sunrise astro:sunrise genkeys auth:genkeys secret auth:secret session-id auth:session-id session-key auth:session-key Builtin validate auth:validate ! b:! + b:+ / b:/ 1+ b:1+ 1- b:1- <> b:<> = b:= >base16 b:>base16 >base32 b:>base32 -Builtin >base64 b:>base64 >base85 b:>base85 >hex b:>hex >mpack b:>mpack @ b:@ append b:append base16> b:base16> -Builtin base32> b:base32> base64> b:base64> base85> b:base85> bit! b:bit! bit@ b:bit@ clear b:clear -Builtin compress b:compress conv b:conv each b:each each! b:each! each-slice b:each-slice expand b:expand -Builtin fill b:fill getb b:getb hex> b:hex> len b:len mem> b:mem> move b:move mpack-compat b:mpack-compat +Builtin >base64 b:>base64 >base85 b:>base85 >hex b:>hex >mpack b:>mpack @ b:@ ICONVLIBS b:ICONVLIBS +Builtin append b:append base16> b:base16> base32> b:base32> base64> b:base64> base85> b:base85> bit! b:bit! +Builtin bit@ b:bit@ clear b:clear compress b:compress conv b:conv each b:each each! b:each! each-slice b:each-slice +Builtin expand b:expand fill b:fill getb b:getb hex> b:hex> len b:len mem> b:mem> move b:move mpack-compat b:mpack-compat Builtin mpack-date b:mpack-date mpack-ignore b:mpack-ignore mpack> b:mpack> n! b:n! n+ b:n+ n@ b:n@ Builtin new b:new op b:op op! b:op! pad b:pad rev b:rev search b:search shmem b:shmem slice b:slice Builtin splice b:splice ungetb b:ungetb unpad b:unpad writable b:writable xor b:xor +block bc:+block Builtin .blocks bc:.blocks add-block bc:add-block block-hash bc:block-hash block@ bc:block@ first-block bc:first-block Builtin hash bc:hash last-block bc:last-block load bc:load new bc:new save bc:save set-sql bc:set-sql Builtin validate bc:validate validate-block bc:validate-block add bloom:add filter bloom:filter in? bloom:in? -Builtin parse bson:parse accept bt:accept ch! bt:ch! ch@ bt:ch@ connect bt:connect disconnect bt:disconnect +Builtin parse bson:parse LIBS bt:LIBS accept bt:accept ch! bt:ch! ch@ bt:ch@ connect bt:connect disconnect bt:disconnect Builtin init bt:init leconnect bt:leconnect lescan bt:lescan listen bt:listen on? bt:on? read bt:read Builtin scan bt:scan service? bt:service? services? bt:services? write bt:write * c:* * c:* + c:+ + c:+ -Builtin = c:= = c:= >ri c:>ri >ri c:>ri abs c:abs abs c:abs arg c:arg arg c:arg conj c:conj conj c:conj -Builtin im c:im n> c:n> new c:new new c:new re c:re (.hebrew) cal:(.hebrew) (.islamic) cal:(.islamic) -Builtin .hebrew cal:.hebrew .islamic cal:.islamic >hebepoch cal:>hebepoch >jdn cal:>jdn Adar cal:Adar -Builtin Adar2 cal:Adar2 Adar2 cal:Adar2 Av cal:Av Elul cal:Elul Heshvan cal:Heshvan Iyar cal:Iyar Kislev cal:Kislev -Builtin Nissan cal:Nissan Shevat cal:Shevat Sivan cal:Sivan Tammuz cal:Tammuz Tevet cal:Tevet Tishrei cal:Tishrei -Builtin days-in-hebrew-year cal:days-in-hebrew-year displaying-hebrew cal:displaying-hebrew fixed>hebrew cal:fixed>hebrew -Builtin fixed>islamic cal:fixed>islamic gershayim cal:gershayim hanukkah cal:hanukkah hebrew-epoch cal:hebrew-epoch -Builtin hebrew>fixed cal:hebrew>fixed hebrewtoday cal:hebrewtoday hmonth-name cal:hmonth-name islamic.epoch cal:islamic.epoch -Builtin islamic>fixed cal:islamic>fixed islamictoday cal:islamictoday jdn> cal:jdn> last-day-of-hebrew-month cal:last-day-of-hebrew-month +Builtin = c:= = c:= >polar c:>polar >polar c:>polar >ri c:>ri >ri c:>ri ^ c:^ ^ c:^ abs c:abs abs c:abs +Builtin arg c:arg arg c:arg conj c:conj conj c:conj im c:im im c:im log c:log log c:log n> c:n> n> c:n> +Builtin new c:new new c:new polar> c:polar> polar> c:polar> re c:re re c:re (.hebrew) cal:(.hebrew) +Builtin (.islamic) cal:(.islamic) .hebrew cal:.hebrew .islamic cal:.islamic >hebepoch cal:>hebepoch +Builtin >jdn cal:>jdn Adar cal:Adar Adar2 cal:Adar2 Av cal:Av Elul cal:Elul Heshvan cal:Heshvan Iyar cal:Iyar +Builtin Kislev cal:Kislev Nissan cal:Nissan Shevat cal:Shevat Sivan cal:Sivan Tammuz cal:Tammuz Tevet cal:Tevet +Builtin Tishrei cal:Tishrei days-in-hebrew-year cal:days-in-hebrew-year displaying-hebrew cal:displaying-hebrew +Builtin fixed>hebrew cal:fixed>hebrew fixed>islamic cal:fixed>islamic gershayim cal:gershayim hanukkah cal:hanukkah +Builtin hebrew-epoch cal:hebrew-epoch hebrew-leap-year? cal:hebrew-leap-year? hebrew>fixed cal:hebrew>fixed +Builtin hebrewtoday cal:hebrewtoday hmonth-name cal:hmonth-name islamic.epoch cal:islamic.epoch islamic>fixed cal:islamic>fixed +Builtin islamictoday cal:islamictoday jdn> cal:jdn> last-day-of-hebrew-month cal:last-day-of-hebrew-month Builtin number>hebrew cal:number>hebrew omer cal:omer pesach cal:pesach purim cal:purim rosh-chodesh? cal:rosh-chodesh? Builtin rosh-hashanah cal:rosh-hashanah shavuot cal:shavuot taanit-esther cal:taanit-esther tisha-beav cal:tisha-beav -Builtin yom-haatsmaut cal:yom-haatsmaut yom-kippur cal:yom-kippur >redir con:>redir accept con:accept -Builtin accept-nl con:accept-nl accept-pwd con:accept-pwd alert con:alert ansi? con:ansi? black con:black -Builtin blue con:blue clreol con:clreol cls con:cls ctrld-empty con:ctrld-empty cyan con:cyan down con:down -Builtin file>history con:file>history free con:free getxy con:getxy gotoxy con:gotoxy green con:green -Builtin history-handler con:history-handler history>file con:history>file key con:key key? con:key? -Builtin left con:left load-history con:load-history magenta con:magenta max-history con:max-history -Builtin onBlack con:onBlack onBlue con:onBlue onCyan con:onCyan onGreen con:onGreen onMagenta con:onMagenta -Builtin onRed con:onRed onWhite con:onWhite onYellow con:onYellow print con:print red con:red redir> con:redir> -Builtin redir? con:redir? right con:right save-history con:save-history size? con:size? up con:up white con:white -Builtin yellow con:yellow >aes128gcm cr:>aes128gcm >aes256gcm cr:>aes256gcm >cp cr:>cp >cpe cr:>cpe -Builtin >decrypt cr:>decrypt >edbox cr:>edbox >encrypt cr:>encrypt >nbuf cr:>nbuf >rsabox cr:>rsabox -Builtin >uuid cr:>uuid aad? cr:aad? aes128box-sig cr:aes128box-sig aes128gcm> cr:aes128gcm> aes256box-sig cr:aes256box-sig -Builtin aes256gcm> cr:aes256gcm> aesgcm cr:aesgcm blakehash cr:blakehash chacha20box-sig cr:chacha20box-sig -Builtin chachapoly cr:chachapoly cipher! cr:cipher! cipher@ cr:cipher@ ciphers cr:ciphers cp> cr:cp> -Builtin cpe> cr:cpe> decrypt cr:decrypt decrypt+ cr:decrypt+ decrypt> cr:decrypt> ebox-sig cr:ebox-sig -Builtin ecc-curves cr:ecc-curves ecc-genkey cr:ecc-genkey ecc-secret cr:ecc-secret ecc-sign cr:ecc-sign -Builtin ecc-verify cr:ecc-verify ed25519 cr:ed25519 ed25519-secret cr:ed25519-secret ed25519-sign cr:ed25519-sign -Builtin ed25519-verify cr:ed25519-verify edbox-sig cr:edbox-sig edbox> cr:edbox> encrypt cr:encrypt -Builtin encrypt+ cr:encrypt+ encrypt> cr:encrypt> ensurekey cr:ensurekey genkey cr:genkey hash cr:hash -Builtin hash! cr:hash! hash+ cr:hash+ hash>b cr:hash>b hash>s cr:hash>s hash@ cr:hash@ hashes cr:hashes -Builtin hmac cr:hmac hotp cr:hotp iv? cr:iv? pem-read cr:pem-read pem-write cr:pem-write pwd-valid? cr:pwd-valid? -Builtin pwd/ cr:pwd/ pwd>hash cr:pwd>hash rand cr:rand randbuf cr:randbuf randkey cr:randkey restore cr:restore -Builtin root-certs cr:root-certs rsa_decrypt cr:rsa_decrypt rsa_encrypt cr:rsa_encrypt rsa_sign cr:rsa_sign -Builtin rsa_verify cr:rsa_verify rsabox-sig cr:rsabox-sig rsabox> cr:rsabox> rsagenkey cr:rsagenkey +Builtin yom-haatsmaut cal:yom-haatsmaut yom-kippur cal:yom-kippur >hsva clr:>hsva complement clr:complement +Builtin dist clr:dist gradient clr:gradient hsva> clr:hsva> invert clr:invert nearest-name clr:nearest-name +Builtin parse clr:parse >redir con:>redir accept con:accept accept-nl con:accept-nl accept-pwd con:accept-pwd +Builtin alert con:alert ansi? con:ansi? black con:black blue con:blue clreol con:clreol cls con:cls +Builtin ctrld-empty con:ctrld-empty cyan con:cyan down con:down file>history con:file>history free con:free +Builtin getxy con:getxy gotoxy con:gotoxy green con:green history-handler con:history-handler history>file con:history>file +Builtin init con:init key con:key key? con:key? left con:left load-history con:load-history magenta con:magenta +Builtin max-history con:max-history onBlack con:onBlack onBlue con:onBlue onCyan con:onCyan onGreen con:onGreen +Builtin onMagenta con:onMagenta onRed con:onRed onWhite con:onWhite onYellow con:onYellow print con:print +Builtin red con:red redir> con:redir> redir? con:redir? right con:right save-history con:save-history +Builtin size? con:size? up con:up white con:white yellow con:yellow >aes128gcm cr:>aes128gcm >aes256gcm cr:>aes256gcm +Builtin >cp cr:>cp >cpe cr:>cpe >decrypt cr:>decrypt >edbox cr:>edbox >encrypt cr:>encrypt >nbuf cr:>nbuf +Builtin >rsabox cr:>rsabox >uuid cr:>uuid aad? cr:aad? aes128box-sig cr:aes128box-sig aes128gcm> cr:aes128gcm> +Builtin aes256box-sig cr:aes256box-sig aes256gcm> cr:aes256gcm> aesgcm cr:aesgcm blakehash cr:blakehash +Builtin chacha20box-sig cr:chacha20box-sig chachapoly cr:chachapoly cipher! cr:cipher! cipher@ cr:cipher@ +Builtin ciphers cr:ciphers cp> cr:cp> cpe> cr:cpe> decrypt cr:decrypt decrypt+ cr:decrypt+ decrypt> cr:decrypt> +Builtin ebox-sig cr:ebox-sig ecc-curves cr:ecc-curves ecc-genkey cr:ecc-genkey ecc-secret cr:ecc-secret +Builtin ecc-sign cr:ecc-sign ecc-verify cr:ecc-verify ed25519 cr:ed25519 ed25519-secret cr:ed25519-secret +Builtin ed25519-sign cr:ed25519-sign ed25519-verify cr:ed25519-verify edbox-sig cr:edbox-sig edbox> cr:edbox> +Builtin encrypt cr:encrypt encrypt+ cr:encrypt+ encrypt> cr:encrypt> ensurekey cr:ensurekey genkey cr:genkey +Builtin hash cr:hash hash! cr:hash! hash+ cr:hash+ hash>b cr:hash>b hash>s cr:hash>s hash@ cr:hash@ +Builtin hashes cr:hashes hmac cr:hmac hotp cr:hotp iv? cr:iv? pem-read cr:pem-read pem-write cr:pem-write +Builtin pwd-valid? cr:pwd-valid? pwd/ cr:pwd/ pwd>hash cr:pwd>hash rand cr:rand randbuf cr:randbuf +Builtin randkey cr:randkey restore cr:restore root-certs cr:root-certs rsa_decrypt cr:rsa_decrypt rsa_encrypt cr:rsa_encrypt +Builtin rsa_sign cr:rsa_sign rsa_verify cr:rsa_verify rsabox-sig cr:rsabox-sig rsabox> cr:rsabox> rsagenkey cr:rsagenkey Builtin save cr:save sbox-sig cr:sbox-sig sha1-hmac cr:sha1-hmac shard cr:shard tag? cr:tag? totp cr:totp Builtin totp-epoch cr:totp-epoch totp-time-step cr:totp-time-step unshard cr:unshard uuid cr:uuid uuid> cr:uuid> -Builtin validate-pgp-sig cr:validate-pgp-sig validate-pwd cr:validate-pwd + d:+ +day d:+day +hour d:+hour -Builtin +min d:+min +msec d:+msec - d:- .time d:.time / d:/ = d:= >fixed d:>fixed >hmds d:>hmds >hmds: d:>hmds: -Builtin >msec d:>msec >unix d:>unix >ymd d:>ymd ?= d:?= Fri d:Fri Mon d:Mon Sat d:Sat Sun d:Sun Thu d:Thu -Builtin Tue d:Tue Wed d:Wed adjust-dst d:adjust-dst alarm d:alarm approx! d:approx! approx? d:approx? -Builtin approximates! d:approximates! between d:between cmp d:cmp d. d:d. default-now d:default-now +Builtin validate-pgp-sig cr:validate-pgp-sig validate-pwd cr:validate-pwd (.time) d:(.time) + d:+ +day d:+day +Builtin +hour d:+hour +min d:+min +msec d:+msec - d:- .time d:.time / d:/ = d:= >fixed d:>fixed >hmds d:>hmds +Builtin >hmds: d:>hmds: >msec d:>msec >unix d:>unix >ymd d:>ymd ?= d:?= Fri d:Fri Mon d:Mon Sat d:Sat +Builtin Sun d:Sun Thu d:Thu Tue d:Tue Wed d:Wed adjust-dst d:adjust-dst alarm d:alarm approx! d:approx! +Builtin approx? d:approx? approximates! d:approximates! between d:between cmp d:cmp d. d:d. default-now d:default-now Builtin doy d:doy dst-ofs d:dst-ofs dst? d:dst? dstinfo d:dstinfo dstquery d:dstquery dstzones? d:dstzones? Builtin elapsed-timer d:elapsed-timer elapsed-timer-hmds d:elapsed-timer-hmds elapsed-timer-msec d:elapsed-timer-msec Builtin elapsed-timer-seconds d:elapsed-timer-seconds first-dow d:first-dow fixed> d:fixed> fixed>dow d:fixed>dow Builtin format d:format join d:join last-dow d:last-dow last-month d:last-month last-week d:last-week -Builtin last-year d:last-year msec d:msec msec> d:msec> new d:new next-dow d:next-dow next-month d:next-month -Builtin next-week d:next-week next-year d:next-year parse d:parse parse-approx d:parse-approx parse-range d:parse-range -Builtin prev-dow d:prev-dow rfc5322 d:rfc5322 start-timer d:start-timer ticks d:ticks ticks/sec d:ticks/sec -Builtin timer d:timer timer-ctrl d:timer-ctrl tzadjust d:tzadjust unix> d:unix> unknown d:unknown unknown? d:unknown? -Builtin updatetz d:updatetz year@ d:year@ ymd d:ymd ymd> d:ymd> add-func db:add-func aes! db:aes! again? db:again? +Builtin last-year d:last-year leap? d:leap? mdays d:mdays msec d:msec msec> d:msec> new d:new next-dow d:next-dow +Builtin next-month d:next-month next-week d:next-week next-year d:next-year parse d:parse parse-approx d:parse-approx +Builtin parse-range d:parse-range prev-dow d:prev-dow rfc5322 d:rfc5322 start-timer d:start-timer ticks d:ticks +Builtin ticks/sec d:ticks/sec timer d:timer timer-ctrl d:timer-ctrl tzadjust d:tzadjust unix> d:unix> +Builtin unknown d:unknown unknown? d:unknown? updatetz d:updatetz year@ d:year@ ymd d:ymd ymd> d:ymd> +Builtin MYSQLLIB db:MYSQLLIB ODBCLIB db:ODBCLIB add-func db:add-func aes! db:aes! again? db:again? Builtin begin db:begin bind db:bind bind-exec db:bind-exec bind-exec{} db:bind-exec{} close db:close Builtin col db:col col{} db:col{} commit db:commit db db:db dbpush db:dbpush disuse db:disuse each db:each Builtin err-handler db:err-handler exec db:exec exec-cb db:exec-cb exec-name db:exec-name exec{} db:exec{} Builtin get db:get get-sub db:get-sub key db:key kind? db:kind? last-rowid db:last-rowid mysql? db:mysql? Builtin odbc? db:odbc? open db:open open? db:open? prep-name db:prep-name prepare db:prepare query db:query Builtin query-all db:query-all rekey db:rekey rollback db:rollback set db:set set-sub db:set-sub sql@ db:sql@ -Builtin sql[] db:sql[] sql[np] db:sql[np] sql{np} db:sql{np} sql{} db:sql{} use db:use zip db:zip bp dbg:bp -Builtin bt dbg:bt except-task@ dbg:except-task@ go dbg:go line-info dbg:line-info prompt dbg:prompt -Builtin stop dbg:stop trace dbg:trace trace-enter dbg:trace-enter trace-leave dbg:trace-leave / f:/ -Builtin >posix f:>posix abspath f:abspath absrel f:absrel append f:append associate f:associate atime f:atime -Builtin autodel f:autodel canwrite? f:canwrite? chmod f:chmod close f:close copy f:copy copydir f:copydir -Builtin create f:create ctime f:ctime dir? f:dir? dname f:dname eachbuf f:eachbuf eachline f:eachline -Builtin enssep f:enssep eof? f:eof? exec f:exec exists? f:exists? flush f:flush fname f:fname getb f:getb -Builtin getc f:getc getline f:getline getmod f:getmod glob f:glob glob-links f:glob-links glob-nocase f:glob-nocase +Builtin sql[] db:sql[] sql[np] db:sql[np] sql{np} db:sql{np} sql{} db:sql{} use db:use zip db:zip .state dbg:.state +Builtin bp dbg:bp bt dbg:bt except-task@ dbg:except-task@ go dbg:go prompt dbg:prompt see dbg:see stop dbg:stop +Builtin trace dbg:trace trace-enter dbg:trace-enter trace-leave dbg:trace-leave pso ds:pso / f:/ >posix f:>posix +Builtin abspath f:abspath absrel f:absrel append f:append associate f:associate atime f:atime autodel f:autodel +Builtin canwrite? f:canwrite? chmod f:chmod close f:close copy f:copy copydir f:copydir create f:create +Builtin ctime f:ctime dir? f:dir? dname f:dname eachbuf f:eachbuf eachline f:eachline enssep f:enssep +Builtin eof? f:eof? exec f:exec exists? f:exists? flush f:flush fname f:fname getb f:getb getc f:getc +Builtin getline f:getline getmod f:getmod glob f:glob glob-links f:glob-links glob-nocase f:glob-nocase Builtin gunz f:gunz homedir f:homedir homedir! f:homedir! include f:include ioctl f:ioctl join f:join Builtin launch f:launch link f:link link> f:link> link? f:link? lock f:lock mkdir f:mkdir mmap f:mmap Builtin mmap-range f:mmap-range mmap-range? f:mmap-range? mtime f:mtime mv f:mv name@ f:name@ open f:open @@ -209,9 +214,9 @@ Builtin ungetc f:ungetc unzip f:unzip unzip-entry f:unzip-entry watch f:watch w Builtin zip+ f:zip+ zip@ f:zip@ zipentry f:zipentry zipnew f:zipnew zipopen f:zipopen zipsave f:zipsave Builtin atlas! font:atlas! atlas@ font:atlas@ default-size font:default-size default-size@ font:default-size@ Builtin info font:info ls font:ls measure font:measure new font:new oversample font:oversample pixels font:pixels -Builtin pixels? font:pixels? system font:system system font:system distance geo:distance km/deg-lat geo:km/deg-lat -Builtin km/deg-lon geo:km/deg-lon nearest geo:nearest +edge gr:+edge +edge+w gr:+edge+w +node gr:+node -Builtin connect gr:connect edges gr:edges edges! gr:edges! m! gr:m! m@ gr:m@ neighbors gr:neighbors +Builtin pixels? font:pixels? system font:system system font:system media? g:media? distance geo:distance +Builtin km/deg-lat geo:km/deg-lat km/deg-lon geo:km/deg-lon nearest geo:nearest +edge gr:+edge +edge+w gr:+edge+w +Builtin +node gr:+node connect gr:connect edges gr:edges edges! gr:edges! m! gr:m! m@ gr:m@ neighbors gr:neighbors Builtin new gr:new node-edges gr:node-edges nodes gr:nodes traverse gr:traverse weight! gr:weight! Builtin + h:+ clear h:clear cmp! h:cmp! len h:len max! h:max! new h:new peek h:peek pop h:pop push h:push Builtin unique h:unique parse html:parse arm? hw:arm? camera hw:camera camera-img hw:camera-img camera-limits hw:camera-limits @@ -219,163 +224,171 @@ Builtin camera? hw:camera? cpu? hw:cpu? device? hw:device? displays? hw:display Builtin finger-match hw:finger-match finger-support hw:finger-support gpio hw:gpio gpio! hw:gpio! gpio-mmap hw:gpio-mmap Builtin gpio@ hw:gpio@ i2c hw:i2c i2c! hw:i2c! i2c!reg hw:i2c!reg i2c@ hw:i2c@ i2c@reg hw:i2c@reg isround? hw:isround? Builtin iswatch? hw:iswatch? mac? hw:mac? mem? hw:mem? model? hw:model? poll hw:poll sensor hw:sensor -Builtin start hw:start stop hw:stop uid? hw:uid? fetch-full imap:fetch-full fetch-uid-mail imap:fetch-uid-mail +Builtin start hw:start stop hw:stop touch? hw:touch? uid? hw:uid? fetch-full imap:fetch-full fetch-uid-mail imap:fetch-uid-mail Builtin login imap:login logout imap:logout new imap:new search imap:search select-inbox imap:select-inbox Builtin >file img:>file >fmt img:>fmt copy img:copy crop img:crop data img:data desat img:desat draw img:draw Builtin draw-sub img:draw-sub fill img:fill fillrect img:fillrect filter img:filter flip img:flip from-svg img:from-svg Builtin line img:line new img:new pikchr img:pikchr pix! img:pix! pix@ img:pix@ qr-gen img:qr-gen qr-parse img:qr-parse Builtin rect img:rect rotate img:rotate scale img:scale scroll img:scroll size img:size countries iso:countries -Builtin languages iso:languages utils/help library:utils/help find loc:find sort loc:sort ! m:! !? m:!? -Builtin + m:+ +? m:+? - m:- <> m:<> = m:= >arr m:>arr @ m:@ @? m:@? _! m:_! _@ m:_@ alias m:alias arr> m:arr> -Builtin bitmap m:bitmap clear m:clear data m:data each m:each exists? m:exists? filter m:filter ic m:ic -Builtin iter m:iter iter-all m:iter-all keys m:keys len m:len map m:map merge m:merge new m:new op! m:op! -Builtin open m:open slice m:slice vals m:vals xchg m:xchg zip m:zip ! mat:! * mat:* + mat:+ = mat:= -Builtin @ mat:@ affine mat:affine col mat:col data mat:data det mat:det dim? mat:dim? get-n mat:get-n -Builtin ident mat:ident inv mat:inv m. mat:m. minor mat:minor n* mat:n* new mat:new new-minor mat:new-minor -Builtin rotate mat:rotate row mat:row same-size? mat:same-size? scale mat:scale shear mat:shear trans mat:trans -Builtin translate mat:translate xform mat:xform 2console md:2console 2html md:2html 2nk md:2nk color meta:color -Builtin console meta:console gui meta:gui meta meta:meta ! n:! * n:* */ n:*/ + n:+ +! n:+! - n:- / n:/ -Builtin /mod n:/mod 1+ n:1+ 1- n:1- < n:< = n:= > n:> >bool n:>bool BIGE n:BIGE BIGPI n:BIGPI E n:E -Builtin PI n:PI ^ n:^ _mod n:_mod abs n:abs acos n:acos acos n:acos andor n:andor asin n:asin asin n:asin -Builtin atan n:atan atan n:atan atan2 n:atan2 band n:band between n:between bfloat n:bfloat bic n:bic +Builtin languages iso:languages utils/help library:utils/help bearing loc:bearing find loc:find sort loc:sort +Builtin ! m:! !? m:!? + m:+ +? m:+? - m:- <> m:<> = m:= >arr m:>arr @ m:@ @? m:@? _! m:_! _@ m:_@ _@? m:_@? +Builtin alias m:alias arr> m:arr> bitmap m:bitmap clear m:clear data m:data each m:each exists? m:exists? +Builtin filter m:filter ic m:ic iter m:iter iter-all m:iter-all keys m:keys len m:len map m:map merge m:merge +Builtin new m:new op! m:op! open m:open slice m:slice vals m:vals xchg m:xchg zip m:zip ! mat:! * mat:* +Builtin + mat:+ = mat:= @ mat:@ affine mat:affine col mat:col data mat:data det mat:det dim? mat:dim? +Builtin get-n mat:get-n ident mat:ident inv mat:inv m. mat:m. minor mat:minor n* mat:n* new mat:new +Builtin new-minor mat:new-minor rotate mat:rotate row mat:row same-size? mat:same-size? scale mat:scale +Builtin shear mat:shear trans mat:trans translate mat:translate xform mat:xform 2console md:2console +Builtin 2html md:2html 2nk md:2nk color meta:color console meta:console gui meta:gui meta meta:meta +Builtin ! n:! * n:* */ n:*/ + n:+ +! n:+! - n:- / n:/ /mod n:/mod 1+ n:1+ 1- n:1- < n:< = n:= > n:> +Builtin >bool n:>bool BIGE n:BIGE BIGPI n:BIGPI E n:E PI n:PI ^ n:^ _mod n:_mod abs n:abs acos n:acos +Builtin acosd n:acosd acosh n:acosh andor n:andor asin n:asin asind n:asind asinh n:asinh atan n:atan +Builtin atan2 n:atan2 atand n:atand atanh n:atanh band n:band between n:between bfloat n:bfloat bic n:bic Builtin bint n:bint binv n:binv bnot n:bnot bor n:bor bxor n:bxor cast n:cast ceil n:ceil clamp n:clamp -Builtin cmp n:cmp comb n:comb cos n:cos cosd n:cosd emod n:emod exp n:exp expm1 n:expm1 expmod n:expmod -Builtin float n:float floor n:floor fmod n:fmod frac n:frac gcd n:gcd int n:int invmod n:invmod kind? n:kind? -Builtin lcm n:lcm lerp n:lerp ln n:ln ln1p n:ln1p lnerp n:lnerp max n:max median n:median min n:min -Builtin mod n:mod neg n:neg odd? n:odd? perm n:perm prime? n:prime? quantize n:quantize quantize! n:quantize! -Builtin r+ n:r+ range n:range rot32l n:rot32l rot32r n:rot32r round n:round round2 n:round2 rounding n:rounding -Builtin running-variance n:running-variance running-variance-finalize n:running-variance-finalize sgn n:sgn -Builtin shl n:shl shr n:shr sin n:sin sind n:sind sqr n:sqr sqrt n:sqrt tan n:tan tand n:tand trunc n:trunc -Builtin ~= n:~= ! net:! !? net:!? - net:- >base64url net:>base64url >url net:>url @ net:@ @? net:@? -Builtin CGI net:CGI DGRAM net:DGRAM INET4 net:INET4 INET6 net:INET6 PROTO_TCP net:PROTO_TCP PROTO_UDP net:PROTO_UDP -Builtin REMOTE_IP net:REMOTE_IP STREAM net:STREAM accept net:accept active? net:active? addrinfo>o net:addrinfo>o -Builtin again? net:again? alloc-and-read net:alloc-and-read alloc-buf net:alloc-buf base64url> net:base64url> -Builtin bind net:bind cgi-get net:cgi-get cgi-http-header net:cgi-http-header cgi-init net:cgi-init -Builtin cgi-init-stunnel net:cgi-init-stunnel cgi-out net:cgi-out close net:close closed? net:closed? -Builtin connect net:connect curnet net:curnet debug? net:debug? delete net:delete get net:get getaddrinfo net:getaddrinfo -Builtin getpeername net:getpeername head net:head ifaces? net:ifaces? ipv6? net:ipv6? listen net:listen -Builtin map>url net:map>url mime-type net:mime-type net-socket net:net-socket opts net:opts port-is-ssl? net:port-is-ssl? +Builtin cmp n:cmp comb n:comb cos n:cos cosd n:cosd cosh n:cosh emod n:emod erf n:erf erfc n:erfc exp n:exp +Builtin expm1 n:expm1 expmod n:expmod float n:float floor n:floor fmod n:fmod frac n:frac gcd n:gcd +Builtin int n:int invmod n:invmod kind? n:kind? lcm n:lcm lerp n:lerp ln n:ln ln1p n:ln1p lnerp n:lnerp +Builtin logistic n:logistic max n:max median n:median min n:min mod n:mod neg n:neg odd? n:odd? perm n:perm +Builtin prime? n:prime? quantize n:quantize quantize! n:quantize! r+ n:r+ range n:range rot32l n:rot32l +Builtin rot32r n:rot32r round n:round round2 n:round2 rounding n:rounding running-variance n:running-variance +Builtin running-variance-finalize n:running-variance-finalize sgn n:sgn shl n:shl shr n:shr sin n:sin +Builtin sincos n:sincos sind n:sind sinh n:sinh sqr n:sqr sqrt n:sqrt tan n:tan tand n:tand tanh n:tanh +Builtin trunc n:trunc ~= n:~= ! net:! !? net:!? - net:- >base64url net:>base64url >url net:>url @ net:@ +Builtin @? net:@? CGI net:CGI DGRAM net:DGRAM INET4 net:INET4 INET6 net:INET6 PROTO_TCP net:PROTO_TCP +Builtin PROTO_UDP net:PROTO_UDP REMOTE_IP net:REMOTE_IP REMOTE_IP net:REMOTE_IP STREAM net:STREAM accept net:accept +Builtin active? net:active? addrinfo>o net:addrinfo>o again? net:again? alloc-and-read net:alloc-and-read +Builtin alloc-buf net:alloc-buf avail? net:avail? base64url> net:base64url> bind net:bind cgi-get net:cgi-get +Builtin cgi-http-header net:cgi-http-header cgi-init net:cgi-init cgi-init-stunnel net:cgi-init-stunnel +Builtin cgi-out net:cgi-out close net:close closed? net:closed? connect net:connect curnet net:curnet +Builtin debug? net:debug? delete net:delete dns net:dns get net:get getaddrinfo net:getaddrinfo getpeername net:getpeername +Builtin head net:head ifaces? net:ifaces? ipv6? net:ipv6? launch net:launch listen net:listen map>url net:map>url +Builtin mime-type net:mime-type net-socket net:net-socket opts net:opts port-is-ssl? net:port-is-ssl? Builtin post net:post proxy! net:proxy! put net:put read net:read read-all net:read-all read-buf net:read-buf Builtin recvfrom net:recvfrom s>url net:s>url sendto net:sendto server net:server setsockopt net:setsockopt Builtin socket net:socket tcp-connect net:tcp-connect tlserr net:tlserr tlshello net:tlshello udp-connect net:udp-connect -Builtin url> net:url> user-agent net:user-agent vpncheck net:vpncheck wait net:wait webserver net:webserver -Builtin write net:write (begin) nk:(begin) (chart-begin) nk:(chart-begin) (chart-begin-colored) nk:(chart-begin-colored) -Builtin (chart-end) nk:(chart-end) (end) nk:(end) (group-begin) nk:(group-begin) (group-end) nk:(group-end) -Builtin (property) nk:(property) >img nk:>img addfont nk:addfont anti-alias nk:anti-alias any-clicked? nk:any-clicked? -Builtin bounds nk:bounds bounds! nk:bounds! button nk:button button-color nk:button-color button-label nk:button-label -Builtin button-set-behavior nk:button-set-behavior button-symbol nk:button-symbol button-symbol-label nk:button-symbol-label -Builtin center-rect nk:center-rect chart-add-slot nk:chart-add-slot chart-add-slot-colored nk:chart-add-slot-colored -Builtin chart-push nk:chart-push chart-push-slot nk:chart-push-slot checkbox nk:checkbox circle nk:circle -Builtin clicked? nk:clicked? close-this! nk:close-this! close-this? nk:close-this? close? nk:close? -Builtin color-picker nk:color-picker combo nk:combo combo-begin-color nk:combo-begin-color combo-begin-label nk:combo-begin-label -Builtin combo-cb nk:combo-cb combo-end nk:combo-end contextual-begin nk:contextual-begin contextual-close nk:contextual-close +Builtin url> net:url> user-agent net:user-agent valid-email? net:valid-email? vpncheck net:vpncheck +Builtin wait net:wait webserver net:webserver write net:write (begin) nk:(begin) (chart-begin) nk:(chart-begin) +Builtin (chart-begin-colored) nk:(chart-begin-colored) (chart-end) nk:(chart-end) (end) nk:(end) (group-begin) nk:(group-begin) +Builtin (group-end) nk:(group-end) (property) nk:(property) >img nk:>img GLLIBS nk:GLLIBS GLXLIBS nk:GLXLIBS +Builtin addfont nk:addfont anti-alias nk:anti-alias any-clicked? nk:any-clicked? bounds nk:bounds bounds! nk:bounds! +Builtin button nk:button button-color nk:button-color button-label nk:button-label button-set-behavior nk:button-set-behavior +Builtin button-symbol nk:button-symbol button-symbol-label nk:button-symbol-label chart-add-slot nk:chart-add-slot +Builtin chart-add-slot-colored nk:chart-add-slot-colored chart-push nk:chart-push chart-push-slot nk:chart-push-slot +Builtin checkbox nk:checkbox circle nk:circle clicked? nk:clicked? close-this! nk:close-this! close-this? nk:close-this? +Builtin close? nk:close? color-chooser nk:color-chooser color-picker nk:color-picker combo nk:combo +Builtin combo-begin-color nk:combo-begin-color combo-begin-label nk:combo-begin-label combo-cb nk:combo-cb +Builtin combo-end nk:combo-end contextual-begin nk:contextual-begin contextual-close nk:contextual-close Builtin contextual-end nk:contextual-end contextual-item-image-text nk:contextual-item-image-text contextual-item-symbol-text nk:contextual-item-symbol-text Builtin contextual-item-text nk:contextual-item-text cp! nk:cp! cp@ nk:cp@ curpos nk:curpos cursor-load nk:cursor-load Builtin cursor-set nk:cursor-set cursor-show nk:cursor-show display-info nk:display-info display@ nk:display@ Builtin do nk:do down? nk:down? draw-image nk:draw-image draw-image-at nk:draw-image-at draw-image-centered nk:draw-image-centered Builtin draw-sub-image nk:draw-sub-image draw-text nk:draw-text draw-text-centered nk:draw-text-centered -Builtin draw-text-high nk:draw-text-high draw-text-wrap nk:draw-text-wrap drivers nk:drivers edit-focus nk:edit-focus -Builtin edit-string nk:edit-string event nk:event event-boost nk:event-boost event-msec nk:event-msec -Builtin event-wait nk:event-wait event? nk:event? fill-arc nk:fill-arc fill-circle nk:fill-circle fill-color nk:fill-color -Builtin fill-poly nk:fill-poly fill-rect nk:fill-rect fill-rect-color nk:fill-rect-color fill-triangle nk:fill-triangle -Builtin finger nk:finger flags! nk:flags! flags@ nk:flags@ flash nk:flash fullscreen nk:fullscreen -Builtin gesture nk:gesture get nk:get get-row-height nk:get-row-height getfont nk:getfont getmap nk:getmap -Builtin getmap! nk:getmap! gl? nk:gl? grid nk:grid grid-push nk:grid-push group-scroll-ofs nk:group-scroll-ofs -Builtin group-scroll-ofs! nk:group-scroll-ofs! hovered? nk:hovered? hrule nk:hrule image nk:image init nk:init -Builtin input-button nk:input-button input-key nk:input-key input-motion nk:input-motion input-scroll nk:input-scroll -Builtin input-string nk:input-string key-down? nk:key-down? key-pressed? nk:key-pressed? key-released? nk:key-released? -Builtin label nk:label label-colored nk:label-colored label-wrap nk:label-wrap label-wrap-colored nk:label-wrap-colored -Builtin layout-bounds nk:layout-bounds layout-grid-begin nk:layout-grid-begin layout-grid-end nk:layout-grid-end -Builtin layout-push-dynamic nk:layout-push-dynamic layout-push-static nk:layout-push-static layout-push-variable nk:layout-push-variable -Builtin layout-ratio-from-pixel nk:layout-ratio-from-pixel layout-reset-row-height nk:layout-reset-row-height -Builtin layout-row nk:layout-row layout-row-begin nk:layout-row-begin layout-row-dynamic nk:layout-row-dynamic -Builtin layout-row-end nk:layout-row-end layout-row-height nk:layout-row-height layout-row-push nk:layout-row-push -Builtin layout-row-static nk:layout-row-static layout-row-template-begin nk:layout-row-template-begin +Builtin draw-text-high nk:draw-text-high draw-text-wrap nk:draw-text-wrap driver nk:driver drivers nk:drivers +Builtin dropped nk:dropped dropping nk:dropping edit-focus nk:edit-focus edit-string nk:edit-string +Builtin event nk:event event-boost nk:event-boost event-msec nk:event-msec event-wait nk:event-wait +Builtin event? nk:event? fill-arc nk:fill-arc fill-circle nk:fill-circle fill-color nk:fill-color fill-poly nk:fill-poly +Builtin fill-rect nk:fill-rect fill-rect-color nk:fill-rect-color fill-triangle nk:fill-triangle finger nk:finger +Builtin flags! nk:flags! flags@ nk:flags@ flash nk:flash fullscreen nk:fullscreen gesture nk:gesture +Builtin get nk:get get-row-height nk:get-row-height getfont nk:getfont getmap nk:getmap getmap! nk:getmap! +Builtin gl? nk:gl? grid nk:grid grid-peek nk:grid-peek grid-push nk:grid-push group-scroll-ofs nk:group-scroll-ofs +Builtin group-scroll-ofs! nk:group-scroll-ofs! hints nk:hints hovered? nk:hovered? hrule nk:hrule image nk:image +Builtin init nk:init input-button nk:input-button input-key nk:input-key input-motion nk:input-motion +Builtin input-scroll nk:input-scroll input-string nk:input-string key-down? nk:key-down? key-pressed? nk:key-pressed? +Builtin key-released? nk:key-released? knob nk:knob label nk:label label-colored nk:label-colored label-wrap nk:label-wrap +Builtin label-wrap-colored nk:label-wrap-colored layout-bounds nk:layout-bounds layout-grid-begin nk:layout-grid-begin +Builtin layout-grid-end nk:layout-grid-end layout-push-dynamic nk:layout-push-dynamic layout-push-static nk:layout-push-static +Builtin layout-push-variable nk:layout-push-variable layout-ratio-from-pixel nk:layout-ratio-from-pixel +Builtin layout-reset-row-height nk:layout-reset-row-height layout-row nk:layout-row layout-row-begin nk:layout-row-begin +Builtin layout-row-dynamic nk:layout-row-dynamic layout-row-end nk:layout-row-end layout-row-height nk:layout-row-height +Builtin layout-row-push nk:layout-row-push layout-row-static nk:layout-row-static layout-row-template-begin nk:layout-row-template-begin Builtin layout-row-template-end nk:layout-row-template-end layout-space-begin nk:layout-space-begin Builtin layout-space-end nk:layout-space-end layout-space-push nk:layout-space-push layout-widget-bounds nk:layout-widget-bounds Builtin line-rel nk:line-rel line-to nk:line-to list-begin nk:list-begin list-end nk:list-end list-new nk:list-new -Builtin list-range nk:list-range m! nk:m! m@ nk:m@ make-style nk:make-style max-vertex-element nk:max-vertex-element +Builtin list-ofs nk:list-ofs list-range nk:list-range m! nk:m! m@ nk:m@ make-style nk:make-style max-vertex-element nk:max-vertex-element Builtin maximize nk:maximize measure nk:measure measure-font nk:measure-font menu-begin nk:menu-begin Builtin menu-close nk:menu-close menu-end nk:menu-end menu-item-image nk:menu-item-image menu-item-label nk:menu-item-label Builtin menu-item-symbol nk:menu-item-symbol menubar-begin nk:menubar-begin menubar-end nk:menubar-end Builtin minimize nk:minimize mouse-pos nk:mouse-pos move-back nk:move-back move-rel nk:move-rel move-to nk:move-to Builtin msg nk:msg msgdlg nk:msgdlg ontop nk:ontop option nk:option pen-color nk:pen-color pen-width nk:pen-width -Builtin plot nk:plot plot-fn nk:plot-fn pop-font nk:pop-font popup-begin nk:popup-begin popup-close nk:popup-close -Builtin popup-end nk:popup-end popup-scroll-ofs nk:popup-scroll-ofs popup-scroll-ofs! nk:popup-scroll-ofs! -Builtin progress nk:progress prop-int nk:prop-int pt-in? nk:pt-in? pt-open nk:pt-open pt>local nk:pt>local -Builtin pt>rect nk:pt>rect pt>screen nk:pt>screen pt>x nk:pt>x pts>rect nk:pts>rect push-font nk:push-font -Builtin raise nk:raise rect! nk:rect! rect-center nk:rect-center rect-intersect nk:rect-intersect rect-ofs nk:rect-ofs -Builtin rect-open nk:rect-open rect-pad nk:rect-pad rect-rel nk:rect-rel rect-shrink nk:rect-shrink -Builtin rect-to nk:rect-to rect-union nk:rect-union rect/high nk:rect/high rect/wide nk:rect/wide rect= nk:rect= -Builtin rect>local nk:rect>local rect>pos nk:rect>pos rect>pts nk:rect>pts rect>pts4 nk:rect>pts4 rect>screen nk:rect>screen -Builtin rect>size nk:rect>size rect>x nk:rect>x rect@ nk:rect@ released? nk:released? render nk:render -Builtin render-timed nk:render-timed restore nk:restore rotate nk:rotate rotate-rel nk:rotate-rel save nk:save -Builtin scale nk:scale scancode? nk:scancode? screen-saver nk:screen-saver screen-size nk:screen-size -Builtin screen-win-close nk:screen-win-close selectable nk:selectable set nk:set set-font nk:set-font -Builtin set-num-vertices nk:set-num-vertices set-radius nk:set-radius setpos nk:setpos setwin nk:setwin -Builtin show nk:show slider nk:slider slider-int nk:slider-int space nk:space spacing nk:spacing stroke-arc nk:stroke-arc -Builtin stroke-circle nk:stroke-circle stroke-curve nk:stroke-curve stroke-line nk:stroke-line stroke-polygon nk:stroke-polygon -Builtin stroke-polyline nk:stroke-polyline stroke-rect nk:stroke-rect stroke-tri nk:stroke-tri style-from-table nk:style-from-table -Builtin swipe nk:swipe swipe-dir-threshold nk:swipe-dir-threshold swipe-threshold nk:swipe-threshold -Builtin text nk:text text-align nk:text-align text-font nk:text-font text-pad nk:text-pad text? nk:text? -Builtin timer-delay nk:timer-delay timer? nk:timer? tooltip nk:tooltip translate nk:translate tree-pop nk:tree-pop -Builtin tree-state-push nk:tree-state-push use-style nk:use-style vsync nk:vsync widget nk:widget widget-bounds nk:widget-bounds +Builtin pix! nk:pix! plot nk:plot plot-fn nk:plot-fn polygon nk:polygon pop-font nk:pop-font popup-begin nk:popup-begin +Builtin popup-close nk:popup-close popup-end nk:popup-end popup-scroll-ofs nk:popup-scroll-ofs popup-scroll-ofs! nk:popup-scroll-ofs! +Builtin progress nk:progress prop-int nk:prop-int pt-in? nk:pt-in? pt>local nk:pt>local pt>screen nk:pt>screen +Builtin push-font nk:push-font raise nk:raise rect-rel nk:rect-rel rect-to nk:rect-to rect>local nk:rect>local +Builtin rect>screen nk:rect>screen released? nk:released? render nk:render render-timed nk:render-timed +Builtin rendering nk:rendering restore nk:restore rotate nk:rotate rotate-rel nk:rotate-rel rtl! nk:rtl! +Builtin rtl? nk:rtl? save nk:save scale nk:scale scancode? nk:scancode? screen-saver nk:screen-saver +Builtin screen-size nk:screen-size screen-win-close nk:screen-win-close selectable nk:selectable set nk:set +Builtin set-font nk:set-font set-num-vertices nk:set-num-vertices set-radius nk:set-radius setpos nk:setpos +Builtin setwin nk:setwin show nk:show slider nk:slider slider-int nk:slider-int space nk:space spacing nk:spacing +Builtin stroke-arc nk:stroke-arc stroke-circle nk:stroke-circle stroke-curve nk:stroke-curve stroke-line nk:stroke-line +Builtin stroke-polygon nk:stroke-polygon stroke-polyline nk:stroke-polyline stroke-rect nk:stroke-rect +Builtin stroke-tri nk:stroke-tri style-from-table nk:style-from-table swipe nk:swipe swipe-dir-threshold nk:swipe-dir-threshold +Builtin swipe-threshold nk:swipe-threshold text nk:text text-align nk:text-align text-font nk:text-font +Builtin text-pad nk:text-pad text? nk:text? timer-delay nk:timer-delay timer? nk:timer? toast nk:toast +Builtin tooltip nk:tooltip translate nk:translate tree-pop nk:tree-pop tree-state-push nk:tree-state-push +Builtin triangle nk:triangle use-style nk:use-style vsync nk:vsync widget nk:widget widget-bounds nk:widget-bounds Builtin widget-disable nk:widget-disable widget-fitting nk:widget-fitting widget-high nk:widget-high Builtin widget-hovered? nk:widget-hovered? widget-mouse-click-down? nk:widget-mouse-click-down? widget-mouse-clicked? nk:widget-mouse-clicked? -Builtin widget-pos nk:widget-pos widget-size nk:widget-size widget-size nk:widget-size widget-wide nk:widget-wide -Builtin win nk:win win-bounds nk:win-bounds win-bounds! nk:win-bounds! win-close nk:win-close win-closed? nk:win-closed? -Builtin win-collapse nk:win-collapse win-collapsed? nk:win-collapsed? win-content-bounds nk:win-content-bounds +Builtin widget-pos nk:widget-pos widget-size nk:widget-size widget-size-allot nk:widget-size-allot +Builtin widget-wide nk:widget-wide win nk:win win-bounds nk:win-bounds win-bounds! nk:win-bounds! win-close nk:win-close +Builtin win-closed? nk:win-closed? win-collapse nk:win-collapse win-collapsed? nk:win-collapsed? win-content-bounds nk:win-content-bounds Builtin win-focus nk:win-focus win-focused? nk:win-focused? win-hidden? nk:win-hidden? win-high nk:win-high -Builtin win-hovered? nk:win-hovered? win-pos nk:win-pos win-scroll-ofs nk:win-scroll-ofs win-scroll-ofs! nk:win-scroll-ofs! -Builtin win-show nk:win-show win-size nk:win-size win-wide nk:win-wide win? nk:win? x>pt nk:x>pt x>rect nk:x>rect -Builtin MAX ns:MAX ! o:! + o:+ +? o:+? ??? o:??? @ o:@ class o:class exec o:exec isa o:isa method o:method -Builtin mutate o:mutate new o:new super o:super chroot os:chroot devname os:devname docker? os:docker? -Builtin env os:env lang os:lang locales os:locales notify os:notify power-state os:power-state region os:region -Builtin waitpid os:waitpid bezier pdf:bezier bezierq pdf:bezierq circle pdf:circle color pdf:color -Builtin ellipse pdf:ellipse font pdf:font img pdf:img line pdf:line new pdf:new page pdf:page page-size pdf:page-size -Builtin rect pdf:rect save pdf:save size pdf:size text pdf:text text-rotate pdf:text-rotate text-size pdf:text-size -Builtin text-width pdf:text-width text-wrap pdf:text-wrap text-wrap-rotate pdf:text-wrap-rotate cast ptr:cast +Builtin win-hovered? nk:win-hovered? win-icon! nk:win-icon! win-pos nk:win-pos win-scroll-ofs nk:win-scroll-ofs +Builtin win-scroll-ofs! nk:win-scroll-ofs! win-show nk:win-show win-size nk:win-size win-title! nk:win-title! +Builtin win-wide nk:win-wide win? nk:win? MAX ns:MAX ! o:! + o:+ +? o:+? ??? o:??? @ o:@ class o:class +Builtin exec o:exec isa o:isa method o:method mutate o:mutate new o:new super o:super POSIX os:POSIX +Builtin chroot os:chroot devname os:devname docker? os:docker? env os:env lang os:lang locales os:locales +Builtin notify os:notify power-state os:power-state region os:region waitpid os:waitpid bezier pdf:bezier +Builtin bezierq pdf:bezierq circle pdf:circle color pdf:color ellipse pdf:ellipse font pdf:font img pdf:img +Builtin line pdf:line new pdf:new page pdf:page page-size pdf:page-size rect pdf:rect save pdf:save +Builtin size pdf:size text pdf:text text-rotate pdf:text-rotate text-size pdf:text-size text-width pdf:text-width +Builtin text-wrap pdf:text-wrap text-wrap-rotate pdf:text-wrap-rotate cast ptr:cast deref ptr:deref Builtin len ptr:len null? ptr:null? pack ptr:pack unpack ptr:unpack unpack_orig ptr:unpack_orig publish pubsub:publish Builtin qsize pubsub:qsize subscribe pubsub:subscribe + q:+ clear q:clear len q:len new q:new notify q:notify Builtin overwrite q:overwrite peek q:peek pick q:pick pop q:pop push q:push remove q:remove shift q:shift Builtin size q:size slide q:slide throwing q:throwing wait q:wait ++match r:++match +/ r:+/ +match r:+match -Builtin / r:/ @ r:@ len r:len match r:match new r:new rx r:rx str r:str * rat:* + rat:+ - rat:- / rat:/ -Builtin >n rat:>n >s rat:>s new rat:new proper rat:proper ! s:! * s:* + s:+ - s:- / s:/ /scripts s:/scripts -Builtin <+ s:<+ <> s:<> = s:= =ic s:=ic >base64 s:>base64 >ucs2 s:>ucs2 @ s:@ append s:append base64> s:base64> -Builtin clear s:clear cmp s:cmp cmpi s:cmpi compress s:compress count-match s:count-match days! s:days! -Builtin dist s:dist each s:each each! s:each! eachline s:eachline escape s:escape expand s:expand fill s:fill -Builtin fold s:fold globmatch s:globmatch hexupr s:hexupr insert s:insert intl s:intl intl! s:intl! -Builtin lang s:lang lc s:lc lc? s:lc? len s:len lsub s:lsub ltrim s:ltrim map s:map months! s:months! -Builtin n> s:n> new s:new norm s:norm reduce s:reduce repinsert s:repinsert replace s:replace replace! s:replace! -Builtin rev s:rev rsearch s:rsearch rsub s:rsub rtrim s:rtrim scan-match s:scan-match script? s:script? -Builtin search s:search size s:size slice s:slice soundex s:soundex strfmap s:strfmap strfmt s:strfmt -Builtin term s:term text-wrap s:text-wrap tr s:tr translate s:translate trim s:trim tsub s:tsub uc s:uc -Builtin uc? s:uc? ucs2> s:ucs2> utf8? s:utf8? zt s:zt close sio:close enum sio:enum open sio:open opts! sio:opts! -Builtin opts@ sio:opts@ read sio:read write sio:write @ slv:@ auto slv:auto build slv:build constraint slv:constraint -Builtin dump slv:dump edit slv:edit named-variable slv:named-variable new slv:new relation slv:relation -Builtin reset slv:reset suggest slv:suggest term slv:term update slv:update v[] slv:v[] variable slv:variable -Builtin v{} slv:v{} new smtp:new send smtp:send apply-filter snd:apply-filter devices? snd:devices? -Builtin end-record snd:end-record filter snd:filter freq snd:freq gain snd:gain gain? snd:gain? init snd:init -Builtin len snd:len loop snd:loop loop? snd:loop? mix snd:mix new snd:new pause snd:pause play snd:play -Builtin played snd:played rate snd:rate ready? snd:ready? record snd:record resume snd:resume seek snd:seek -Builtin stop snd:stop stopall snd:stopall volume snd:volume volume? snd:volume? + st:+ . st:. clear st:clear -Builtin len st:len ndrop st:ndrop new st:new op! st:op! peek st:peek pick st:pick pop st:pop push st:push -Builtin roll st:roll shift st:shift size st:size slide st:slide swap st:swap throwing st:throwing >buf struct:>buf -Builtin arr> struct:arr> buf struct:buf buf> struct:buf> byte struct:byte double struct:double field! struct:field! +Builtin / r:/ @ r:@ len r:len match r:match match[] r:match[] matchall[] r:matchall[] new r:new rx r:rx +Builtin str r:str * rat:* + rat:+ - rat:- / rat:/ >n rat:>n >s rat:>s new rat:new proper rat:proper +Builtin ! rect:! /high rect:/high /wide rect:/wide = rect:= >a rect:>a >pts rect:>pts >pts4 rect:>pts4 +Builtin @ rect:@ center rect:center center-pt rect:center-pt intersect rect:intersect new rect:new +Builtin new-pt rect:new-pt ofs rect:ofs open rect:open pad rect:pad pos rect:pos pt-open rect:pt-open +Builtin pt>a rect:pt>a pt>rect rect:pt>rect pts> rect:pts> restrict rect:restrict shrink rect:shrink +Builtin size rect:size union rect:union ! s:! * s:* + s:+ - s:- / s:/ /scripts s:/scripts /ws s:/ws +Builtin 2len s:2len <+ s:<+ <> s:<> = s:= =ic s:=ic >base64 s:>base64 >ucs2 s:>ucs2 @ s:@ _len s:_len +Builtin append s:append base64> s:base64> clear s:clear cmp s:cmp cmpi s:cmpi compress s:compress count-match s:count-match +Builtin days! s:days! dist s:dist each s:each each! s:each! eachline s:eachline escape s:escape expand s:expand +Builtin fill s:fill fold s:fold gen-uid s:gen-uid globmatch s:globmatch hexupr s:hexupr insert s:insert +Builtin intl s:intl intl! s:intl! lang s:lang lc s:lc lc? s:lc? len s:len lsub s:lsub ltrim s:ltrim +Builtin map s:map months! s:months! n> s:n> new s:new norm s:norm reduce s:reduce repinsert s:repinsert +Builtin replace s:replace replace! s:replace! rev s:rev rsearch s:rsearch rsub s:rsub rtl s:rtl rtrim s:rtrim +Builtin scan-match s:scan-match script? s:script? search s:search size s:size slice s:slice soundex s:soundex +Builtin strfmap s:strfmap strfmt s:strfmt term s:term text-wrap s:text-wrap tr s:tr translate s:translate +Builtin trim s:trim tsub s:tsub uc s:uc uc? s:uc? ucs2> s:ucs2> utf8? s:utf8? zt s:zt close sio:close +Builtin enum sio:enum open sio:open opts! sio:opts! opts@ sio:opts@ read sio:read write sio:write @ slv:@ +Builtin auto slv:auto build slv:build constraint slv:constraint dump slv:dump edit slv:edit named-variable slv:named-variable +Builtin new slv:new relation slv:relation reset slv:reset suggest slv:suggest term slv:term update slv:update +Builtin v[] slv:v[] variable slv:variable v{} slv:v{} new smtp:new send smtp:send apply-filter snd:apply-filter +Builtin devices? snd:devices? end-record snd:end-record filter snd:filter freq snd:freq gain snd:gain +Builtin gain? snd:gain? init snd:init len snd:len loop snd:loop loop? snd:loop? mix snd:mix new snd:new +Builtin pause snd:pause play snd:play played snd:played rate snd:rate ready? snd:ready? record snd:record +Builtin resume snd:resume seek snd:seek stop snd:stop stopall snd:stopall volume snd:volume volume? snd:volume? +Builtin + st:+ . st:. clear st:clear dot-depth st:dot-depth len st:len list st:list ndrop st:ndrop +Builtin new st:new op! st:op! peek st:peek pick st:pick pop st:pop push st:push roll st:roll shift st:shift +Builtin size st:size slide st:slide swap st:swap throwing st:throwing >buf struct:>buf arr> struct:arr> +Builtin buf struct:buf buf> struct:buf> byte struct:byte double struct:double field! struct:field! Builtin field@ struct:field@ float struct:float ignore struct:ignore int struct:int long struct:long -Builtin struct; struct:struct; word struct:word ! t:! @ t:@ by-name t:by-name cor t:cor cor-drop t:cor-drop -Builtin curtask t:curtask def-queue t:def-queue def-stack t:def-stack done? t:done? dtor t:dtor err! t:err! -Builtin err? t:err? errno? t:errno? extra t:extra getq t:getq handler t:handler handler@ t:handler@ -Builtin kill t:kill list t:list main t:main max-exceptions t:max-exceptions name! t:name! name@ t:name@ -Builtin notify t:notify parent t:parent pop t:pop priority t:priority push t:push push! t:push! q-notify t:q-notify -Builtin q-wait t:q-wait qlen t:qlen result t:result set-affinity t:set-affinity setq t:setq start t:start -Builtin task t:task task-n t:task-n task-stop t:task-stop ticks t:ticks wait t:wait yield t:yield yield! t:yield! -Builtin add tree:add binary tree:binary bk tree:bk btree tree:btree cmp! tree:cmp! data tree:data del tree:del -Builtin find tree:find iter tree:iter next tree:next nodes tree:nodes parent tree:parent parse tree:parse -Builtin prev tree:prev root tree:root search tree:search trie tree:trie ! w:! (is) w:(is) @ w:@ alias: w:alias: -Builtin cb w:cb deprecate w:deprecate dlcall w:dlcall dlopen w:dlopen dlsym w:dlsym exec w:exec exec? w:exec? -Builtin ffifail w:ffifail find w:find forget w:forget is w:is name w:name undo w:undo close ws:close -Builtin decode ws:decode encode ws:encode encode-nomask ws:encode-nomask gen-accept-header ws:gen-accept-header +Builtin struct; struct:struct; word struct:word ! t:! @ t:@ by-name t:by-name curtask t:curtask def-queue t:def-queue +Builtin def-stack t:def-stack done? t:done? dtor t:dtor err! t:err! err? t:err? errno? t:errno? extra t:extra +Builtin getq t:getq handler t:handler handler@ t:handler@ kill t:kill list t:list main t:main max-exceptions t:max-exceptions +Builtin name! t:name! name@ t:name@ notify t:notify parent t:parent pop t:pop priority t:priority push t:push +Builtin push! t:push! q-notify t:q-notify q-wait t:q-wait qlen t:qlen result t:result set-affinity t:set-affinity +Builtin setq t:setq task t:task task-n t:task-n task-stop t:task-stop ticks t:ticks wait t:wait add tree:add +Builtin binary tree:binary bk tree:bk btree tree:btree cmp! tree:cmp! data tree:data del tree:del find tree:find +Builtin iter tree:iter next tree:next nodes tree:nodes parent tree:parent parse tree:parse prev tree:prev +Builtin root tree:root search tree:search trie tree:trie ! w:! (is) w:(is) @ w:@ alias: w:alias: cb w:cb +Builtin deprecate w:deprecate dlcall w:dlcall dlopen w:dlopen dlsym w:dlsym exec w:exec exec? w:exec? +Builtin ffifail w:ffifail find w:find forget w:forget is w:is name w:name undo w:undo xt w:xt xt> w:xt> +Builtin close ws:close decode ws:decode encode ws:encode encode-nomask ws:encode-nomask gen-accept-header ws:gen-accept-header Builtin gen-accept-key ws:gen-accept-key opcodes ws:opcodes open ws:open >s xml:>s >txt xml:>txt md-init xml:md-init Builtin md-parse xml:md-parse parse xml:parse parse-html xml:parse-html parse-stream xml:parse-stream Builtin getmsg[] zmq:getmsg[] sendmsg[] zmq:sendmsg[] @@ -413,8 +426,9 @@ syn match eighthBuiltin /db:bind-exec\[]/ syn match eighthBuiltin /db:exec\[]/ syn match eighthBuiltin /db:col\[]/ -" TODO -syn region eighthComment start="\zs\\" end="$" contains=eighthTodo +syn region eighthComment start="\zs\\" end="$" contains=eighthTodo,@Spell +syn region eighthComment start="\zs--\s" end="$" contains=eighthTodo,@Spell +syn region eighthComment start="\zs(\*\_[:space:]" end="\_[:space:]\*)\ze" contains=eightTodo,@Spell " The default methods for highlighting. Can be overriden later. hi def link eighthTodo Todo @@ -452,6 +466,7 @@ hi def link jsonArray Special hi def link jsonNull Function hi def link jsonBool Boolean +delcommand Builtin let b:current_syntax = "8th" let &cpo = s:cpo_save unlet s:cpo_save From 39f52a62492086acef1e9dbd71e344447954deb5 Mon Sep 17 00:00:00 2001 From: Duke Date: Thu, 7 Nov 2024 22:05:32 +0100 Subject: [PATCH 044/106] runtime(structurizr): Update structurizr syntax closes: #16003 Signed-off-by: Duke Signed-off-by: Bastian Venthur Signed-off-by: Christian Brabandt --- runtime/syntax/structurizr.vim | 37 ++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/runtime/syntax/structurizr.vim b/runtime/syntax/structurizr.vim index 363ee70438..c10f1a4569 100644 --- a/runtime/syntax/structurizr.vim +++ b/runtime/syntax/structurizr.vim @@ -1,10 +1,9 @@ " Vim syntax file " Language: Structurizr DSL " Maintainer: Bastian Venthur -" Last Change: 2022-05-22 +" Last Change: 2024-11-06 " Remark: For a language reference, see -" https://github.com/structurizr/dsl - +" https://docs.structurizr.com/dsl/language if exists("b:current_syntax") finish @@ -20,7 +19,11 @@ syn region scomment start="/\*" end="\*/" " keywords syn keyword skeyword animation syn keyword skeyword autoLayout +syn keyword skeyword background +syn keyword skeyword border syn keyword skeyword branding +syn keyword skeyword color +syn keyword skeyword colour syn keyword skeyword component syn keyword skeyword configuration syn keyword skeyword container @@ -37,48 +40,74 @@ syn keyword skeyword element syn keyword skeyword enterprise syn keyword skeyword exclude syn keyword skeyword filtered +syn keyword skeyword font +syn keyword skeyword fontsize syn keyword skeyword group syn keyword skeyword healthcheck +syn keyword skeyword height +syn keyword skeyword icon +syn keyword skeyword image syn keyword skeyword include syn keyword skeyword infrastructurenode syn keyword skeyword instances +syn keyword skeyword logo +syn keyword skeyword metadata syn keyword skeyword model +syn keyword skeyword opacity syn keyword skeyword person syn keyword skeyword perspectives syn keyword skeyword properties syn keyword skeyword relationship +syn keyword skeyword routing +syn keyword skeyword scope +syn keyword skeyword shape syn keyword skeyword softwaresystem syn keyword skeyword softwaresysteminstance +syn keyword skeyword stroke +syn keyword skeyword strokewidth syn keyword skeyword styles syn keyword skeyword systemcontext syn keyword skeyword systemlandscape +syn keyword skeyword tag syn keyword skeyword tags syn keyword skeyword technology syn keyword skeyword terminology syn keyword skeyword theme syn keyword skeyword themes +syn keyword skeyword thickness +syn keyword skeyword this syn keyword skeyword title syn keyword skeyword url syn keyword skeyword users syn keyword skeyword views +syn keyword skeyword visibility +syn keyword skeyword width syn keyword skeyword workspace syn match skeyword "\!adrs\s\+" -syn match skeyword "\!constant\s\+" +syn match skeyword "\!components\s\+" syn match skeyword "\!docs\s\+" +syn match skeyword "\!element\s\+" +syn match skeyword "\!elements\s\+" +syn match skeyword "\!extend\s\+" syn match skeyword "\!identifiers\s\+" syn match skeyword "\!impliedrelationships\s\+" syn match skeyword "\!include\s\+" syn match skeyword "\!plugin\s\+" syn match skeyword "\!ref\s\+" +syn match skeyword "\!relationship\s\+" +syn match skeyword "\!relationships\s\+" syn match skeyword "\!script\s\+" syn region sstring oneline start='"' end='"' syn region sblock start='{' end='}' fold transparent +syn match soperator "\->\s+" + hi def link sstring string hi def link scomment comment hi def link skeyword keyword +hi def link soperator operator let b:current_syntax = "structurizr" From d91124f926c85e292b6141191fd98d77cac1e623 Mon Sep 17 00:00:00 2001 From: Yee Cheng Chin Date: Thu, 7 Nov 2024 22:11:06 +0100 Subject: [PATCH 045/106] patch 9.1.0846: debug symbols for xxd are not cleaned in Makefile Problem: debug symbols for xxd are not cleaned in Makefile Solution: remove xxd.dSYM in xxds Makefile, call xxd clean target from main Makefile (Yee Cheng Chin) Remove xxd.dSYM folder when calling `make clean`. On macOS, when compiling with debug info, clang will generate a "dSYM" folder that contains debug symbols for the executable because unlike Linux, the DWARF data is not embedded in the executable itself. closes: #16010 Signed-off-by: Yee Cheng Chin Signed-off-by: Christian Brabandt --- src/Makefile | 5 +++-- src/version.c | 2 ++ src/xxd/Makefile | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index c7ba9fbf7c..7bb0a7ebd6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2882,9 +2882,9 @@ uninstall_runtime: # Clean up all the files that have been produced, except configure's. # We support common typing mistakes for Juergen! :-) clean celan: testclean - -rm -f *.o core $(VIMTARGET).core $(VIMTARGET) vim xxd/*.o + -rm -f *.o core $(VIMTARGET).core $(VIMTARGET) vim -rm -rf objects - -rm -f $(TOOLS) auto/osdef.h auto/pathdef.c auto/if_perl.c auto/gui_gtk_gresources.c auto/gui_gtk_gresources.h auto/os_haiku.rdef + -rm -f auto/osdef.h auto/pathdef.c auto/if_perl.c auto/gui_gtk_gresources.c auto/gui_gtk_gresources.h auto/os_haiku.rdef -rm -f conftest* *~ auto/link.sed -rm -f testdir/opt_test.vim -rm -f $(UNITTEST_TARGETS) @@ -2894,6 +2894,7 @@ clean celan: testclean if test -d $(PODIR); then \ cd $(PODIR); $(MAKE) prefix=$(DESTDIR)$(prefix) clean; \ fi + cd xxd; $(MAKE) clean # Make a shadow directory for compilation on another system or with different # features: diff --git a/src/version.c b/src/version.c index 22d1d2616d..a1b75862f7 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 */ +/**/ + 846, /**/ 845, /**/ diff --git a/src/xxd/Makefile b/src/xxd/Makefile index d08af7aa01..5937f13746 100644 --- a/src/xxd/Makefile +++ b/src/xxd/Makefile @@ -5,3 +5,4 @@ xxd: xxd.c clean: rm -f xxd xxd.o + rm -rf xxd.dSYM From 28d3941ede2995b76755ec1fab7f347bc1663b86 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Thu, 7 Nov 2024 23:05:57 +0100 Subject: [PATCH 046/106] patch 9.1.0847: tests: test_popupwin fails because of updated help file Problem: tests: test_popupwin fails because of updated main help file Solution: normalize Last Change header in test_popup_setbuf screendumps Signed-off-by: Christian Brabandt --- src/testdir/dumps/Test_popup_setbuf_04.vim | 2 ++ src/testdir/dumps/Test_popup_setbuf_05.vim | 2 ++ src/testdir/dumps/Test_popup_setbuf_06.vim | 2 ++ src/version.c | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 src/testdir/dumps/Test_popup_setbuf_04.vim create mode 100644 src/testdir/dumps/Test_popup_setbuf_05.vim create mode 100644 src/testdir/dumps/Test_popup_setbuf_06.vim diff --git a/src/testdir/dumps/Test_popup_setbuf_04.vim b/src/testdir/dumps/Test_popup_setbuf_04.vim new file mode 100644 index 0000000000..f55dbf30d8 --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_04.vim @@ -0,0 +1,2 @@ +" replace Last Change Header in help.txt +:1s/|L|a|s|t| |c|h|a|n|g|e|:| |\d|\d|\d|\d| |\w|\w|\w| |\d|\d|/|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7|/g diff --git a/src/testdir/dumps/Test_popup_setbuf_05.vim b/src/testdir/dumps/Test_popup_setbuf_05.vim new file mode 100644 index 0000000000..f55dbf30d8 --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_05.vim @@ -0,0 +1,2 @@ +" replace Last Change Header in help.txt +:1s/|L|a|s|t| |c|h|a|n|g|e|:| |\d|\d|\d|\d| |\w|\w|\w| |\d|\d|/|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7|/g diff --git a/src/testdir/dumps/Test_popup_setbuf_06.vim b/src/testdir/dumps/Test_popup_setbuf_06.vim new file mode 100644 index 0000000000..f55dbf30d8 --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_06.vim @@ -0,0 +1,2 @@ +" replace Last Change Header in help.txt +:1s/|L|a|s|t| |c|h|a|n|g|e|:| |\d|\d|\d|\d| |\w|\w|\w| |\d|\d|/|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7|/g diff --git a/src/version.c b/src/version.c index a1b75862f7..fe1902e56a 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 */ +/**/ + 847, /**/ 846, /**/ From 07c9ab8c0549158bdd10fde38243a8b95214f5b7 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Fri, 8 Nov 2024 12:42:51 +0100 Subject: [PATCH 047/106] git: git-blame-ignore-revs shown as an error on Github So let's move the comment above the actual revision. related: https://github.com/vim/vim/commit/88542445871d882b2a0e79410774797a73fe9e60#commitcomment-148723832 Signed-off-by: Christian Brabandt --- .git-blame-ignore-revs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index f859027d68..5888c31fcf 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -5,5 +5,6 @@ # # Run this command to always ignore formatting commits in git blame # git config blame.ignoreRevsFile .git-blame-ignore-revs -# -8ce738de3fd7192fa6274730594305cde780074c # expand tabs to spaces in sound.c + +# Patch v9.1.0829 expanded tabs to spaces in sound.c +8ce738de3fd7192fa6274730594305cde780074c From 0f60fbf6796b72111184a6734b702a93f8f8944b Mon Sep 17 00:00:00 2001 From: Konfekt Date: Fri, 8 Nov 2024 18:49:43 +0100 Subject: [PATCH 048/106] runtime(compiler): improve cppcheck Properly escape the values for makeprg according to the :set rules closes: #16014 Signed-off-by: Konfekt Signed-off-by: Christian Brabandt --- runtime/compiler/cppcheck.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/compiler/cppcheck.vim b/runtime/compiler/cppcheck.vim index d6fc0d6873..4df12d1714 100644 --- a/runtime/compiler/cppcheck.vim +++ b/runtime/compiler/cppcheck.vim @@ -1,7 +1,7 @@ " vim compiler file " Compiler: cppcheck (C++ static checker) " Maintainer: Vincent B. (twinside@free.fr) -" Last Change: 2024 Oct 17 by @Konfekt +" Last Change: 2024 Nov 08 by @Konfekt if exists("current_compiler") | finish | endif let current_compiler = "cppcheck" @@ -25,7 +25,7 @@ let &l:makeprg = 'cppcheck --quiet' \ (filereadable('compile_commands.json') ? '--project=compile_commands.json' : \ (!empty(glob('*'..s:slash..'compile_commands.json', 1, 1)) ? '--project='..glob('*'..s:slash..'compile_commands.json', 1, 1)[0] : \ (empty(&path) ? '' : '-I')..join(map(filter(split(&path, ','), 'isdirectory(v:val)'),'shellescape(v:val)'), ' -I'))))) -silent CompilerSet makeprg +exe 'CompilerSet makeprg='..escape(&l:makeprg, ' "') CompilerSet errorformat= \%f:%l:%c:\ %tarning:\ %m, From 815c822aaf58bf533995da476c77fa27c2f058d7 Mon Sep 17 00:00:00 2001 From: Antonio Giovanni Colombo Date: Fri, 8 Nov 2024 18:53:56 +0100 Subject: [PATCH 049/106] translation(it): Updated Italian vimtutor Signed-off-by: Antonio Giovanni Colombo Signed-off-by: Christian Brabandt --- runtime/doc/vimtutor-it.1 | 95 ++++++++++++++++++++++++--------- runtime/doc/vimtutor-it.UTF-8.1 | 95 ++++++++++++++++++++++++--------- 2 files changed, 140 insertions(+), 50 deletions(-) diff --git a/runtime/doc/vimtutor-it.1 b/runtime/doc/vimtutor-it.1 index 36103dfc6c..28d921b95a 100644 --- a/runtime/doc/vimtutor-it.1 +++ b/runtime/doc/vimtutor-it.1 @@ -1,61 +1,106 @@ -.TH VIMTUTOR 1 "12 agosto 2024" +.TH VIMTUTOR 1 "04 novembre 2024" .SH NOME vimtutor \- Un breve corso introduttivo a Vim .SH SINTASSI .br -.B vimtutor [\-g] [lingua] +.B vimtutor [\-l | \-\-language ISO639] [\-c | \-\-chapter NUMERO] [\-g | \-\-gui] [ISO639] +.br +.B vimtutor [\-h | \-\-help] +.br +.B vimtutor [\-\-list] .SH DESCRIZIONE .B Vimtutor inizia il .B Vim tutor (un breve corso introduttivo a Vim). -Viene utilizzata una copia del file di lavoro, che pu cos essere modificato -a piacere senza alterare il file usato come modello. .PP Il comando .B Vimtutor utile a chi voglia imparare i primi comandi di -.B Vim -. -.PP -L'argomento opzionale \-g inizia vimtutor usando gvim invece che vim, se la -versione GUI di vim disponibile; altrimenti viene utilizzato vim. -.PP -L'argomento opzionale [lingua] l'abbreviazione di due lettere del nome +.B Vim. +L'argomento opzionale [language] specifica l'abbreviazione di due lettere del nome di una lingua, per esempio "it" oppure "es". -Se l'argomento [lingua] non viene specificato, si utilizza la lingua "locale" -del computer. -Se la versione in tale lingua del "tutor" non disponibile, -verr usata la versione inglese. +.PP +.B Vimtutor +utilizza delle copie dei file originali, non c' pericolo di danneggiare +i file stessi. .PP .B Vim sempre iniziato in Modo compatibile con Vi. +.SH OPZIONI +.TP +.BR \-l ", " \-\-language =\fIISO639\fR +Imposta il codice di due o tre lettere che designa la lingua. +P.es., 'it', 'es', 'bar'. +Il default il linguaggio locale, se una traduzione disponibile, +altrimenti viene utilizzato il testo originale in inglese. +.TP +.BR \-c ", " \-\-chapter =\fINUMBER\fR +Imposta il numero del capitolo. Il default il capitolo uno. +.TP +.BR \-g ", " \-\-gui +Inizia +.B vimtutor +nella versione GUI di vim, se disponibile, altrimenti viene usata la versione console. +.TP +.BR \-h ", " \-\-help +Visualizza le informazioni relative all'uso del comando. +.TP +.BR \-\-list +Visualizza capitoli e lingue disponibili. +.SH ESEMPI +Per iniziare +.B vimtutor +in tedesco, dal capitolo uno: +.PP +.nf +.RS +vimtutor de +.RE +.fi +.PP +In inglese, dal capitolo due: +.PP +.nf +.RS +vimtutor -c2 +.RE +.fi +.PP +Comandi nel formato esteso per usare il linguaggio bavarese, nella GUI, dal capitolo uno: +.PP +.nf +.RS +vimtutor --language bar --chapter 1 --gui +.RE +.fi .SH FILE .TP 15 /usr/local/lib/vim/vim??/tutor/tutor[.lingua] -I file di testo per +I file di testo per il capitolo uno di .B Vimtutor . -.br -.I vim?? - il numero di versione corto, p.es., vim91 per indicare -.B Vim 9.1. +.TP 15 +/usr/local/share/vim/vim??/tutor/tutor2[.lingua] +I file di testo per il capitolo due di +.B Vimtutor. .TP 15 /usr/local/share/vim/vim??/tutor/tutor.vim Lo script di Vim usato per copiare il file di testo -.B Vimtutor -. +.B Vimtutor. .SH AUTORE Il corso introduttivo .B Vimtutor stato scritto in origine per Vi da Michael C. Pierce e Robert K. Ware, Colorado School of Mines, usando idee fornite da Charles Smith, Colorado State University. -E-mail: bware@mines.colorado.edu (non pi valido). -.br - stato modificato per +.B E-mail: bware@mines.colorado.edu (non pi valido). +.PP +.B Vimtutor + stato modificato per .B Vim da Bram Moolenaar. +.PP Per i nomi dei traduttori, vedere i file nelle rispettive lingue. .SH VEDERE ANCHE vim(1) diff --git a/runtime/doc/vimtutor-it.UTF-8.1 b/runtime/doc/vimtutor-it.UTF-8.1 index ae42b10d5c..47b68b52ee 100644 --- a/runtime/doc/vimtutor-it.UTF-8.1 +++ b/runtime/doc/vimtutor-it.UTF-8.1 @@ -1,61 +1,106 @@ -.TH VIMTUTOR 1 "12 agosto 2024" +.TH VIMTUTOR 1 "04 novembre 2024" .SH NOME vimtutor \- Un breve corso introduttivo a Vim .SH SINTASSI .br -.B vimtutor [\-g] [lingua] +.B vimtutor [\-l | \-\-language ISO639] [\-c | \-\-chapter NUMERO] [\-g | \-\-gui] [ISO639] +.br +.B vimtutor [\-h | \-\-help] +.br +.B vimtutor [\-\-list] .SH DESCRIZIONE .B Vimtutor inizia il .B Vim tutor (un breve corso introduttivo a Vim). -Viene utilizzata una copia del file di lavoro, che può così essere modificato -a piacere senza alterare il file usato come modello. .PP Il comando .B Vimtutor è utile a chi voglia imparare i primi comandi di -.B Vim -. -.PP -L'argomento opzionale \-g inizia vimtutor usando gvim invece che vim, se la -versione GUI di vim è disponibile; altrimenti viene utilizzato vim. -.PP -L'argomento opzionale [lingua] è l'abbreviazione di due lettere del nome +.B Vim. +L'argomento opzionale [language] specifica l'abbreviazione di due lettere del nome di una lingua, per esempio "it" oppure "es". -Se l'argomento [lingua] non viene specificato, si utilizza la lingua "locale" -del computer. -Se la versione in tale lingua del "tutor" non è disponibile, -verrà usata la versione inglese. +.PP +.B Vimtutor +utilizza delle copie dei file originali, non c'è pericolo di danneggiare +i file stessi. .PP .B Vim è sempre iniziato in Modo compatibile con Vi. +.SH OPZIONI +.TP +.BR \-l ", " \-\-language =\fIISO639\fR +Imposta il codice di due o tre lettere che designa la lingua. +P.es., 'it', 'es', 'bar'. +Il default è il linguaggio locale, se una traduzione è disponibile, +altrimenti viene utilizzato il testo originale in inglese. +.TP +.BR \-c ", " \-\-chapter =\fINUMBER\fR +Imposta il numero del capitolo. Il default è il capitolo uno. +.TP +.BR \-g ", " \-\-gui +Inizia +.B vimtutor +nella versione GUI di vim, se disponibile, altrimenti viene usata la versione console. +.TP +.BR \-h ", " \-\-help +Visualizza le informazioni relative all'uso del comando. +.TP +.BR \-\-list +Visualizza capitoli e lingue disponibili. +.SH ESEMPI +Per iniziare +.B vimtutor +in tedesco, dal capitolo uno: +.PP +.nf +.RS +vimtutor de +.RE +.fi +.PP +In inglese, dal capitolo due: +.PP +.nf +.RS +vimtutor -c2 +.RE +.fi +.PP +Comandi nel formato esteso per usare il linguaggio bavarese, nella GUI, dal capitolo uno: +.PP +.nf +.RS +vimtutor --language bar --chapter 1 --gui +.RE +.fi .SH FILE .TP 15 /usr/local/lib/vim/vim??/tutor/tutor[.lingua] -I file di testo per +I file di testo per il capitolo uno di .B Vimtutor . -.br -.I vim?? -è il numero di versione corto, p.es., vim91 per indicare -.B Vim 9.1. +.TP 15 +/usr/local/share/vim/vim??/tutor/tutor2[.lingua] +I file di testo per il capitolo due di +.B Vimtutor. .TP 15 /usr/local/share/vim/vim??/tutor/tutor.vim Lo script di Vim usato per copiare il file di testo -.B Vimtutor -. +.B Vimtutor. .SH AUTORE Il corso introduttivo .B Vimtutor è stato scritto in origine per Vi da Michael C. Pierce e Robert K. Ware, Colorado School of Mines, usando idee fornite da Charles Smith, Colorado State University. -E-mail: bware@mines.colorado.edu (non più valido). -.br -È stato modificato per +.B E-mail: bware@mines.colorado.edu (non più valido). +.PP +.B Vimtutor +è stato modificato per .B Vim da Bram Moolenaar. +.PP Per i nomi dei traduttori, vedere i file nelle rispettive lingue. .SH VEDERE ANCHE vim(1) From 5e7f43b6ac2ac23d4fbfded75827a13f981d9a96 Mon Sep 17 00:00:00 2001 From: Ella Moss Date: Sat, 9 Nov 2024 11:32:15 +0100 Subject: [PATCH 050/106] runtime(termdebug): allow to use decimal signs closes: #16011 Co-authored-by: Christian Brabandt Signed-off-by: Ella Moss Signed-off-by: Christian Brabandt --- runtime/doc/terminal.txt | 12 ++++++++---- runtime/pack/dist/opt/termdebug/plugin/termdebug.vim | 5 +++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index 6b53e0223a..7027b3fef7 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -1,4 +1,4 @@ -*terminal.txt* For Vim version 9.1. Last change: 2024 Oct 27 +*terminal.txt* For Vim version 9.1. Last change: 2024 Nov 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1683,13 +1683,17 @@ Change default signs ~ Termdebug uses the hex number of the breakpoint ID in the signcolumn to represent breakpoints. If it is greater than "0xFF", then it will be displayed as "F+", due to we really only have two screen cells for the sign. +You may also use decimal breakpoint signs instead, in which case IDs greater +than 99 will be displayed as "9+". -If you want to customize the breakpoint signs: > +If you want to customize the breakpoint signs to show `>>` in the signcolumn: > let g:termdebug_config['sign'] = '>>' +If you would like to use decimal (base 10) breakpoint signs: > + let g:termdebug_config['sign_decimal'] = 1 If there is no g:terminal_config yet you can use: > let g:termdebug_config = {'sign': '>>'} - -After this, breakpoints will be displayed as `>>` in the signcolumn. +Likewise, to enable decimal signs: > + let g:termdebug_config = {'sign_decimal': 1} Window toolbar ~ diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index e7c010d4ce..6f1f4b5227 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -1912,6 +1912,11 @@ def CreateBreakpoint(id: number, subid: number, enabled: string) var label = '' if exists('g:termdebug_config') && has_key(g:termdebug_config, 'sign') label = g:termdebug_config['sign'] + elseif exists('g:termdebug_config') && has_key(g:termdebug_config, 'sign_decimal') + label = printf('%02d', id) + if id > 99 + label = '9+' + endif else label = printf('%02X', id) if id > 255 From a14c457cad99621db7950b78e7d257c300b7d897 Mon Sep 17 00:00:00 2001 From: Dani Dickstein Date: Sat, 9 Nov 2024 11:53:54 +0100 Subject: [PATCH 051/106] runtime(dune): use :setl instead of :set in ftplugin closes: #11419 Signed-off-by: Dani Dickstein Signed-off-by: Christian Brabandt --- runtime/ftplugin/dune.vim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/ftplugin/dune.vim b/runtime/ftplugin/dune.vim index 6e20a8fabb..7608d53527 100644 --- a/runtime/ftplugin/dune.vim +++ b/runtime/ftplugin/dune.vim @@ -6,13 +6,14 @@ " 2023 Aug 28 - Added undo_ftplugin (Vim Project) " 2018 Nov 03 - Added commentstring (Markus Mottl) " 2017 Sep 06 - Initial version (Etienne Millon) +" 2024 Nov 09 - use setl instead of :set if exists("b:did_ftplugin") finish endif let b:did_ftplugin=1 -set lisp +setl lisp " Comment string setl commentstring=;\ %s From 50732c7ba648f955ba027e6386745ea37acf007b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 9 Nov 2024 18:30:10 +0100 Subject: [PATCH 052/106] patch 9.1.0848: if_lua: v:false/v:true are not evaluated to boolean Problem: if_lua: v:false/v:true are not evaluated to boolean Solution: Use lua_pushboolean() instead of lua_pushinteger(). (zeertzjq) fixes: #15994 closes: #11419 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- src/if_lua.c | 2 +- src/testdir/test_lua.vim | 8 ++++---- src/testdir/test_python3.vim | 2 +- src/version.c | 2 ++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/if_lua.c b/src/if_lua.c index 4d19c3ef52..d01b9f96ad 100644 --- a/src/if_lua.c +++ b/src/if_lua.c @@ -595,7 +595,7 @@ luaV_pushtypval(lua_State *L, typval_T *tv) case VAR_BOOL: case VAR_SPECIAL: if (tv->vval.v_number <= VVAL_TRUE) - lua_pushinteger(L, (int) tv->vval.v_number); + lua_pushboolean(L, (int) tv->vval.v_number); else lua_pushnil(L); break; diff --git a/src/testdir/test_lua.vim b/src/testdir/test_lua.vim index a99affc047..5225ce8f8e 100644 --- a/src/testdir/test_lua.vim +++ b/src/testdir/test_lua.vim @@ -117,11 +117,11 @@ func Test_lua_eval() " lua.eval with a bool lua v = vim.eval('v:true') - call assert_equal('number', luaeval('vim.type(v)')) - call assert_equal(1, luaeval('v')) + call assert_equal('boolean', luaeval('vim.type(v)')) + call assert_equal(v:true, luaeval('v')) lua v = vim.eval('v:false') - call assert_equal('number', luaeval('vim.type(v)')) - call assert_equal(0, luaeval('v')) + call assert_equal('boolean', luaeval('vim.type(v)')) + call assert_equal(v:false, luaeval('v')) " lua.eval with a null lua v = vim.eval('v:null') diff --git a/src/testdir/test_python3.vim b/src/testdir/test_python3.vim index 5e2b555be4..20f9dc6c69 100644 --- a/src/testdir/test_python3.vim +++ b/src/testdir/test_python3.vim @@ -299,7 +299,7 @@ func Test_unicode() endfunc " Test vim.eval() with various types. -func Test_python3_vim_val() +func Test_python3_vim_eval() call assert_equal("\n8", execute('py3 print(vim.eval("3+5"))')) call assert_equal("\n3.140000", execute('py3 print(vim.eval("1.01+2.13"))')) call assert_equal("\n0.000000", execute('py3 print(vim.eval("0.0/(1.0/0.0)"))')) diff --git a/src/version.c b/src/version.c index fe1902e56a..2839e89808 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 */ +/**/ + 848, /**/ 847, /**/ From 624bb83619cbd685b1902b016ca3ececfc1c135c Mon Sep 17 00:00:00 2001 From: h-east Date: Sat, 9 Nov 2024 18:37:32 +0100 Subject: [PATCH 053/106] runtime(doc): Tweak documentation style a bit closes: #11419 Signed-off-by: h-east Signed-off-by: Christian Brabandt --- runtime/defaults.vim | 4 +-- runtime/doc/builtin.txt | 8 +++--- runtime/doc/filetype.txt | 6 ++--- runtime/doc/if_pyth.txt | 6 ++--- runtime/doc/pattern.txt | 38 +++++++++++++-------------- runtime/doc/pi_netrw.txt | 4 +-- runtime/doc/pi_tutor.txt | 14 +++++----- runtime/doc/syntax.txt | 57 ++++++++++++++++++++-------------------- runtime/doc/undo.txt | 4 +-- 9 files changed, 71 insertions(+), 70 deletions(-) diff --git a/runtime/defaults.vim b/runtime/defaults.vim index 4e58233ea5..1dcc959c26 100644 --- a/runtime/defaults.vim +++ b/runtime/defaults.vim @@ -1,7 +1,7 @@ " The default vimrc file. " " Maintainer: The Vim Project -" Last Change: 2024 Nov 03 +" Last Change: 2024 Nov 09 " Former Maintainer: Bram Moolenaar " " This is loaded if no vimrc file was found. @@ -115,7 +115,7 @@ if 1 \ | execute "normal! g`\"" \ | endif - " Set the default background for putty to dark. Putty usually sets the + " Set the default background for putty to dark. Putty usually sets the " $TERM to xterm and by default it starts with a dark background which " makes syntax highlighting often hard to read with bg=light " undo this using: ":au! vimStartup TermResponse" diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 70d6f47a51..d32c09d2fb 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 06 +*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -5203,7 +5203,7 @@ glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) *glob()* on {list} -glob2regpat({string}) *glob2regpat()* +glob2regpat({string}) *glob2regpat()* Convert a file pattern, as used by glob(), into a search pattern. The result can be used to match with a string that is a file name. E.g. > @@ -5656,7 +5656,7 @@ iconv({string}, {from}, {to}) *iconv()* Return type: |String| -id({item}) *id()* +id({item}) *id()* The result is a unique String associated with the {item} and not with the {item}'s contents. It is only valid while the {item} exists and is referenced. It is valid only in the @@ -7081,7 +7081,7 @@ matchbufline({buf}, {pat}, {lnum}, {end}, [, {dict}]) Return type: list> or list -matchdelete({id} [, {win}) *matchdelete()* *E802* *E803* +matchdelete({id} [, {win}) *matchdelete()* *E802* *E803* Deletes a match with ID {id} previously defined by |matchadd()| or one of the |:match| commands. Returns 0 if successful, otherwise -1. See example for |matchadd()|. All matches can diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index be3ba021d0..88ec43f1df 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -1,4 +1,4 @@ -*filetype.txt* For Vim version 9.1. Last change: 2024 Oct 21 +*filetype.txt* For Vim version 9.1. Last change: 2024 Nov 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -946,8 +946,8 @@ To enable: > let g:typst_folding = 1 < *g:typst_foldnested* -When |TRUE| the Typst filetype plugin will fold nested heading under their parents -(default: |TRUE|) +When |TRUE| the Typst filetype plugin will fold nested heading under their +parents. (default: |TRUE|) To disable: > let g:typst_foldnested = 0 diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt index 0b6140f252..480ff02c27 100644 --- a/runtime/doc/if_pyth.txt +++ b/runtime/doc/if_pyth.txt @@ -1,4 +1,4 @@ -*if_pyth.txt* For Vim version 9.1. Last change: 2024 Nov 06 +*if_pyth.txt* For Vim version 9.1. Last change: 2024 Nov 09 VIM REFERENCE MANUAL by Paul Moore @@ -201,8 +201,8 @@ vim.eval(str) *python-eval* [{'cmd': '/^eval_expr(arg, nextcmd)$/', 'static': 0, 'name': ~ 'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}] ~ - NOTE: In vim9script, local variables in def functions are not visible - to to python evaluations. To pass local variables to python evaluations, + NOTE: In Vim9 script, local variables in def functions are not visible + to python evaluations. To pass local variables to python evaluations, use the {locals} dict when calling |py3eval()| and friends. vim.bindeval(str) *python-bindeval* diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index 4351944df9..6ebef9e44f 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -1,4 +1,4 @@ -*pattern.txt* For Vim version 9.1. Last change: 2024 Jun 18 +*pattern.txt* For Vim version 9.1. Last change: 2024 Nov 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -164,7 +164,7 @@ or auto suspended with nohlsearch plugin. See |nohlsearch-install|. When 'shortmess' does not include the "S" flag, Vim will automatically show an -index, on which the cursor is. This can look like this: > +index, on which the cursor is. This can look like this: > [1/5] Cursor is on first of 5 matches. [1/>99] Cursor is on first of more than 99 matches. @@ -757,7 +757,7 @@ overview. \([a-z]\+\)\zs,\1 ",abc" in "abc,abc" \@123<= - Like "\@<=" but only look back 123 bytes. This avoids trying lots + Like "\@<=" but only look back 123 bytes. This avoids trying lots of matches that are known to fail and make executing the pattern very slow. Example, check if there is a "<" just before "span": /<\@1<=span @@ -783,7 +783,7 @@ overview. \(\/\/.*\)\@ /\%Vfoo.*ba\%Vr -< This also works if only "foo bar" was Visually selected. This: > +< This also works if only "foo bar" was Visually selected. This: > /\%Vfoo.*bar\%V < would match "foo bar" if the Visual selection continues after the "r". Only works for the current buffer. @@ -1014,7 +1014,7 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on): < To match all characters after the current virtual column (where the cursor is): > /\%>.v.* -< Column 17 is not included, because this is a |/zero-width| match. To +< Column 17 is not included, because this is a |/zero-width| match. To include the column use: > /^.*\%17v. < This command does the same thing, but also matches when there is no @@ -1138,11 +1138,11 @@ x A single character, with no special meaning, matches itself in the collection: "[^xyz]" matches anything but 'x', 'y' and 'z'. - If two characters in the sequence are separated by '-', this is shorthand for the full list of ASCII characters between them. E.g., - "[0-9]" matches any decimal digit. If the starting character exceeds - the ending character, e.g. [c-a], E944 occurs. Non-ASCII characters + "[0-9]" matches any decimal digit. If the starting character exceeds + the ending character, e.g. [c-a], E944 occurs. Non-ASCII characters can be used, but the character values must not be more than 256 apart - in the old regexp engine. For example, searching by [\u3000-\u4000] - after setting re=1 emits a E945 error. Prepending \%#=2 will fix it. + in the old regexp engine. For example, searching by [\u3000-\u4000] + after setting re=1 emits a E945 error. Prepending \%#=2 will fix it. - A character class expression is evaluated to the set of characters belonging to that character class. The following character classes are supported: @@ -1208,7 +1208,7 @@ x A single character, with no special meaning, matches itself any character that's not in "^]-\bdertnoUux". "[\xyz]" matches '\', 'x', 'y' and 'z'. It's better to use "\\" though, future expansions may use other characters after '\'. - - Omitting the trailing ] is not considered an error. "[]" works like + - Omitting the trailing ] is not considered an error. "[]" works like "[]]", it matches the ']' character. - The following translations are accepted when the 'l' flag is not included in 'cpoptions': @@ -1444,14 +1444,14 @@ Finally, these constructs are unique to Perl: display you may get unexpected results. That is because Vim looks for a match in the line where redrawing starts. - Also see |matcharg()| and |getmatches()|. The former returns + Also see |matcharg()| and |getmatches()|. The former returns the highlight group and pattern of a previous |:match| command. The latter returns a list with highlight groups and patterns defined by both |matchadd()| and |:match|. Highlighting matches using |:match| are limited to three matches (aside from |:match|, |:2match| and |:3match| are - available). |matchadd()| does not have this limitation and in + available). |matchadd()| does not have this limitation and in addition makes it possible to prioritize matches. Another example, which highlights all characters in virtual @@ -1480,7 +1480,7 @@ Finally, these constructs are unique to Perl: with the lowest number has priority if several match at the same position. It uses the match id 3. The ":3match" command is used by (Vim < 9.0.2054) |matchparen| - plugin. You are suggested to use ":match" for manual matching + plugin. You are suggested to use ":match" for manual matching and ":2match" for another plugin or even better make use of the more flexible |matchadd()| (and similar) functions instead. @@ -1489,10 +1489,10 @@ Finally, these constructs are unique to Perl: Fuzzy matching refers to matching strings using a non-exact search string. Fuzzy matching will match a string, if all the characters in the search string -are present anywhere in the string in the same order. Case is ignored. In a +are present anywhere in the string in the same order. Case is ignored. In a matched string, other characters can be present between two consecutive -characters in the search string. If the search string has multiple words, then -each word is matched separately. So the words in the search string can be +characters in the search string. If the search string has multiple words, then +each word is matched separately. So the words in the search string can be present in any order in a string. Fuzzy matching assigns a score for each matched string based on the following @@ -1511,8 +1511,8 @@ will match the strings "GetPattern", "PatternGet", "getPattern", "patGetter", "getSomePattern", "MatchpatternGet" etc. The functions |matchfuzzy()| and |matchfuzzypos()| can be used to fuzzy search -a string in a List of strings. The matchfuzzy() function returns a List of -matching strings. The matchfuzzypos() functions returns the List of matches, +a string in a List of strings. The matchfuzzy() function returns a List of +matching strings. The matchfuzzypos() functions returns the List of matches, the matching positions and the fuzzy match scores. The "f" flag of `:vimgrep` enables fuzzy matching. diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index 6b4c5e06d4..c82a1bdeeb 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -1,4 +1,4 @@ -*pi_netrw.txt* For Vim version 9.1. Last change: 2024 Nov 02 +*pi_netrw.txt* For Vim version 9.1. Last change: 2024 Nov 09 ------------------------------------------------ NETRW REFERENCE MANUAL by Charles E. Campbell @@ -1537,7 +1537,7 @@ Associated setting variables: |g:netrw_nogx| prevent gx map while editing |g:netrw_suppress_gx_mesg| controls gx's suppression of browser messages -OPENING FILES AND LAUNCHING APPS *netrw-gx* *:Open* *:Launch* {{{2 +OPENING FILES AND LAUNCHING APPS *netrw-gx* *:Open* *:Launch* {{{2 Netrw determines which special handler by the following method: diff --git a/runtime/doc/pi_tutor.txt b/runtime/doc/pi_tutor.txt index 0f8479e88f..618fe745ac 100644 --- a/runtime/doc/pi_tutor.txt +++ b/runtime/doc/pi_tutor.txt @@ -1,26 +1,26 @@ -*pi_tutor.txt* For Vim version 9.1. Last change: 2024 Nov 03 +*pi_tutor.txt* For Vim version 9.1. Last change: 2024 Nov 09 INTERACTIVE TUTORIALS FOR VIM *vim-tutor-mode* vim-tutor-mode provides a system to follow and create interactive tutorials -for vim and third party plugins. It replaces the venerable `vimtutor` system. +for vim and third party plugins. It replaces the venerable `vimtutor` system. ============================================================================= 1. Usage *vim-tutor-usage* vim-tutor-mode tutorials are hypertext documents, they have rich text and -contain links. To stand out from the rest of the text, links are underlined. +contain links. To stand out from the rest of the text, links are underlined. You can follow them by placing the cursor over them and pressing , or by double-clicking them. 1.1 Commands ------------ *:Tutor* -:Tutor {tutorial} Opens a tutorial. Command-line completion for +:Tutor {tutorial} Opens a tutorial. Command-line completion for {tutorial} is provided, the candidates are a list of '.tutor' files found in the 'tutor/' folder in - the 'runtimepath'. Tutorials prefixed with 'vim-' will - always be shown first. + the 'runtimepath'. Tutorials prefixed with 'vim-' + will always be shown first. If no {tutorial} is provided, the command starts the 'vim-01-beginner' tutorial, which is equivalent to @@ -29,7 +29,7 @@ by double-clicking them. ============================================================================= 2. Creating tutorials *vim-tutor-create* -Writing vim-tutor-mode tutorials is easy. For an overview of the format used, +Writing vim-tutor-mode tutorials is easy. For an overview of the format used, please consult the 'tutor.tutor' file: > :Tutor tutor diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index be62c43b8c..eff99f7638 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1,4 +1,4 @@ -*syntax.txt* For Vim version 9.1. Last change: 2024 Oct 22 +*syntax.txt* For Vim version 9.1. Last change: 2024 Nov 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1679,20 +1679,20 @@ on" command in your .vimrc file. When you edit an existing Fortran file, the syntax script will assume free source form if the fortran_free_source variable has been set, and assumes fixed source form if the fortran_fixed_source variable has been set. Suppose -neither of these variables have been set. In that case, the syntax script attempts to -determine which source form has been used by examining the file extension -using conventions common to the ifort, gfortran, Cray, NAG, and PathScale -compilers (.f, .for, .f77 for fixed-source, .f90, .f95, .f03, .f08 for -free-source). No default is used for the .fpp and .ftn file extensions because -different compilers treat them differently. If none of this works, then the -script examines the first five columns of the first 500 lines of your file. If -no signs of free source form are detected, then the file is assumed to be in -fixed source form. The algorithm should work in the vast majority of cases. -In some cases, such as a file that begins with 500 or more full-line comments, -the script may incorrectly decide that the code is in fixed form. If that -happens, just add a non-comment statement beginning anywhere in the first five -columns of the first twenty-five lines, save (:w), and then reload (:e!) the -file. +neither of these variables have been set. In that case, the syntax script +attempts to determine which source form has been used by examining the file +extension using conventions common to the ifort, gfortran, Cray, NAG, and +PathScale compilers (.f, .for, .f77 for fixed-source, .f90, .f95, .f03, .f08 +for free-source). No default is used for the .fpp and .ftn file extensions +because different compilers treat them differently. If none of this works, +then the script examines the first five columns of the first 500 lines of your +file. If no signs of free source form are detected, then the file is assumed +to be in fixed source form. The algorithm should work in the vast majority of +cases. In some cases, such as a file that begins with 500 or more full-line +comments, the script may incorrectly decide that the code is in fixed form. +If that happens, just add a non-comment statement beginning anywhere in the +first five columns of the first twenty-five lines, save (:w), and then reload +(:e!) the file. Vendor extensions ~ Fixed-form Fortran requires a maximum line length of 72 characters but the @@ -2226,9 +2226,9 @@ define the vim variable 'lace_case_insensitive' in your startup file: > LF (LFRC) *lf.vim* *ft-lf-syntax* *g:lf_shell_syntax* *b:lf_shell_syntax* -For the lf file manager configuration files (lfrc) the shell commands -syntax highlighting can be changed globally and per buffer by setting -a different 'include' command search pattern using these variables: +For the lf file manager configuration files (lfrc) the shell commands syntax +highlighting can be changed globally and per buffer by setting a different +'include' command search pattern using these variables: > let g:lf_shell_syntax = "syntax/dosbatch.vim" let b:lf_shell_syntax = "syntax/zsh.vim" @@ -2538,9 +2538,10 @@ set "msql_minlines" to the value you desire. Example: > :let msql_minlines = 200 -NEOMUTT *neomutt.vim* *ft-neomuttrc-syntax* *ft-neomuttlog-syntax* +NEOMUTT *neomutt.vim* *ft-neomuttrc-syntax* + *ft-neomuttlog-syntax* -To disable the default NeoMutt log colors > +To disable the default NeoMutt log colors: > :let g:neolog_disable_default_colors = 1 @@ -2710,9 +2711,9 @@ specified. Default = 1 > :let g:pandoc#syntax#codeblocks#embeds#use = 1 -For specify what languages and using what syntax files to highlight embeds. This is a -list of language names. When the language pandoc and vim use don't match, you -can use the "PANDOC=VIM" syntax. For example: > +For specify what languages and using what syntax files to highlight embeds. +This is a list of language names. When the language pandoc and vim use don't +match, you can use the "PANDOC=VIM" syntax. For example: > :let g:pandoc#syntax#codeblocks#embeds#langs = ["ruby", "bash=sh"] @@ -3922,7 +3923,7 @@ set "tf_minlines" to the value you desire. Example: > :let tf_minlines = your choice < TYPESCRIPT *typescript.vim* *ft-typescript-syntax* - *typescriptreact.vim* *ft-typescriptreact-syntax* + *typescriptreact.vim* *ft-typescriptreact-syntax* There is one option to control the TypeScript syntax highlighting. @@ -5309,9 +5310,9 @@ of colors by using the `:colorscheme` command, for example: > This is basically the same as > :echo g:colors_name < In case g:colors_name has not been defined :colo will - output "default". Its palette is defined in the file + output "default". Its palette is defined in the file "$VIMRUNTIME/syntax/syncolor.vim" and is based on - legacy versions of peachpuff and desert. When compiled + legacy versions of peachpuff and desert. When compiled without the |+eval| feature it will output "unknown". :colo[rscheme] {name} Load color scheme {name}. This searches 'runtimepath' @@ -5721,8 +5722,8 @@ guisp={color-name} *highlight-guisp* :highlight Comment guifg=#11f0c3 guibg=#ff00ff < If you are authoring a color scheme and use the same hexadecimal value - repeatedly, you can define a (lower case) name for it in |v:colornames|. - For example: > + repeatedly, you can define a (lower case) name for it in + |v:colornames|. For example: > # provide a default value for this color but allow the user to # override it. diff --git a/runtime/doc/undo.txt b/runtime/doc/undo.txt index 7a83e776e3..1d6a481c6e 100644 --- a/runtime/doc/undo.txt +++ b/runtime/doc/undo.txt @@ -1,4 +1,4 @@ -*undo.txt* For Vim version 9.1. Last change: 2024 Sep 29 +*undo.txt* For Vim version 9.1. Last change: 2024 Nov 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -183,7 +183,7 @@ g- Go to older text state. With a count repeat that many g+ Go to newer text state. With a count repeat that many times. *:lat* *:later* -:lat[er] {count} Go to newer text state {count} times. +:lat[er] {count} Go to newer text state {count} times. :lat[er] {N}s Go to newer text state about {N} seconds later. :lat[er] {N}m Go to newer text state about {N} minutes later. :lat[er] {N}h Go to newer text state about {N} hours later. From 8e6b5034f32049fd0f1447c85ab71d47f49a820a Mon Sep 17 00:00:00 2001 From: amarakon Date: Sat, 9 Nov 2024 18:59:31 +0100 Subject: [PATCH 054/106] runtime(tex): add Number highlighting to syntax file closes: #11271 Signed-off-by: amarakon Signed-off-by: Christian Brabandt --- runtime/syntax/tex.vim | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim index d782bd4845..dc45790808 100644 --- a/runtime/syntax/tex.vim +++ b/runtime/syntax/tex.vim @@ -109,9 +109,9 @@ if s:tex_fold_enabled && &fdm == "manual" setl fdm=syntax endif if s:tex_fold_enabled && has("folding") - com! -nargs=* TexFold fold + com! -nargs=* TexFold fold else - com! -nargs=* TexFold + com! -nargs=* TexFold endif " (La)TeX keywords: uses the characters 0-9,a-z,A-Z,192-255 only... {{{1 @@ -162,7 +162,7 @@ endif " Clusters: {{{1 " -------- -syn cluster texCmdGroup contains=texCmdBody,texComment,texDefParm,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathOper,texNewCmd,texNewEnv,texRefZone,texSection,texBeginEnd,texBeginEndName,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,@texMathZones +syn cluster texCmdGroup contains=texCmdBody,texComment,texDefParm,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathOper,texMathNumber,texNewCmd,texNewEnv,texRefZone,texSection,texBeginEnd,texBeginEndName,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,@texMathZones if !s:tex_no_error syn cluster texCmdGroup add=texMathError endif @@ -202,8 +202,8 @@ if !exists("g:tex_no_math") syn cluster texMathZones contains=texMathZoneV,texMathZoneW,texMathZoneX,texMathZoneY,texMathZoneZ syn cluster texMatchGroup add=@texMathZones syn cluster texMathDelimGroup contains=texMathDelimBad,texMathDelimKey,texMathDelimSet1,texMathDelimSet2 - syn cluster texMathMatchGroup contains=@texMathZones,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathMatcher,texMathOper,texNewCmd,texNewEnv,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone - syn cluster texMathZoneGroup contains=texBadPar,texComment,texDelimiter,texLength,texMathDelim,texMathMatcher,texMathOper,texMathSymbol,texMathText,texRefZone,texSpecialChar,texStatement,texTypeSize,texTypeStyle + syn cluster texMathMatchGroup contains=@texMathZones,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathMatcher,texMathOper,texMathNumber,texNewCmd,texNewEnv,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone + syn cluster texMathZoneGroup contains=texBadPar,texComment,texDelimiter,texLength,texMathDelim,texMathMatcher,texMathOper,texMathNumber,texMathSymbol,texMathText,texRefZone,texSpecialChar,texStatement,texTypeSize,texTypeStyle if !s:tex_no_error syn cluster texMathMatchGroup add=texMathError syn cluster texMathZoneGroup add=texMathError @@ -424,7 +424,7 @@ if s:tex_fast =~# 'b' syn region texEmphStyle matchgroup=texTypeStyle start="\\texts[cfl]\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup,@Spell syn region texEmphStyle matchgroup=texTypeStyle start="\\textup\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup,@Spell syn region texEmphStyle matchgroup=texTypeStyle start="\\texttt\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup,@Spell - else + else syn region texBoldStyle matchgroup=texTypeStyle start="\\textbf\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup syn region texBoldItalStyle matchgroup=texTypeStyle start="\\textit\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texItalGroup syn region texItalStyle matchgroup=texTypeStyle start="\\textit\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texItalGroup @@ -502,6 +502,7 @@ if !exists("g:tex_no_math") endif syn match texMathOper "[_^=]" contained + syn match texMathNumber "\<\d\|\.\d" contained " Text Inside Math Zones: {{{2 if s:tex_fast =~# 'M' @@ -1330,6 +1331,7 @@ if !exists("skip_tex_syntax_inits") hi def link texMath Special hi def link texMathDelim Statement hi def link texMathOper Operator + hi def link texMathNumber Number hi def link texNewCmd Statement hi def link texNewEnv Statement hi def link texOption Number From bbe5252c2c2a6a49c794719a894ab10cdafebc62 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sat, 9 Nov 2024 19:11:25 +0100 Subject: [PATCH 055/106] runtime(vim): Update base-syntax, improve :normal highlighting Fix command name termination, match bang, and allow a line-continued argument. closes: #15358 Signed-off-by: Doug Kearns Signed-off-by: Christian Brabandt --- runtime/syntax/generator/vim.vim.base | 15 +++++++------- .../testdir/dumps/vim_ex_normal_00.dump | 20 +++++++++++++++++++ .../testdir/dumps/vim_ex_normal_01.dump | 20 +++++++++++++++++++ .../syntax/testdir/input/vim_ex_normal.vim | 20 +++++++++++++++++++ runtime/syntax/vim.vim | 13 ++++++------ 5 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 runtime/syntax/testdir/dumps/vim_ex_normal_00.dump create mode 100644 runtime/syntax/testdir/dumps/vim_ex_normal_01.dump create mode 100644 runtime/syntax/testdir/input/vim_ex_normal.vim diff --git a/runtime/syntax/generator/vim.vim.base b/runtime/syntax/generator/vim.vim.base index 9088af1033..6d67d7b93c 100644 --- a/runtime/syntax/generator/vim.vim.base +++ b/runtime/syntax/generator/vim.vim.base @@ -2,7 +2,7 @@ " Language: Vim script " Maintainer: Hirohito Higashi " Doug Kearns -" Last Change: 2024 Oct 05 +" Last Change: 2024 Oct 08 " Former Maintainer: Charles E. Campbell " DO NOT CHANGE DIRECTLY. @@ -202,7 +202,7 @@ syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSub syn case match " All vimCommands are contained by vimIsCommand. {{{2 -syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,vimDefFold,vimDelcommand,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimFuncFold,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNorm,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList +syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,vimDefFold,vimDelcommand,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimFuncFold,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNormal,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList syn cluster vim9CmdList contains=vim9Class,vim9Const,vim9Enum,vim9Export,vim9Final,vim9For,vim9Interface,vim9Type,vim9Var syn match vimCmdSep "[:|]\+" skipwhite nextgroup=@vimCmdList,vimSubst1 syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand @@ -214,6 +214,7 @@ syn match vimVar "\s\zs&t_\S[a-zA-Z0-9]\>" syn match vimVar "\s\zs&t_k;" syn match vimFBVar contained "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>" syn keyword vimCommand contained in +syn match vimBang contained "!" syn cluster vimExprList contains=vimEnvvar,vimFunc,vimNumber,vimOper,vimOperParen,vimLetRegister,vimString,vimVar,@vim9ExprList syn cluster vim9ExprList contains=vim9Boolean,vim9Null @@ -811,10 +812,10 @@ syn keyword vimMatchNone contained none syn case match syn region vimMatchPattern contained matchgroup=Delimiter start="\z([!#$%&'()*+,-./:;<=>?@[\]^_`{}~]\)" skip="\\\\\|\\\z1" end="\z1" contains=@vimSubstList oneline -" Norm: {{{2 -" ==== -syn match vimNorm "\!\=" skipwhite nextgroup=vimNormalArg contains=vimBang +syn region vimNormalArg contained start="\S" skip=+\n\s*\\\|\n\s*["#]\\ + end="$" contains=@vimContinue " Sleep: {{{2 " ===== @@ -1371,7 +1372,7 @@ if !exists("skip_vim_syntax_inits") hi def link vimMenutranslateComment vimComment hi def link vim9MethodName vimFuncName hi def link vimMtchComment vimComment - hi def link vimNorm vimCommand + hi def link vimNormal vimCommand hi def link vimNotation Special hi def link vimNotFunc vimCommand hi def link vimNotPatSep vimString diff --git a/runtime/syntax/testdir/dumps/vim_ex_normal_00.dump b/runtime/syntax/testdir/dumps/vim_ex_normal_00.dump new file mode 100644 index 0000000000..60a4537844 --- /dev/null +++ b/runtime/syntax/testdir/dumps/vim_ex_normal_00.dump @@ -0,0 +1,20 @@ +>"+0#0000e05#ffffff0| |V|i|m| |:|n|o|r|m|a|l| |c|o|m@1|a|n|d| +0#0000000&@53 +@75 +|n+0#af5f00255&|o|r|m|a|l| +0#0000000&|j| @66 +|n+0#af5f00255&|o|r|m|a|l|!| +0#0000000&|j| @65 +|n+0#af5f00255&|o|r|m|a|l|!|j+0#0000000&| @66 +@75 +|"+0#0000e05&| |n|o| |t|r|a|i|l|i|n|g| |b|a|r| +0#0000000&@57 +|n+0#af5f00255&|o|r|m|a|l| +0#0000000&|j| |4|2|||e|c|h|o| |"|n|o|t| |e|c|h|o| |c|o|m@1|a|n|d|"| @39 +@75 +|"+0#0000e05&| |n|o| |t|r|a|i|l|i|n|g| |c|o|m@1|e|n|t| +0#0000000&@53 +|n+0#af5f00255&|o|r|m|a|l| +0#0000000&|j| |"|0|p| @62 +@75 +|"+0#0000e05&| |m|u|l|t|i|l|i|n|e| |a|r|g| +0#0000000&@59 +|n+0#af5f00255&|o|r|m|a|l| +0#0000000&|j| @66 +@6|\+0#e000e06&|k+0#0000000&| @66 +@6|"+0#0000e05&|\| |c|o|m@1|e|n|t| +0#0000000&@58 +@6|\+0#e000e06&|j+0#0000000&| @66 +@75 +|"+0#0000e05&| |w|o|r|d|-|b|o|u|n|d|a|r|y| |r|e|q|u|i|r|e|d| |a|f|t|e|r| |n|a|m|e| |(|o|l|d| |b|u|g|)| +0#0000000&@29 +@57|1|,|1| @10|T|o|p| diff --git a/runtime/syntax/testdir/dumps/vim_ex_normal_01.dump b/runtime/syntax/testdir/dumps/vim_ex_normal_01.dump new file mode 100644 index 0000000000..b6fa3b87c0 --- /dev/null +++ b/runtime/syntax/testdir/dumps/vim_ex_normal_01.dump @@ -0,0 +1,20 @@ +|n+0#af5f00255#ffffff0|o|r|m|a|l| +0#0000000&|j| @66 +@6|\+0#e000e06&|k+0#0000000&| @66 +@6|"+0#0000e05&|\| |c|o|m@1|e|n|t| +0#0000000&@58 +@6|\+0#e000e06&|j+0#0000000&| @66 +@75 +>"+0#0000e05&| |w|o|r|d|-|b|o|u|n|d|a|r|y| |r|e|q|u|i|r|e|d| |a|f|t|e|r| |n|a|m|e| |(|o|l|d| |b|u|g|)| +0#0000000&@29 +|n|o|r|m|a|l|j| @67 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|1|9|,|1| @9|B|o|t| diff --git a/runtime/syntax/testdir/input/vim_ex_normal.vim b/runtime/syntax/testdir/input/vim_ex_normal.vim new file mode 100644 index 0000000000..174a3c7fb3 --- /dev/null +++ b/runtime/syntax/testdir/input/vim_ex_normal.vim @@ -0,0 +1,20 @@ +" Vim :normal command + +normal j +normal! j +normal!j + +" no trailing bar +normal j 42|echo "not echo command" + +" no trailing comment +normal j "0p + +" multiline arg +normal j + \k + "\ comment + \j + +" word-boundary required after name (old bug) +normalj diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 28fdda5215..eea6e82a89 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -240,7 +240,7 @@ syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSub syn case match " All vimCommands are contained by vimIsCommand. {{{2 -syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,vimDefFold,vimDelcommand,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimFuncFold,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNorm,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList +syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,vimDefFold,vimDelcommand,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimFuncFold,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNormal,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList syn cluster vim9CmdList contains=vim9Class,vim9Const,vim9Enum,vim9Export,vim9Final,vim9For,vim9Interface,vim9Type,vim9Var syn match vimCmdSep "[:|]\+" skipwhite nextgroup=@vimCmdList,vimSubst1 syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand @@ -252,6 +252,7 @@ syn match vimVar "\s\zs&t_\S[a-zA-Z0-9]\>" syn match vimVar "\s\zs&t_k;" syn match vimFBVar contained "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>" syn keyword vimCommand contained in +syn match vimBang contained "!" syn cluster vimExprList contains=vimEnvvar,vimFunc,vimNumber,vimOper,vimOperParen,vimLetRegister,vimString,vimVar,@vim9ExprList syn cluster vim9ExprList contains=vim9Boolean,vim9Null @@ -857,10 +858,10 @@ syn keyword vimMatchNone contained none syn case match syn region vimMatchPattern contained matchgroup=Delimiter start="\z([!#$%&'()*+,-./:;<=>?@[\]^_`{}~]\)" skip="\\\\\|\\\z1" end="\z1" contains=@vimSubstList oneline -" Norm: {{{2 -" ==== -syn match vimNorm "\!\=" skipwhite nextgroup=vimNormalArg contains=vimBang +syn region vimNormalArg contained start="\S" skip=+\n\s*\\\|\n\s*["#]\\ + end="$" contains=@vimContinue " Sleep: {{{2 " ===== @@ -1417,7 +1418,7 @@ if !exists("skip_vim_syntax_inits") hi def link vimMenutranslateComment vimComment hi def link vim9MethodName vimFuncName hi def link vimMtchComment vimComment - hi def link vimNorm vimCommand + hi def link vimNormal vimCommand hi def link vimNotation Special hi def link vimNotFunc vimCommand hi def link vimNotPatSep vimString From 060107cbc40a68b30d81e5531a1c8dde91fc9b59 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 10 Nov 2024 14:08:56 +0100 Subject: [PATCH 056/106] runtime(doc): fix typo in g:termdebug_config closes: #16023 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- runtime/doc/terminal.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index 7027b3fef7..637277ab59 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -1,4 +1,4 @@ -*terminal.txt* For Vim version 9.1. Last change: 2024 Nov 09 +*terminal.txt* For Vim version 9.1. Last change: 2024 Nov 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1690,7 +1690,7 @@ If you want to customize the breakpoint signs to show `>>` in the signcolumn: > let g:termdebug_config['sign'] = '>>' If you would like to use decimal (base 10) breakpoint signs: > let g:termdebug_config['sign_decimal'] = 1 -If there is no g:terminal_config yet you can use: > +If the variable g:termdebug_config does not yet exist, you can use: > let g:termdebug_config = {'sign': '>>'} Likewise, to enable decimal signs: > let g:termdebug_config = {'sign_decimal': 1} From 6065755a39d838aaba03808f77d58c34b3b63e91 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sun, 10 Nov 2024 14:10:52 +0100 Subject: [PATCH 057/106] runtime(tex): update Last Change header in syntax script related: #11271 Signed-off-by: Christian Brabandt --- runtime/syntax/tex.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim index dc45790808..bd47e168d7 100644 --- a/runtime/syntax/tex.vim +++ b/runtime/syntax/tex.vim @@ -4,6 +4,7 @@ " Former Maintainer: Charles E. Campbell " Last Change: Apr 22, 2022 " 2024 Feb 19 by Vim Project (announce adoption) +" 2024 Nov 09 add Number highlight (#11271) " Version: 121 " Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX " From 18defabaebe3b8e679b5df2d7c8ec82172a6e41b Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sun, 10 Nov 2024 20:10:42 +0100 Subject: [PATCH 058/106] runtime(doc): add a table of supported Operating Systems Signed-off-by: Christian Brabandt --- runtime/doc/tags | 1 + runtime/doc/version9.txt | 2 +- runtime/doc/vi_diff.txt | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/runtime/doc/tags b/runtime/doc/tags index 82a01e2d73..6e5085a0d8 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -9331,6 +9331,7 @@ options.txt options.txt /*options.txt* optwin options.txt /*optwin* or() builtin.txt /*or()* oracle ft_sql.txt /*oracle* +os-support vi_diff.txt /*os-support* os2 os_os2.txt /*os2* os390 os_390.txt /*os390* os_390.txt os_390.txt /*os_390.txt* diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index c4022d8882..daba9848c9 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -31790,7 +31790,7 @@ Changed ~ - The features |++builtin_terms|, |+cmdline_info|, |+cmdwin|, |+file_in_path|, |+float|, |+path_extra|, |+textobjects|, |+wildignore| and |+wildmenu| are available in all the builds. -- Support for Windows-XP is dropped. +- Support for Windows-XP is dropped (starting with v9.0.0496) - Support for VisVim is removed. - The "small" and "big" builds are dropped in favor of "tiny" and "huge" builds. diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt index 58bce5e53e..b96f77907c 100644 --- a/runtime/doc/vi_diff.txt +++ b/runtime/doc/vi_diff.txt @@ -1,4 +1,4 @@ -*vi_diff.txt* For Vim version 9.1. Last change: 2024 Oct 05 +*vi_diff.txt* For Vim version 9.1. Last change: 2024 Nov 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -21,6 +21,7 @@ is missing something or because Posix is beside the mark). 6. Supported Vi features |vi-features| 7. Command-line arguments |cmdline-arguments| 8. POSIX compliance |posix-compliance| +9. Supported Operating Systems |os-support| ============================================================================== 1. Simulated command *simulated-command* @@ -1361,5 +1362,37 @@ These are remarks about running the POSIX test suite: 1 instead of 2. - ex test 534 fails because .exrc isn't read in silent mode. +============================================================================== +9. Supported Operating systems *os-support* + +Vim tries to support some old operating systems, however support for older +operating systems might be dropped if maintenance becomes a burden or can no +longer be verified. + +Here is the status of some operating systems. Note fully supported means, +support is verified as part of the CI test suite. + +System | Status:~ +--------------------------------+----------------------------------------- +Amiga (OS4, AROS & MorphOS): | still supported (?) +Haiku: | still supported (?) +Linux: | fully supported (on maintained versions) +Mac OS: | fully supported up until v10.6 (?) +MS-Windows 7, 8, 10, 11: | fully supported +UNIX: | supported (on maintained versions) +OpenVMS: | supported +QNX: | still supported (?) +zOS/OS390: | still supported (?) + +The following operating systems are no longer supported: + +System | Status:~ +--------------------------------+----------------------------------------- +Atari MiNT | support was dropped with v8.2.1215 +BeOS: | support was dropped with v8.2.0849 +MS-DOS: | support was dropped with v7.4.1399 +MS-Windows XP and Vista: | support was dropped with v9.0.0496 +OS/2 | support was dropped with v7.4.1008 +RISC OS: | support was dropped with v7.3.0187 vim:tw=78:ts=8:noet:ft=help:norl: From 5b63b236a0af198f6c3c9883a3f6344b110dabb3 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sun, 10 Nov 2024 20:22:34 +0100 Subject: [PATCH 059/106] runtime(netrw): directory symlink not resolved in tree view closes: #16020 Signed-off-by: Christian Brabandt --- runtime/autoload/netrw.vim | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index 6799a3444b..d11c43a494 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -34,6 +34,7 @@ " 2024 Oct 31 by Vim Project: fix E874 when browsing remote dir (#15964) " 2024 Nov 07 by Vim Project: use keeppatterns to prevent polluting the search history " 2024 Nov 07 by Vim Project: fix a few issues with netrw tree listing (#15996) +" 2024 Nov 10 by Vim Project: directory symlink not resolved in tree view (#16020) " }}} " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim @@ -4585,6 +4586,12 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,cursor,...) if a:cursor && exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treetop") " dirname is the path to the word under the cursor let dirname = s:NetrwTreePath(w:netrw_treetop) + " newdir resolves to a directory and points to a directory in dirname + " /tmp/test/folder_symlink/ -> /tmp/test/original_folder/ + if a:islocal && fnamemodify(dirname, ':t') == newdir && isdirectory(resolve(dirname)) && resolve(dirname) == resolve(newdir) + let dirname = fnamemodify(resolve(dirname), ':p:h:h') + let newdir = fnamemodify(resolve(newdir), ':t') + endif " Remove trailing "/" let dirname = substitute(dirname, "/$", "", "") From 7c5152826f61bc968ba539ff6db3a55e75556bf2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 10 Nov 2024 20:26:12 +0100 Subject: [PATCH 060/106] patch 9.1.0849: there are a few typos in the source Problem: there are a few typos in the source. Solution: Correct typos (zeertzjq). closes: #16026 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- runtime/doc/Make_mvc.mak | 2 +- runtime/doc/builtin.txt | 14 +++++++------- runtime/doc/quickfix.txt | 4 ++-- runtime/doc/syntax.txt | 4 ++-- runtime/doc/tags | 2 +- src/ex_cmds.c | 2 +- src/po/Make_mvc.mak | 2 +- src/testdir/test_diffmode.vim | 2 +- src/version.c | 2 ++ 9 files changed, 18 insertions(+), 16 deletions(-) diff --git a/runtime/doc/Make_mvc.mak b/runtime/doc/Make_mvc.mak index 5bfe934e3d..a6af4baf8a 100644 --- a/runtime/doc/Make_mvc.mak +++ b/runtime/doc/Make_mvc.mak @@ -10,7 +10,7 @@ # TODO: to think about what to use instead of awk. PowerShell? #AWK = -# Correct the following line for the where executeable file vim is installed. +# Correct the following line for the where executable file vim is installed. # Please do not put the path in quotes. VIMPROG = D:\Programs\Vim\vim91\vim.exe diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index d32c09d2fb..67f447d7db 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 09 +*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -467,9 +467,9 @@ prop_type_get({name} [, {props}]) prop_type_list([{props}]) List get list of property types pum_getpos() Dict position and size of pum if visible pumvisible() Number whether popup menu is visible -py3eval({expr}[, {locals}]) any evaluate |python3| expression -pyeval({expr}[, {locals}]) any evaluate |Python| expression -pyxeval({expr}[, {locals}]) any evaluate |python_x| expression +py3eval({expr} [, {locals}]) any evaluate |python3| expression +pyeval({expr} [, {locals}]) any evaluate |Python| expression +pyxeval({expr} [, {locals}]) any evaluate |python_x| expression rand([{expr}]) Number get pseudo-random number range({expr} [, {max} [, {stride}]]) List items from {expr} to {max} @@ -8127,7 +8127,7 @@ pumvisible() *pumvisible()* Return type: |Number| -py3eval({expr}[, {locals}]) *py3eval()* +py3eval({expr} [, {locals}]) *py3eval()* Evaluate Python expression {expr} and return its result converted to Vim data structures. If a {locals} |Dictionary| is given, it defines set of local @@ -8153,7 +8153,7 @@ py3eval({expr}[, {locals}]) *py3eval()* {only available when compiled with the |+python3| feature} *E858* *E859* -pyeval({expr}[, {locals}]) *pyeval()* +pyeval({expr} [, {locals}]) *pyeval()* Evaluate Python expression {expr} and return its result converted to Vim data structures. For {locals} see |py3eval()|. @@ -8172,7 +8172,7 @@ pyeval({expr}[, {locals}]) *pyeval()* {only available when compiled with the |+python| feature} -pyxeval({expr}[, {locals}]) *pyxeval()* +pyxeval({expr} [, {locals}]) *pyxeval()* Evaluate Python expression {expr} and return its result converted to Vim data structures. For {locals} see |py3eval()|. diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index 37f0a181d1..48f192a7b8 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1,4 +1,4 @@ -*quickfix.txt* For Vim version 9.1. Last change: 2024 Nov 07 +*quickfix.txt* For Vim version 9.1. Last change: 2024 Nov 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -361,7 +361,7 @@ processing a quickfix or location list command, it will be aborted. Example: > :g/mypattern/caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".") < - *:lad* *:addd* *:laddexpr* + *:lad* *:ladd* *:laddexpr* :lad[dexpr] {expr} Same as ":caddexpr", except the location list for the current window is used instead of the quickfix list. diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index eff99f7638..b0c77db1d4 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1,4 +1,4 @@ -*syntax.txt* For Vim version 9.1. Last change: 2024 Nov 09 +*syntax.txt* For Vim version 9.1. Last change: 2024 Nov 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2670,7 +2670,7 @@ To specify elements that should not be concealed, set the following variable: > :let g:pandoc#syntax#conceal#blacklist = [] -This is a list of the rules wich can be used here: +This is a list of the rules which can be used here: - titleblock - image diff --git a/runtime/doc/tags b/runtime/doc/tags index 6e5085a0d8..3039737f54 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -2216,7 +2216,6 @@ $quote eval.txt /*$quote* :abo windows.txt /*:abo* :aboveleft windows.txt /*:aboveleft* :abstract vim9class.txt /*:abstract* -:addd quickfix.txt /*:addd* :al windows.txt /*:al* :all windows.txt /*:all* :am gui.txt /*:am* @@ -2736,6 +2735,7 @@ $quote eval.txt /*$quote* :lab quickfix.txt /*:lab* :labove quickfix.txt /*:labove* :lad quickfix.txt /*:lad* +:ladd quickfix.txt /*:ladd* :laddb quickfix.txt /*:laddb* :laddbuffer quickfix.txt /*:laddbuffer* :laddexpr quickfix.txt /*:laddexpr* diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 462232f728..e1e6c4ee7c 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -2743,7 +2743,7 @@ do_ecmd( } if (buf == NULL) goto theend; - // autocommands try to edit a file that is goind to be removed, + // autocommands try to edit a file that is going to be removed, // abort if (buf_locked(buf)) { diff --git a/src/po/Make_mvc.mak b/src/po/Make_mvc.mak index f567d88f8b..de0339743b 100644 --- a/src/po/Make_mvc.mak +++ b/src/po/Make_mvc.mak @@ -38,7 +38,7 @@ VIMRUNTIME = ..\..\runtime !ENDIF PACKAGE = vim -# Correct the following line for the where executeable file vim is +# Correct the following line for the where executable file vim is # installed. Please do not put the path in quotes. !IFNDEF VIMPROG VIMPROG = ..\vim.exe diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim index a654b6dda0..bed795e1cc 100644 --- a/src/testdir/test_diffmode.vim +++ b/src/testdir/test_diffmode.vim @@ -2258,7 +2258,7 @@ func Test_diff_overlapped_diff_blocks_will_be_merged() call StopVimInTerminal(buf) endfunc -" switching windows in diff mode caused an unneccessary scroll +" switching windows in diff mode caused an unnecessary scroll func Test_diff_topline_noscroll() CheckScreendump diff --git a/src/version.c b/src/version.c index 2839e89808..7906b07e00 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 */ +/**/ + 849, /**/ 848, /**/ From 7724d621f21ff6599ba49f11401ddb45ff321099 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sun, 10 Nov 2024 20:36:28 +0100 Subject: [PATCH 061/106] runtime(vim): Fix indent after :silent! function See https://github.com/vim/vim/commit/35699f17497dcdcfdd747fedaef28f208ac6eb5f#commitcomment-148816912 closes: #16009 Signed-off-by: Doug Kearns Signed-off-by: Christian Brabandt --- runtime/autoload/dist/vimindent.vim | 7 ++++--- runtime/indent/testdir/vim.in | 9 +++++++++ runtime/indent/testdir/vim.ok | 9 +++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/runtime/autoload/dist/vimindent.vim b/runtime/autoload/dist/vimindent.vim index 07b21538e1..727e98352c 100644 --- a/runtime/autoload/dist/vimindent.vim +++ b/runtime/autoload/dist/vimindent.vim @@ -2,10 +2,11 @@ vim9script # Language: Vim script # Maintainer: github user lacygoill -# Last Change: 2023 Jun 29 +# Last Change: 2024 Nov 08 # -# Includes Changes from Vim: +# Includes changes from The Vim Project: # - 2024 Feb 09: Fix indent after literal Dict (A. Radev via #13966) +# - 2024 Nov 08: Fix indent after :silent! function (D. Kearns via #16009) # NOTE: Whenever you change the code, make sure the tests are still passing: # @@ -295,7 +296,7 @@ patterns = [] endfor } -const STARTS_NAMED_BLOCK: string = $'^\s*\%(sil\%[ent]\s\+\)\=\%({patterns->join('\|')}\)\>\%(\s\|$\|!\)\@=' +const STARTS_NAMED_BLOCK: string = $'^\s*\%(sil\%[ent]!\=\s\+\)\=\%({patterns->join('\|')}\)\>\%(\s\|$\|!\)\@=' # STARTS_CURLY_BLOCK {{{3 diff --git a/runtime/indent/testdir/vim.in b/runtime/indent/testdir/vim.in index 1ff2d0d000..a3c8c920bf 100644 --- a/runtime/indent/testdir/vim.in +++ b/runtime/indent/testdir/vim.in @@ -951,3 +951,12 @@ endenum call prop_type_add('indent_after_literal_dict', #{ foo: 'bar' }) call prop_type_delete('indent_after_literal_dict') " END_INDENT + +" START_INDENT +silent function Foo() +return 42 +endfunction +silent! function Bar() +return 42 +endfunction +" END_INDENT diff --git a/runtime/indent/testdir/vim.ok b/runtime/indent/testdir/vim.ok index fa8869b61f..56f3d98ba0 100644 --- a/runtime/indent/testdir/vim.ok +++ b/runtime/indent/testdir/vim.ok @@ -951,3 +951,12 @@ endenum call prop_type_add('indent_after_literal_dict', #{ foo: 'bar' }) call prop_type_delete('indent_after_literal_dict') " END_INDENT + +" START_INDENT +silent function Foo() + return 42 +endfunction +silent! function Bar() + return 42 +endfunction +" END_INDENT From 622f6f5b9a9c2b88423f31a98e99cd3324446fcf Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Mon, 11 Nov 2024 08:49:04 +0100 Subject: [PATCH 062/106] runtime(tex): extra Number highlighting causes issues So let's revert "runtime(tex): add Number highlighting to syntax file" This (partly) reverts commits 8e6b5034f32049fd0 and 6065755a39d838aab fixes: #16030 Signed-off-by: Christian Brabandt --- runtime/syntax/tex.vim | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim index bd47e168d7..77a40e11d3 100644 --- a/runtime/syntax/tex.vim +++ b/runtime/syntax/tex.vim @@ -4,7 +4,6 @@ " Former Maintainer: Charles E. Campbell " Last Change: Apr 22, 2022 " 2024 Feb 19 by Vim Project (announce adoption) -" 2024 Nov 09 add Number highlight (#11271) " Version: 121 " Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX " @@ -163,7 +162,7 @@ endif " Clusters: {{{1 " -------- -syn cluster texCmdGroup contains=texCmdBody,texComment,texDefParm,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathOper,texMathNumber,texNewCmd,texNewEnv,texRefZone,texSection,texBeginEnd,texBeginEndName,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,@texMathZones +syn cluster texCmdGroup contains=texCmdBody,texComment,texDefParm,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathOper,texNewCmd,texNewEnv,texRefZone,texSection,texBeginEnd,texBeginEndName,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,@texMathZones if !s:tex_no_error syn cluster texCmdGroup add=texMathError endif @@ -203,8 +202,8 @@ if !exists("g:tex_no_math") syn cluster texMathZones contains=texMathZoneV,texMathZoneW,texMathZoneX,texMathZoneY,texMathZoneZ syn cluster texMatchGroup add=@texMathZones syn cluster texMathDelimGroup contains=texMathDelimBad,texMathDelimKey,texMathDelimSet1,texMathDelimSet2 - syn cluster texMathMatchGroup contains=@texMathZones,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathMatcher,texMathOper,texMathNumber,texNewCmd,texNewEnv,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone - syn cluster texMathZoneGroup contains=texBadPar,texComment,texDelimiter,texLength,texMathDelim,texMathMatcher,texMathOper,texMathNumber,texMathSymbol,texMathText,texRefZone,texSpecialChar,texStatement,texTypeSize,texTypeStyle + syn cluster texMathMatchGroup contains=@texMathZones,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathMatcher,texMathOper,texNewCmd,texNewEnv,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone + syn cluster texMathZoneGroup contains=texBadPar,texComment,texDelimiter,texLength,texMathDelim,texMathMatcher,texMathOper,texMathSymbol,texMathText,texRefZone,texSpecialChar,texStatement,texTypeSize,texTypeStyle if !s:tex_no_error syn cluster texMathMatchGroup add=texMathError syn cluster texMathZoneGroup add=texMathError @@ -503,7 +502,6 @@ if !exists("g:tex_no_math") endif syn match texMathOper "[_^=]" contained - syn match texMathNumber "\<\d\|\.\d" contained " Text Inside Math Zones: {{{2 if s:tex_fast =~# 'M' @@ -1332,7 +1330,6 @@ if !exists("skip_tex_syntax_inits") hi def link texMath Special hi def link texMathDelim Statement hi def link texMathOper Operator - hi def link texMathNumber Number hi def link texNewCmd Statement hi def link texNewEnv Statement hi def link texOption Number From 56d45f1b6658ca64857b4cb22f18a18eeefa0f1d Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Mon, 11 Nov 2024 19:58:55 +0100 Subject: [PATCH 063/106] patch 9.1.0850: Vim9: cannot access nested object inside objects Problem: Vim9: cannot access nested object inside objects (lifepillar, 91khr, mawkish) Solution: Add support for accessing an object member using a "any" variable type (Yegappan Lakshmanan) fixes: #11822 fixes: #12024 fixes: #12196 fixes: #12198 closes: #16029 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- runtime/doc/tags | 1 + runtime/doc/vim9class.txt | 29 ++- src/proto/vim9class.pro | 2 + src/testdir/test_vim9_class.vim | 337 +++++++++++++++++++++++++++++++- src/version.c | 2 + src/vim9class.c | 54 +++-- src/vim9execute.c | 142 +++++++++++--- 7 files changed, 522 insertions(+), 45 deletions(-) diff --git a/runtime/doc/tags b/runtime/doc/tags index 3039737f54..d38c8958e8 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -9282,6 +9282,7 @@ o_CTRL-V motion.txt /*o_CTRL-V* o_V motion.txt /*o_V* o_object-select motion.txt /*o_object-select* o_v motion.txt /*o_v* +obj-var-type-any vim9class.txt /*obj-var-type-any* object vim9class.txt /*object* object-const-variable vim9class.txt /*object-const-variable* object-empty() vim9class.txt /*object-empty()* diff --git a/runtime/doc/vim9class.txt b/runtime/doc/vim9class.txt index ef96aa9076..a06c2c6e08 100644 --- a/runtime/doc/vim9class.txt +++ b/runtime/doc/vim9class.txt @@ -1,4 +1,4 @@ -*vim9class.txt* For Vim version 9.1. Last change: 2024 Apr 13 +*vim9class.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -873,6 +873,33 @@ Note that the method name must start with "new". If there is no method called "new()" then the default constructor is added, even though there are other constructor methods. +Using variable type "any" for an Object~ + *obj-var-type-any* +You can use a variable declared with type "any" to hold an object. e.g. +> + vim9script + class A + var n = 10 + def Get(): number + return this.n + enddef + endclass + + def Fn(o: any) + echo o.n + echo o.Get() + enddef + + var a = A.new() + Fn(a) +< +In this example, Vim cannot determine the type of the parameter "o" for +function Fn() at compile time. It can be either a |Dict| or an |Object| +value. Therefore, at runtime, when the type is known, the object member +variable and method are looked up. This process is not efficient, so it is +recommended to use a more specific type whenever possible for better +efficiency. + Compiling methods in a Class ~ *class-compile* The |:defcompile| command can be used to compile all the class and object diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro index 7d11523cef..d59caa0673 100644 --- a/src/proto/vim9class.pro +++ b/src/proto/vim9class.pro @@ -9,6 +9,8 @@ type_T *oc_member_type_by_idx(class_T *cl, int is_object, int member_idx); void ex_enum(exarg_T *eap); void typealias_unref(typealias_T *ta); void ex_type(exarg_T *eap); +int get_member_tv(class_T *cl, int is_object, char_u *name, size_t namelen, class_T *current_class, typval_T *rettv); +int obj_method_to_partial_tv(object_T *obj, ufunc_T *obj_method, typval_T *rettv); int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose); ufunc_T *find_class_func(char_u **arg); int class_member_idx(class_T *cl, char_u *name, size_t namelen); diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index 8791a5218d..4ce9fcdc49 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -784,7 +784,7 @@ def Test_member_any_used_as_object() vim9script class Inner - var value: number = 0 + public var value: number = 0 endclass class Outer @@ -11213,4 +11213,339 @@ def Test_class_cast() v9.CheckScriptSuccess(lines) enddef +" Test for using a variable of type "any" with an object +def Test_any_obj_var_type() + var lines =<< trim END + vim9script + class A + var name: string = "foobar" + def Foo(): string + return "func foo" + enddef + endclass + + def CheckVals(x: any) + assert_equal("foobar", x.name) + assert_equal("func foo", x.Foo()) + enddef + + var a = A.new() + CheckVals(a) + END + v9.CheckScriptSuccess(lines) + + # Try to set a non-existing variable + lines =<< trim END + vim9script + class A + var name: string = "foobar" + endclass + + def SetNonExistingVar(x: any) + x.bar = [1, 2, 3] + enddef + + var a = A.new() + SetNonExistingVar(a) + END + v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1) + + # Try to read a non-existing variable + lines =<< trim END + vim9script + class A + var name: string = "foobar" + endclass + + def GetNonExistingVar(x: any) + var i: dict = x.bar + enddef + + var a = A.new() + GetNonExistingVar(a) + END + v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1) + + # Try to invoke a non-existing method + lines =<< trim END + vim9script + class A + def Foo(): number + return 10 + enddef + endclass + + def CallNonExistingMethod(x: any) + var i: number = x.Bar() + enddef + + var a = A.new() + CallNonExistingMethod(a) + END + v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1) + + # Use an object which is a Dict value + lines =<< trim END + vim9script + class Foo + def Bar(): number + return 369 + enddef + endclass + + def GetValue(FooDict: dict): number + var n: number = 0 + for foo in values(FooDict) + n += foo.Bar() + endfor + return n + enddef + + var d = {'x': Foo.new()} + assert_equal(369, GetValue(d)) + END + v9.CheckScriptSuccess(lines) + + # Nested data. Object containg a Dict containing another Object. + lines =<< trim END + vim9script + class Context + public var state: dict = {} + endclass + + class Metadata + public var value = 0 + endclass + + var ctx = Context.new() + ctx.state["meta"] = Metadata.new(2468) + + const foo = ctx.state.meta.value + + def F(): number + const bar = ctx.state.meta.value + return bar + enddef + + assert_equal(2468, F()) + END + v9.CheckScriptSuccess(lines) + + # Accessing an object from a method inside the class using any type + lines =<< trim END + vim9script + class C + def _G(): string + return '_G' + enddef + static def S(o_any: any): string + return o_any._G() + enddef + endclass + + var o1 = C.new() + assert_equal('_G', C.S(o1)) + END + v9.CheckScriptSuccess(lines) + + # Modifying an object private variable from a method in another class using + # any type + lines =<< trim END + vim9script + + class A + var num = 10 + endclass + + class B + def SetVal(x: any) + x.num = 20 + enddef + endclass + + var a = A.new() + var b = B.new() + b.SetVal(a) + END + v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1) + + # Accessing a object protected variable from a method in another class using + # any type + lines =<< trim END + vim9script + + class A + var _num = 10 + endclass + + class B + def GetVal(x: any): number + return x._num + enddef + endclass + + var a = A.new() + var b = B.new() + var i = b.GetVal(a) + END + v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1) + + # Accessing an object returned from an imported function and class + lines =<< trim END + vim9script + export class Foo + public var name: string + endclass + + export def ReturnFooObject(): Foo + var r = Foo.new('star') + return r + enddef + END + writefile(lines, 'Xanyvar1.vim', 'D') + + lines =<< trim END + vim9script + + import './Xanyvar1.vim' + + def GetName(): string + var whatever = Xanyvar1.ReturnFooObject() + return whatever.name + enddef + + assert_equal('star', GetName()) + END + v9.CheckScriptSuccess(lines) + + # Try to modify a private object variable using a variable of type "any" + lines =<< trim END + vim9script + + class Foo + var n: number = 10 + endclass + def Fn(x: any) + x.n = 20 + enddef + var a = Foo.new() + Fn(a) + END + v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1) + + # Try to read a protected object variable using a variable of type "any" + lines =<< trim END + vim9script + + class Foo + var _n: number = 10 + endclass + def Fn(x: any): number + return x._n + enddef + + var a = Foo.new() + Fn(a) + END + v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1) + + # Read a protected object variable using a variable of type "any" in an object + # method + lines =<< trim END + vim9script + + class Foo + var _n: number = 10 + def Fn(x: any): number + return x._n + enddef + endclass + + var a = Foo.new() + assert_equal(10, a.Fn(a)) + END + v9.CheckScriptSuccess(lines) + + # Try to call a protected object method using a "any" type variable + lines =<< trim END + vim9script + + class Foo + def _GetVal(): number + return 234 + enddef + endclass + def Fn(x: any): number + return x._GetVal() + enddef + + var a = Foo.new() + Fn(a) + END + v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1) + + # Call a protected object method using a "any" type variable from another + # object method + lines =<< trim END + vim9script + + class Foo + def _GetVal(): number + return 234 + enddef + def FooVal(x: any): number + return x._GetVal() + enddef + endclass + + var a = Foo.new() + assert_equal(234, a.FooVal(a)) + END + v9.CheckScriptSuccess(lines) + + # Method chaining + lines =<< trim END + vim9script + + export class T + var id: number = 268 + def F(): any + return this + enddef + endclass + + def H() + var a = T.new().F().F() + assert_equal(268, a.id) + enddef + H() + + var b: T = T.new().F().F() + assert_equal(268, b.id) + END + v9.CheckScriptSuccess(lines) + + # Using a null object to access a member variable + lines =<< trim END + vim9script + def Fn(x: any): number + return x.num + enddef + + Fn(null_object) + END + v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1) + + # Using a null object to invoke a method + lines =<< trim END + vim9script + def Fn(x: any) + x.Foo() + enddef + + Fn(null_object) + END + v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 7906b07e00..636dfaa12e 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 */ +/**/ + 850, /**/ 849, /**/ diff --git a/src/vim9class.c b/src/vim9class.c index 87b4d45ea5..d0ddcb8209 100644 --- a/src/vim9class.c +++ b/src/vim9class.c @@ -2777,12 +2777,13 @@ ex_type(exarg_T *eap) * "rettv". If "is_object" is TRUE, then the object member variable table is * searched. Otherwise the class member variable table is searched. */ - static int + int get_member_tv( class_T *cl, int is_object, char_u *name, size_t namelen, + class_T *current_class, typval_T *rettv) { ocmember_T *m; @@ -2793,7 +2794,8 @@ get_member_tv( if (m == NULL) return FAIL; - if (*name == '_') + if (*name == '_' && (current_class == NULL || + !class_instance_of(current_class, cl))) { emsg_var_cl_define(e_cannot_access_protected_variable_str, m->ocm_name, 0, cl); @@ -2873,7 +2875,7 @@ call_oc_method( if (ocm == NULL && *fp->uf_name == '_') { - // Cannot access a private method outside of a class + // Cannot access a protected method outside of a class semsg(_(e_cannot_access_protected_method_str), fp->uf_name); return FAIL; } @@ -2916,6 +2918,33 @@ call_oc_method( return OK; } +/* + * Create a partial typval for "obj.obj_method" and store it in "rettv". + * Returns OK on success and FAIL on memory allocation failure. + */ + int +obj_method_to_partial_tv(object_T *obj, ufunc_T *obj_method, typval_T *rettv) +{ + partial_T *pt = ALLOC_CLEAR_ONE(partial_T); + if (pt == NULL) + return FAIL; + + pt->pt_refcount = 1; + if (obj != NULL) + { + pt->pt_obj = obj; + ++pt->pt_obj->obj_refcount; + } + pt->pt_auto = TRUE; + pt->pt_func = obj_method; + func_ptr_ref(pt->pt_func); + + rettv->v_type = VAR_PARTIAL; + rettv->vval.v_partial = pt; + + return OK; +} + /* * Evaluate what comes after a class: * - class member: SomeClass.varname @@ -2978,7 +3007,7 @@ class_object_index( // Search in the object member variable table and the class member // variable table. int is_object = rettv->v_type == VAR_OBJECT; - if (get_member_tv(cl, is_object, name, len, rettv) == OK) + if (get_member_tv(cl, is_object, name, len, NULL, rettv) == OK) { *arg = name_end; return OK; @@ -2989,28 +3018,17 @@ class_object_index( ufunc_T *fp = method_lookup(cl, rettv->v_type, name, len, &fidx); if (fp != NULL) { - // Private methods are not accessible outside the class + // Protected methods are not accessible outside the class if (*name == '_') { semsg(_(e_cannot_access_protected_method_str), fp->uf_name); return FAIL; } - partial_T *pt = ALLOC_CLEAR_ONE(partial_T); - if (pt == NULL) + if (obj_method_to_partial_tv(is_object ? rettv->vval.v_object : + NULL, fp, rettv) == FAIL) return FAIL; - pt->pt_refcount = 1; - if (is_object) - { - pt->pt_obj = rettv->vval.v_object; - ++pt->pt_obj->obj_refcount; - } - pt->pt_auto = TRUE; - pt->pt_func = fp; - func_ptr_ref(pt->pt_func); - rettv->v_type = VAR_PARTIAL; - rettv->vval.v_partial = pt; *arg = name_end; return OK; } diff --git a/src/vim9execute.c b/src/vim9execute.c index f523e27b89..da03d5e7d4 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2268,15 +2268,23 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) ocmember_T *m = object_member_lookup(cl, member, 0, &m_idx); if (m != NULL) { - if (*member == '_') + // Get the current function + ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data) + + ectx->ec_dfunc_idx)->df_ufunc; + + // Check whether the member variable is writeable + if ((m->ocm_access != VIM_ACCESS_ALL) && + (ufunc->uf_class == NULL || + !class_instance_of(ufunc->uf_class, cl))) { - emsg_var_cl_define( - e_cannot_access_protected_variable_str, - m->ocm_name, 0, cl); + char *msg = (m->ocm_access == VIM_ACCESS_PRIVATE) + ? e_cannot_access_protected_variable_str + : e_variable_is_not_writable_str; + emsg_var_cl_define(msg, m->ocm_name, 0, cl); status = FAIL; } - - lidx = m_idx; + else + lidx = m_idx; } else { @@ -3119,6 +3127,73 @@ object_required_error(typval_T *tv) clear_type_list(&type_list); } +/* + * Accessing the member of an object stored in a variable of type "any". + * Returns OK if the member variable is present. + * Returns FAIL if the variable is not found. + */ + static int +any_var_get_obj_member(class_T *current_class, isn_T *iptr, typval_T *tv) +{ + object_T *obj = tv->vval.v_object; + typval_T mtv; + + if (obj == NULL) + { + SOURCING_LNUM = iptr->isn_lnum; + emsg(_(e_using_null_object)); + return FAIL; + } + + // get_member_tv() needs the object information in the typval argument. + // So set the object information. + copy_tv(tv, &mtv); + + // 'name' can either be a object variable or a object method + int namelen = STRLEN(iptr->isn_arg.string); + int save_did_emsg = did_emsg; + + if (get_member_tv(obj->obj_class, TRUE, iptr->isn_arg.string, namelen, + current_class, &mtv) == OK) + { + copy_tv(&mtv, tv); + clear_tv(&mtv); + return OK; + } + + if (did_emsg != save_did_emsg) + return FAIL; + + // could be a member function + ufunc_T *obj_method; + int obj_method_idx; + + obj_method = method_lookup(obj->obj_class, VAR_OBJECT, + iptr->isn_arg.string, namelen, + &obj_method_idx); + if (obj_method == NULL) + { + SOURCING_LNUM = iptr->isn_lnum; + semsg(_(e_variable_not_found_on_object_str_str), iptr->isn_arg.string, + obj->obj_class->class_name); + return FAIL; + } + + // Protected methods are not accessible outside the class + if (*obj_method->uf_name == '_' + && !class_instance_of(current_class, obj->obj_class)) + { + semsg(_(e_cannot_access_protected_method_str), obj_method->uf_name); + return FAIL; + } + + // Create a partial for the member function + if (obj_method_to_partial_tv(obj, obj_method, tv) == FAIL) + return FAIL; + + return OK; +} + /* * Execute instructions in execution context "ectx". * Return OK or FAIL; @@ -5482,6 +5557,7 @@ exec_instructions(ectx_T *ectx) } break; + // dict member with string key (dict['member']) case ISN_MEMBER: { dict_T *dict; @@ -5526,35 +5602,51 @@ exec_instructions(ectx_T *ectx) } break; - // dict member with string key + // dict member with string key (dict.member) + // or can be an object case ISN_STRINGMEMBER: { dict_T *dict; dictitem_T *di; tv = STACK_TV_BOT(-1); - if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) - { - SOURCING_LNUM = iptr->isn_lnum; - emsg(_(e_dictionary_required)); - goto on_error; - } - dict = tv->vval.v_dict; - if ((di = dict_find(dict, iptr->isn_arg.string, -1)) - == NULL) + if (tv->v_type == VAR_OBJECT) { - SOURCING_LNUM = iptr->isn_lnum; - semsg(_(e_key_not_present_in_dictionary_str), - iptr->isn_arg.string); - goto on_error; + if (dict_stack_save(tv) == FAIL) + goto on_fatal_error; + + ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data) + + ectx->ec_dfunc_idx)->df_ufunc; + // Class object (not a Dict) + if (any_var_get_obj_member(ufunc->uf_class, iptr, tv) == FAIL) + goto on_error; } - // Put the dict used on the dict stack, it might be used by - // a dict function later. - if (dict_stack_save(tv) == FAIL) - goto on_fatal_error; + else + { + if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) + { + SOURCING_LNUM = iptr->isn_lnum; + emsg(_(e_dictionary_required)); + goto on_error; + } + dict = tv->vval.v_dict; - copy_tv(&di->di_tv, tv); + if ((di = dict_find(dict, iptr->isn_arg.string, -1)) + == NULL) + { + SOURCING_LNUM = iptr->isn_lnum; + semsg(_(e_key_not_present_in_dictionary_str), + iptr->isn_arg.string); + goto on_error; + } + // Put the dict used on the dict stack, it might be + // used by a dict function later. + if (dict_stack_save(tv) == FAIL) + goto on_fatal_error; + + copy_tv(&di->di_tv, tv); + } } break; From e7a1bbf2102ecd2083613ff18d7d46c45d1e568e Mon Sep 17 00:00:00 2001 From: John Marriott Date: Mon, 11 Nov 2024 20:40:33 +0100 Subject: [PATCH 064/106] patch 9.1.0851: too many strlen() calls in getchar.c Problem: too many strlen() calls in getchar.c Solution: refactor code and reduce strlen() calls (John Marriott) closes: #16017 Signed-off-by: John Marriott Signed-off-by: Christian Brabandt --- src/getchar.c | 101 ++++++++++++++++++++++++++++++-------------------- src/structs.h | 2 + src/version.c | 2 + 3 files changed, 65 insertions(+), 40 deletions(-) diff --git a/src/getchar.c b/src/getchar.c index 96e180f4ae..c1628ee5ad 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -36,9 +36,9 @@ #define MINIMAL_SIZE 20 // minimal size for b_str -static buffheader_T redobuff = {{NULL, {NUL}}, NULL, 0, 0}; -static buffheader_T old_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; -static buffheader_T recordbuff = {{NULL, {NUL}}, NULL, 0, 0}; +static buffheader_T redobuff = {{NULL, 0, {NUL}}, NULL, 0, 0, FALSE}; +static buffheader_T old_redobuff = {{NULL, 0, {NUL}}, NULL, 0, 0, FALSE}; +static buffheader_T recordbuff = {{NULL, 0, {NUL}}, NULL, 0, 0, FALSE}; static int typeahead_char = 0; // typeahead char that's not flushed @@ -129,17 +129,19 @@ free_buff(buffheader_T *buf) static char_u * get_buffcont( buffheader_T *buffer, - int dozero) // count == zero is not an error + int dozero, // count == zero is not an error + size_t *len) // the length of the returned buffer { long_u count = 0; char_u *p = NULL; char_u *p2; char_u *str; buffblock_T *bp; + size_t i = 0; // compute the total length of the string for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next) - count += (long_u)STRLEN(bp->b_str); + count += (long_u)bp->b_strlen; if ((count > 0 || dozero) && (p = alloc(count + 1)) != NULL) { @@ -148,7 +150,12 @@ get_buffcont( for (str = bp->b_str; *str; ) *p2++ = *str++; *p2 = NUL; + i = (size_t)(p2 - p); } + + if (len != NULL) + *len = i; + return p; } @@ -163,14 +170,13 @@ get_recorded(void) char_u *p; size_t len; - p = get_buffcont(&recordbuff, TRUE); + p = get_buffcont(&recordbuff, TRUE, &len); free_buff(&recordbuff); /* * Remove the characters that were added the last time, these must be the * (possibly mapped) characters that stopped the recording. */ - len = STRLEN(p); if (len >= last_recorded_len) { len -= last_recorded_len; @@ -194,7 +200,7 @@ get_recorded(void) char_u * get_inserted(void) { - return get_buffcont(&redobuff, FALSE); + return get_buffcont(&redobuff, FALSE, NULL); } /* @@ -207,9 +213,6 @@ add_buff( char_u *s, long slen) // length of "s" or -1 { - buffblock_T *p; - long_u len; - if (slen < 0) slen = (long)STRLEN(s); if (slen == 0) // don't add empty strings @@ -217,8 +220,8 @@ add_buff( if (buf->bh_first.b_next == NULL) // first add to list { - buf->bh_space = 0; buf->bh_curr = &(buf->bh_first); + buf->bh_create_newblock = TRUE; } else if (buf->bh_curr == NULL) // buffer has already been read { @@ -226,19 +229,26 @@ add_buff( return; } else if (buf->bh_index != 0) + { mch_memmove(buf->bh_first.b_next->b_str, buf->bh_first.b_next->b_str + buf->bh_index, - STRLEN(buf->bh_first.b_next->b_str + buf->bh_index) + 1); + (buf->bh_first.b_next->b_strlen - buf->bh_index) + 1); + buf->bh_first.b_next->b_strlen -= buf->bh_index; + buf->bh_space += buf->bh_index; + } buf->bh_index = 0; - if (buf->bh_space >= (int)slen) + if (!buf->bh_create_newblock && buf->bh_space >= (int)slen) { - len = (long_u)STRLEN(buf->bh_curr->b_str); - vim_strncpy(buf->bh_curr->b_str + len, s, (size_t)slen); + vim_strncpy(buf->bh_curr->b_str + buf->bh_curr->b_strlen, s, (size_t)slen); + buf->bh_curr->b_strlen += slen; buf->bh_space -= slen; } else { + long_u len; + buffblock_T *p; + if (slen < MINIMAL_SIZE) len = MINIMAL_SIZE; else @@ -246,8 +256,10 @@ add_buff( p = alloc(offsetof(buffblock_T, b_str) + len + 1); if (p == NULL) return; // no space, just forget it - buf->bh_space = (int)(len - slen); vim_strncpy(p->b_str, s, (size_t)slen); + p->b_strlen = slen; + buf->bh_space = (int)(len - slen); + buf->bh_create_newblock = FALSE; p->b_next = buf->bh_curr->b_next; buf->bh_curr->b_next = p; @@ -262,15 +274,13 @@ add_buff( static void delete_buff_tail(buffheader_T *buf, int slen) { - int len; - if (buf->bh_curr == NULL) return; // nothing to delete - len = (int)STRLEN(buf->bh_curr->b_str); - if (len < slen) + if (buf->bh_curr->b_strlen < (size_t)slen) return; - buf->bh_curr->b_str[len - slen] = NUL; + buf->bh_curr->b_str[buf->bh_curr->b_strlen - (size_t)slen] = NUL; + buf->bh_curr->b_strlen -= slen; buf->bh_space += slen; } @@ -281,9 +291,10 @@ delete_buff_tail(buffheader_T *buf, int slen) add_num_buff(buffheader_T *buf, long n) { char_u number[32]; + int numberlen; - sprintf((char *)number, "%ld", n); - add_buff(buf, number, -1L); + numberlen = vim_snprintf((char *)number, sizeof(number), "%ld", n); + add_buff(buf, number, (long)numberlen); } /* @@ -297,6 +308,7 @@ add_char_buff(buffheader_T *buf, int c) int len; int i; char_u temp[4]; + long templen; if (IS_SPECIAL(c)) len = 1; @@ -314,6 +326,7 @@ add_char_buff(buffheader_T *buf, int c) temp[1] = K_SECOND(c); temp[2] = K_THIRD(c); temp[3] = NUL; + templen = 3; } #ifdef FEAT_GUI else if (c == CSI) @@ -323,22 +336,24 @@ add_char_buff(buffheader_T *buf, int c) temp[1] = KS_EXTRA; temp[2] = (int)KE_CSI; temp[3] = NUL; + templen = 3; } #endif else { temp[0] = c; temp[1] = NUL; + templen = 1; } - add_buff(buf, temp, -1L); + add_buff(buf, temp, templen); } } // First read ahead buffer. Used for translated commands. -static buffheader_T readbuf1 = {{NULL, {NUL}}, NULL, 0, 0}; +static buffheader_T readbuf1 = {{NULL, 0, {NUL}}, NULL, 0, 0, FALSE}; // Second read ahead buffer. Used for redo. -static buffheader_T readbuf2 = {{NULL, {NUL}}, NULL, 0, 0}; +static buffheader_T readbuf2 = {{NULL, 0, {NUL}}, NULL, 0, 0, FALSE}; /* * Get one byte from the read buffers. Use readbuf1 one first, use readbuf2 @@ -390,12 +405,12 @@ start_stuff(void) if (readbuf1.bh_first.b_next != NULL) { readbuf1.bh_curr = &(readbuf1.bh_first); - readbuf1.bh_space = 0; + readbuf1.bh_create_newblock = TRUE; // force a new block to be created (see add_buff()) } if (readbuf2.bh_first.b_next != NULL) { readbuf2.bh_curr = &(readbuf2.bh_first); - readbuf2.bh_space = 0; + readbuf2.bh_create_newblock = TRUE; // force a new block to be created (see add_buff()) } } @@ -529,6 +544,7 @@ CancelRedo(void) saveRedobuff(save_redo_T *save_redo) { char_u *s; + size_t slen; save_redo->sr_redobuff = redobuff; redobuff.bh_first.b_next = NULL; @@ -536,11 +552,11 @@ saveRedobuff(save_redo_T *save_redo) old_redobuff.bh_first.b_next = NULL; // Make a copy, so that ":normal ." in a function works. - s = get_buffcont(&save_redo->sr_redobuff, FALSE); + s = get_buffcont(&save_redo->sr_redobuff, FALSE, &slen); if (s == NULL) return; - add_buff(&redobuff, s, -1L); + add_buff(&redobuff, s, (long)slen); vim_free(s); } @@ -2219,13 +2235,15 @@ do_key_input_pre(int c) // character. Only use it when changed, otherwise continue with the // original character. char_u *v_char; + size_t v_charlen; v_char = get_vim_var_str(VV_CHAR); + v_charlen = STRLEN(v_char); // Convert special bytes when it is special string. - if (STRLEN(v_char) >= 3 && v_char[0] == K_SPECIAL) + if (v_charlen >= 3 && v_char[0] == K_SPECIAL) res = TERMCAP2KEY(v_char[1], v_char[2]); - else if (STRLEN(v_char) > 0) + else if (v_charlen > 0) res = PTR2CHAR(v_char); } @@ -2438,9 +2456,9 @@ getchar_common(typval_T *argvars, typval_T *rettv) i += (*mb_char2bytes)(n, temp + i); else temp[i++] = n; - temp[i++] = NUL; + temp[i] = NUL; rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave(temp); + rettv->vval.v_string = vim_strnsave(temp, i); if (is_mouse_key(n)) { @@ -2507,9 +2525,9 @@ f_getcharstr(typval_T *argvars, typval_T *rettv) else temp[i++] = n; } - temp[i++] = NUL; + temp[i] = NUL; rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave(temp); + rettv->vval.v_string = vim_strnsave(temp, i); } /* @@ -3256,7 +3274,7 @@ handle_mapping( buf[1] = KS_EXTRA; buf[2] = KE_IGNORE; buf[3] = NUL; - map_str = vim_strsave(buf); + map_str = vim_strnsave(buf, 3); if (State & MODE_CMDLINE) { // redraw the command below the error @@ -4265,6 +4283,7 @@ getcmdkeycmd( may_add_last_used_map_to_redobuff(void) { char_u buf[3 + 20]; + int buflen; int sid = -1; if (last_used_map != NULL) @@ -4279,8 +4298,10 @@ may_add_last_used_map_to_redobuff(void) buf[0] = K_SPECIAL; buf[1] = KS_EXTRA; buf[2] = KE_SID; - vim_snprintf((char *)buf + 3, 20, "%d;", sid); - add_buff(&redobuff, buf, -1L); + buflen = 3; + + buflen += vim_snprintf((char *)buf + 3, 20, "%d;", sid); + add_buff(&redobuff, buf, (long)buflen); } #endif diff --git a/src/structs.h b/src/structs.h index 66d57e02d8..19768e6580 100644 --- a/src/structs.h +++ b/src/structs.h @@ -573,6 +573,7 @@ typedef struct buffheader buffheader_T; struct buffblock { buffblock_T *b_next; // pointer to next buffblock + size_t b_strlen; // length of b_str, excluding the NUL char_u b_str[1]; // contents (actually longer) }; @@ -585,6 +586,7 @@ struct buffheader buffblock_T *bh_curr; // buffblock for appending int bh_index; // index for reading int bh_space; // space in bh_curr for appending + int bh_create_newblock; // create a new block? }; typedef struct diff --git a/src/version.c b/src/version.c index 636dfaa12e..665b30b0f6 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 */ +/**/ + 851, /**/ 850, /**/ From 45e0704d9670c10bfaf2bb408d6a5cd639d23835 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Mon, 11 Nov 2024 20:52:55 +0100 Subject: [PATCH 065/106] patch 9.1.0852: No warning when X11 registers are not available Problem: No warning when X11 registers are not available (delvh) Solution: Output W23 once when connection to X11 clipboard/selection is not possible, mention in the documentation, that register 0 will be used instead Vim silently uses the 0 register, when clipboard or selection register * or + are not available. This might be a bit unexpected for the user. So let's just warn once when this happens. fixes: #14768 closes: #16013 Signed-off-by: Christian Brabandt --- runtime/doc/gui.txt | 4 +++- runtime/doc/gui_x11.txt | 10 +++++++++- runtime/doc/tags | 1 + src/clipboard.c | 8 +++++--- src/message.c | 16 ++++++++++++++++ src/proto/message.pro | 1 + src/register.c | 15 ++++++++++++--- src/testdir/test_registers.vim | 12 ++++++++++++ src/version.c | 2 ++ 9 files changed, 61 insertions(+), 8 deletions(-) diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt index 071de9c4b1..4fdfc0f05a 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -1,4 +1,4 @@ -*gui.txt* For Vim version 9.1. Last change: 2024 Jul 17 +*gui.txt* For Vim version 9.1. Last change: 2024 Nov 07 VIM REFERENCE MANUAL by Bram Moolenaar @@ -474,6 +474,8 @@ When the "unnamed" string is included in the 'clipboard' option, the unnamed register is the same as the "* register. Thus you can yank to and paste the selection without prepending "* to commands. +See also |W23|. + ============================================================================== 5. Menus *menus* diff --git a/runtime/doc/gui_x11.txt b/runtime/doc/gui_x11.txt index dbd4b10843..0658bfab98 100644 --- a/runtime/doc/gui_x11.txt +++ b/runtime/doc/gui_x11.txt @@ -1,4 +1,4 @@ -*gui_x11.txt* For Vim version 9.1. Last change: 2024 Apr 22 +*gui_x11.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -708,6 +708,14 @@ Examples: (assuming the default option values) Note that the text in the "+ register remains available when making a Visual selection, which makes other text available in the "* register. That allows overwriting selected text. + + *W23* +When you are yanking into the "* or "+ register and Vim cannot establish a +connection to the X11 selection (or clipboard), it will use register 0 and +output a warning: + + Warning: Clipboard register not available, using register 0 ~ + *x11-cut-buffer* There are, by default, 8 cut-buffers: CUT_BUFFER0 to CUT_BUFFER7. Vim only uses CUT_BUFFER0, which is the one that xterm uses by default. diff --git a/runtime/doc/tags b/runtime/doc/tags index d38c8958e8..00d65eb12b 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -5818,6 +5818,7 @@ W19 autocmd.txt /*W19* W20 if_pyth.txt /*W20* W21 if_pyth.txt /*W21* W22 userfunc.txt /*W22* +W23 gui_x11.txt /*W23* WORD motion.txt /*WORD* WSL os_win32.txt /*WSL* WWW intro.txt /*WWW* diff --git a/src/clipboard.c b/src/clipboard.c index 6c8b60c2e7..75e0f4f320 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -2220,10 +2220,12 @@ adjust_clip_reg(int *rp) *rp = ((clip_unnamed_saved & CLIP_UNNAMED_PLUS) && clip_plus.available) ? '+' : '*'; } - if (!clip_star.available && *rp == '*') - *rp = 0; - if (!clip_plus.available && *rp == '+') + if ((!clip_star.available && *rp == '*') || + (!clip_plus.available && *rp == '+')) + { + msg_warn_missing_clipboard(); *rp = 0; + } } #endif // FEAT_CLIPBOARD diff --git a/src/message.c b/src/message.c index 03c7072a71..576d92268e 100644 --- a/src/message.c +++ b/src/message.c @@ -55,6 +55,9 @@ static int msg_hist_len = 0; static FILE *verbose_fd = NULL; static int verbose_did_open = FALSE; +static int did_warn_clipboard = FALSE; +static char *warn_clipboard = "W23: Clipboard register not available, using register 0"; + /* * When writing messages to the screen, there are many different situations. * A number of variables is used to remember the current state: @@ -4060,6 +4063,19 @@ msg_advance(int col) msg_putchar(' '); } +/* + * Warn about missing Clipboard Support + */ + void +msg_warn_missing_clipboard(void) +{ + if (!global_busy && !did_warn_clipboard) + { + msg(_(warn_clipboard)); + did_warn_clipboard = TRUE; + } +} + #if defined(FEAT_CON_DIALOG) || defined(PROTO) /* * Used for "confirm()" function, and the :confirm command prefix. diff --git a/src/proto/message.pro b/src/proto/message.pro index 6657a08ec3..54a0a77651 100644 --- a/src/proto/message.pro +++ b/src/proto/message.pro @@ -73,6 +73,7 @@ void give_warning(char_u *message, int hl); void give_warning_with_source(char_u *message, int hl, int with_source); void give_warning2(char_u *message, char_u *a1, int hl); void msg_advance(int col); +void msg_warn_missing_clipboard(void); int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd); int vim_dialog_yesno(int type, char_u *title, char_u *message, int dflt); int vim_dialog_yesnocancel(int type, char_u *title, char_u *message, int dflt); diff --git a/src/register.c b/src/register.c index 279c2140a6..c9bc752240 100644 --- a/src/register.c +++ b/src/register.c @@ -198,6 +198,13 @@ valid_yank_reg( #endif ) return TRUE; + // clipboard support not enabled in this build + else if (regname == '*' || regname == '+') + { + // Warn about missing clipboard support once + msg_warn_missing_clipboard(); + return FALSE; + } return FALSE; } @@ -1173,10 +1180,12 @@ op_yank(oparg_T *oap, int deleting, int mess) return OK; #ifdef FEAT_CLIPBOARD - if (!clip_star.available && oap->regname == '*') - oap->regname = 0; - else if (!clip_plus.available && oap->regname == '+') + if ((!clip_star.available && oap->regname == '*') || + (!clip_plus.available && oap->regname == '+')) + { oap->regname = 0; + msg_warn_missing_clipboard(); + } #endif if (!deleting) // op_delete() already set y_current diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim index b2261d4d6c..f2d38d8391 100644 --- a/src/testdir/test_registers.vim +++ b/src/testdir/test_registers.vim @@ -1045,4 +1045,16 @@ func Test_insert_small_delete_replace_mode() bwipe! endfunc +" Test for W23 when clipboard is not available +func Test_clipboard_regs_not_working() + CheckNotGui + if !has("clipboard") + new + call append(0, "text for clipboard test") + let mess = execute(':norm "*yiw') + call assert_match('W23', mess) + bw! + endif +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 665b30b0f6..ceb17ac42f 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 */ +/**/ + 852, /**/ 851, /**/ From 6fbf63de865001dedafc227465e651926cf6f6dc Mon Sep 17 00:00:00 2001 From: Jonathan Lopez Date: Mon, 11 Nov 2024 21:03:31 +0100 Subject: [PATCH 066/106] patch 9.1.0853: filetype: kubernetes config file not recognized Problem: filetype: kubernetes config file not recognized Solution: detect '/.kube/config' file as yaml filetype (Jonathan Lopez) closes: #11076 Signed-off-by: Jonathan Lopez Signed-off-by: Christian Brabandt --- runtime/filetype.vim | 1 + src/testdir/test_filetype.vim | 3 ++- src/version.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 6e9f0b222a..fbccf22991 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -2919,6 +2919,7 @@ au BufNewFile,BufRead *.y call dist#ft#FTy() " Yaml au BufNewFile,BufRead *.yaml,*.yml,*.eyaml setf yaml +au BufNewFile,BufRead */.kube/config setf yaml " Raml au BufNewFile,BufRead *.raml setf raml diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index cca619bfaa..09fc184ca6 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -885,7 +885,8 @@ def s:GetFilenameChecks(): dict> xsd: ['file.xsd'], xslt: ['file.xsl', 'file.xslt'], yacc: ['file.yy', 'file.yxx', 'file.y++'], - yaml: ['file.yaml', 'file.yml', 'file.eyaml', 'any/.bundle/config', '.clangd', '.clang-format', '.clang-tidy', 'file.mplstyle', 'matplotlibrc', 'yarn.lock'], + yaml: ['file.yaml', 'file.yml', 'file.eyaml', 'any/.bundle/config', '.clangd', '.clang-format', '.clang-tidy', 'file.mplstyle', 'matplotlibrc', 'yarn.lock', + '/home/user/.kube/config'], yang: ['file.yang'], yuck: ['file.yuck'], z8a: ['file.z8a'], diff --git a/src/version.c b/src/version.c index ceb17ac42f..4e5864f09f 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 */ +/**/ + 853, /**/ 852, /**/ From 1083cae7091f006249c1349d0575412d2ff6a7dc Mon Sep 17 00:00:00 2001 From: mikoto2000 Date: Mon, 11 Nov 2024 21:24:14 +0100 Subject: [PATCH 067/106] patch 9.1.0854: cannot get terminal cell size Problem: cannot get terminal cell size Solution: add getcellpixels() function to return xpixel * ypixel cell size on terminal Unix (mikoto2000) closes: #16004 Signed-off-by: mikoto2000 Signed-off-by: Christian Brabandt --- runtime/doc/builtin.txt | 12 ++++++- runtime/doc/tags | 1 + runtime/doc/usr_41.txt | 4 ++- runtime/doc/version9.txt | 3 +- src/evalfunc.c | 8 +++++ src/os_unix.c | 71 +++++++++++++++++++++++++++++++++++++-- src/os_unix.h | 6 ++++ src/proto/os_unix.pro | 2 ++ src/testdir/test_utf8.vim | 8 +++++ src/version.c | 2 ++ 10 files changed, 112 insertions(+), 5 deletions(-) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 67f447d7db..1c7814fe61 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 10 +*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -222,6 +222,7 @@ getbufline({buf}, {lnum} [, {end}]) getbufoneline({buf}, {lnum}) String line {lnum} of buffer {buf} getbufvar({buf}, {varname} [, {def}]) any variable {varname} in buffer {buf} +getcellpixels() List get character cell pixel size getcellwidths() List get character cell width overrides getchangelist([{buf}]) List list of change list items getchar([{expr}]) Number or String @@ -3786,6 +3787,15 @@ getbufvar({buf}, {varname} [, {def}]) *getbufvar()* Return type: any, depending on {varname} +getcellpixels() *getcellpixels()* + Returns a |List| of terminal cell pixel size. + List format is [xpixels, ypixels]. + Only works on Unix. For gVim and on other systems, + returns [-1, -1]. + + Return type: list + + getcellwidths() *getcellwidths()* Returns a |List| of cell widths of character ranges overridden by |setcellwidths()|. The format is equal to the argument of diff --git a/runtime/doc/tags b/runtime/doc/tags index 00d65eb12b..f7ca8d2e8d 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -7838,6 +7838,7 @@ getbufinfo() builtin.txt /*getbufinfo()* getbufline() builtin.txt /*getbufline()* getbufoneline() builtin.txt /*getbufoneline()* getbufvar() builtin.txt /*getbufvar()* +getcellpixels() builtin.txt /*getcellpixels()* getcellwidths() builtin.txt /*getcellwidths()* getchangelist() builtin.txt /*getchangelist()* getchar() builtin.txt /*getchar()* diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index af67429ece..36907d249c 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: 2024 Oct 05 +*usr_41.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM USER MANUAL - by Bram Moolenaar @@ -778,6 +778,7 @@ String manipulation: *string-functions* strdisplaywidth() size of string when displayed, deals with tabs setcellwidths() set character cell width overrides getcellwidths() get character cell width overrides + getcellpixels() get character cell pixel size reverse() reverse the order of characters in a string substitute() substitute a pattern match with a string submatch() get a specific match in ":s" and substitute() @@ -1394,6 +1395,7 @@ Various: *various-functions* did_filetype() check if a FileType autocommand was used diff() diff two Lists of strings eventhandler() check if invoked by an event handler + getcellpixels() get List of cell pixel size getpid() get process ID of Vim getscriptinfo() get list of sourced vim scripts getimstatus() check if IME status is active diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index daba9848c9..ac0700ed79 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2024 Nov 06 +*version9.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41621,6 +41621,7 @@ Functions: ~ |foreach()| apply function to List items |getcmdcomplpat()| Shell command line completion |getcmdprompt()| get prompt for input()/confirm() +|getcellpixels()| get List of terminal cell pixel size |getregion()| get a region of text from a buffer |getregionpos()| get a list of positions for a region |id()| get unique identifier for a Dict, List, Object, diff --git a/src/evalfunc.c b/src/evalfunc.c index 2d886682d5..04967efc32 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2077,6 +2077,14 @@ static funcentry_T global_functions[] = ret_string, f_getbufoneline}, {"getbufvar", 2, 3, FEARG_1, arg3_buffer_string_any, ret_any, f_getbufvar}, + {"getcellpixels", 0, 0, 0, NULL, + ret_list_any, +#if (defined(UNIX) || defined(VMS)) && (defined(FEAT_EVAL) || defined(PROTO)) + f_getcellpixels +#else + NULL +#endif + }, {"getcellwidths", 0, 0, 0, NULL, ret_list_any, f_getcellwidths}, {"getchangelist", 0, 1, FEARG_1, arg1_buffer, diff --git a/src/os_unix.c b/src/os_unix.c index 0aa6f3ca13..c69798d7d5 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4348,6 +4348,68 @@ mch_get_shellsize(void) return OK; } +#if defined(FEAT_EVAL) || defined(PROTO) + void +f_getcellpixels(typval_T *argvars UNUSED, typval_T *rettv) +{ + struct cellsize cs; + mch_calc_cell_size(&cs); + + if (rettv_list_alloc(rettv) == FAIL) + return; + + list_append_number(rettv->vval.v_list, (varnumber_T)cs.cs_xpixel); + list_append_number(rettv->vval.v_list, (varnumber_T)cs.cs_ypixel); +} +#endif + +/* + * Try to get the current terminal cell size. + * If faile get cell size, fallback 5x10 pixel. + */ + void +mch_calc_cell_size(struct cellsize *cs_out) +{ +#if defined(FEAT_GUI) + if (!gui.in_use) + { +#endif + // get current tty size. + struct winsize ws; + int fd = 1; + int retval = -1; + retval = ioctl(fd, TIOCGWINSZ, &ws); +# ifdef FEAT_EVAL + ch_log(NULL, "ioctl(TIOCGWINSZ) %s", retval == 0 ? "success" : "failed"); +# endif + if (retval == -1) + { + cs_out->cs_xpixel = -1; + cs_out->cs_ypixel = -1; + return; + } + + // calculate parent tty's pixel per cell. + int x_cell_size = ws.ws_xpixel / ws.ws_col; + int y_cell_size = ws.ws_ypixel / ws.ws_row; + + // calculate current tty's pixel + cs_out->cs_xpixel = x_cell_size; + cs_out->cs_ypixel = y_cell_size; + +# ifdef FEAT_EVAL + ch_log(NULL, "Got cell pixel size with TIOCGWINSZ: %d x %d", x_cell_size, y_cell_size); +# endif +#if defined(FEAT_GUI) + } + else + { + cs_out->cs_xpixel = -1; + cs_out->cs_ypixel = -1; + } +#endif +} + #if defined(FEAT_TERMINAL) || defined(PROTO) /* * Report the windows size "rows" and "cols" to tty "fd". @@ -4367,8 +4429,13 @@ mch_report_winsize(int fd, int rows, int cols) ws.ws_col = cols; ws.ws_row = rows; - ws.ws_xpixel = cols * 5; - ws.ws_ypixel = rows * 10; + + // calcurate and set tty pixel size + struct cellsize cs; + mch_calc_cell_size(&cs); + ws.ws_xpixel = cols * cs.cs_xpixel; + ws.ws_ypixel = rows * cs.cs_ypixel; + retval = ioctl(tty_fd, TIOCSWINSZ, &ws); ch_log(NULL, "ioctl(TIOCSWINSZ) %s", retval == 0 ? "success" : "failed"); # elif defined(TIOCSSIZE) diff --git a/src/os_unix.h b/src/os_unix.h index 99184abe6c..fac2c0fd99 100644 --- a/src/os_unix.h +++ b/src/os_unix.h @@ -488,3 +488,9 @@ int mch_rename(const char *src, const char *dest); // We have three kinds of ACL support. #define HAVE_ACL (HAVE_POSIX_ACL || HAVE_SOLARIS_ACL || HAVE_AIX_ACL) + +struct cellsize { + unsigned int cs_xpixel; + unsigned int cs_ypixel; +}; + diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro index d9dc8d9d54..be4942d291 100644 --- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -91,4 +91,6 @@ void xsmp_close(void); void stop_timeout(void); volatile sig_atomic_t *start_timeout(long msec); void delete_timer(void); +void f_getcellpixels(typval_T *argvars UNUSED, typval_T *rettv); +void mch_calc_cell_size(struct cellsize *cs_out); /* vim: set ft=c : */ diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim index 991a095380..d820e3517d 100644 --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -273,6 +273,14 @@ func Test_setcellwidths() bwipe! endfunc +" Pixel size of a cell is terminal-dependent, so in the test, only the list and size 2 are checked. +func Test_getcellpixels() + " Not yet Windows-compatible + CheckNotMSWindows + let cellpixels = getcellpixels() + call assert_equal(2, len(cellpixels)) +endfunc + func Test_getcellwidths() call setcellwidths([]) call assert_equal([], getcellwidths()) diff --git a/src/version.c b/src/version.c index 4e5864f09f..5337b1ad25 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 */ +/**/ + 854, /**/ 853, /**/ From feea1b444e8dabddc10f380ff61ef97f4ff6fa62 Mon Sep 17 00:00:00 2001 From: Luca Saccarola Date: Mon, 11 Nov 2024 21:33:50 +0100 Subject: [PATCH 068/106] Add an .editorconfig file to repository This commit tries to use an editorconfig file to ensure the same settings across editors while contributing to the vim repository. The rules are based of the guidelines defined in `runtime/doc/develop.txt`. Signed-off-by: Luca Saccarola Signed-off-by: Christian Brabandt --- .editorconfig | 21 +++++++++++++++++++++ Filelist | 1 + runtime/doc/develop.txt | 6 +++++- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..bda9fd2896 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# https://spec.editorconfig.org/#supported-pairs +root = true + +[*] +indent_style = tab +tab_width = 8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{c,h,proto}] +indent_size = 4 + +[*.{md,yml,sh,bat}] +# This will become the default after we migrate the codebase +indent_style = space +indent_size = 2 + +[*.md] +# Markdown uses trailing whitespaces to do an hard line break +# https://spec.commonmark.org/0.31.2/#hard-line-breaks +trim_trailing_whitespace = false diff --git a/Filelist b/Filelist index 96af57b439..1f899b5c77 100644 --- a/Filelist +++ b/Filelist @@ -18,6 +18,7 @@ SRC_ALL = \ .hgignore \ .appveyor.yml \ .codecov.yml \ + .editorconfig \ ci/appveyor.bat \ ci/config.mk*.sed \ ci/if_ver*.vim \ diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index dd8b94d91b..84aa53dc8c 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -1,4 +1,4 @@ -*develop.txt* For Vim version 9.1. Last change: 2024 Oct 31 +*develop.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -166,6 +166,10 @@ stick to these rules, to keep the sources readable and maintainable. This list is not complete. Look in the source code for more examples. +The code repository contains an editorconfig file, that can be used together +with the distributed editorconfig plugin |editorconfig-install| to ensure the +recommended style is followed. + MAKING CHANGES *style-changes* From 2e48567007f2becd484a3c3dd0706bf3a0beeae7 Mon Sep 17 00:00:00 2001 From: nwounkn Date: Mon, 11 Nov 2024 21:48:30 +0100 Subject: [PATCH 069/106] patch 9.1.0855: setting 'cmdheight' may cause hit-enter-prompt Problem: setting 'cmdheight' may cause hit-enter-prompt and echo output to be missing Solution: Before cleaning the cmdline, check the need_wait_return flag (nwounkn) closes: #13432 Signed-off-by: nwounkn Signed-off-by: Christian Brabandt --- src/testdir/dumps/Test_changing_cmdheight_7.dump | 8 ++++++++ src/testdir/test_cmdline.vim | 10 ++++++++++ src/version.c | 2 ++ src/window.c | 13 ++++++++----- 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 src/testdir/dumps/Test_changing_cmdheight_7.dump diff --git a/src/testdir/dumps/Test_changing_cmdheight_7.dump b/src/testdir/dumps/Test_changing_cmdheight_7.dump new file mode 100644 index 0000000000..a3ba88e48d --- /dev/null +++ b/src/testdir/dumps/Test_changing_cmdheight_7.dump @@ -0,0 +1,8 @@ +|~+0#4040ff13#ffffff0| @73 +|~| @73 +|~| @73 +|~| @73 +|[+3#0000000&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1 +|f+0&&|o@1| @71 +|b|a|r| @71 +|P+0#00e0003&|r|e|s@1| |E|N|T|E|R| |o|r| |t|y|p|e| |c|o|m@1|a|n|d| |t|o| |c|o|n|t|i|n|u|e> +0#0000000&@35 diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 30ded35b8d..110be65cd9 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -270,6 +270,12 @@ func Test_changing_cmdheight() let lines =<< trim END set cmdheight=1 laststatus=2 + func EchoOne() + set laststatus=2 cmdheight=1 + echo 'foo' + echo 'bar' + set cmdheight=2 + endfunc func EchoTwo() set laststatus=2 set cmdheight=5 @@ -305,6 +311,10 @@ func Test_changing_cmdheight() call term_sendkeys(buf, ":call EchoTwo()\") call VerifyScreenDump(buf, 'Test_changing_cmdheight_6', {}) + " increasing 'cmdheight' doesn't clear the messages that need hit-enter + call term_sendkeys(buf, ":call EchoOne()\") + call VerifyScreenDump(buf, 'Test_changing_cmdheight_7', {}) + " clean up call StopVimInTerminal(buf) endfunc diff --git a/src/version.c b/src/version.c index 5337b1ad25..22473eb55b 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 */ +/**/ + 855, /**/ 854, /**/ diff --git a/src/window.c b/src/window.c index 7c8f4fb366..f8a6907ec8 100644 --- a/src/window.c +++ b/src/window.c @@ -7343,11 +7343,14 @@ command_height(void) // Recompute window positions. (void)win_comp_pos(); - // clear the lines added to cmdline - if (full_screen) - screen_fill(cmdline_row, (int)Rows, 0, - (int)Columns, ' ', ' ', 0); - msg_row = cmdline_row; + if (!need_wait_return) + { + // clear the lines added to cmdline + if (full_screen) + screen_fill(cmdline_row, (int)Rows, 0, + (int)Columns, ' ', ' ', 0); + msg_row = cmdline_row; + } redraw_cmdline = TRUE; return; } From a1b654ff36a9d3a22d632d7eeaddb8224e621928 Mon Sep 17 00:00:00 2001 From: Yee Cheng Chin Date: Mon, 11 Nov 2024 21:57:27 +0100 Subject: [PATCH 070/106] patch 9.1.0856: mouseshape might be wrong on r and gr Problem: mouseshape might be wrong on r and gr Solution: call update_mousesape(-1) immediately (Yee Cheng Chin) Currently, when entering the "pretend" or single character replace modes using `r` or `gr`, the mouse cursor doesn't immediately update until you have re-focused the window or moved the mouse. This is because it's not calling `update_mouseshape(-1)` immediately, so the cursor will only be updated when it's called by other functions like `gui_mouse_focus`. To fix this, just make sure we call this `update_mouseshape(-1)`. It's what we do when entering Insert or Replace modes for example. I noticed this when trying to figure out why MacVim CI is failing in `Test_mouse_shape_after_cancelling_gr` (introduced in #12110), but I think that test is only passing in Vim GTK CI by accident, since this issue happens there too. I think the window captured focus after the mouse `gr` call which triggers a mouse shape change but it probably would have failed under other circumstances. fixes: #14660 closes: #12157 Signed-off-by: Yee Cheng Chin Signed-off-by: Christian Brabandt --- src/normal.c | 3 +++ src/version.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/normal.c b/src/normal.c index b0540050ad..9e617d9267 100644 --- a/src/normal.c +++ b/src/normal.c @@ -417,6 +417,9 @@ normal_cmd_get_more_chars( State = MODE_REPLACE; // pretend Replace mode #ifdef CURSOR_SHAPE ui_cursor_shape(); // show different cursor shape +#endif +#ifdef FEAT_MOUSESHAPE + update_mouseshape(-1); #endif } if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP) diff --git a/src/version.c b/src/version.c index 22473eb55b..4f66b3de24 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 */ +/**/ + 856, /**/ 855, /**/ From 4b9fa957125e33951a4a830414ccb70172976397 Mon Sep 17 00:00:00 2001 From: DungSaga Date: Mon, 11 Nov 2024 22:19:50 +0100 Subject: [PATCH 071/106] patch 9.1.0857: xxd: --- is incorrectly recognized as end-of-options Problem: xxd: --- is incorrectly recognized as end-of-options Solution: improve xxds end-of-option parser (DungSaga) closes: #9285 Signed-off-by: DungSaga Signed-off-by: Christian Brabandt --- src/testdir/test_xxd.vim | 9 ++++++++- src/version.c | 2 ++ src/xxd/xxd.c | 5 +++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/testdir/test_xxd.vim b/src/testdir/test_xxd.vim index f10c2447db..690c8daf7d 100644 --- a/src/testdir/test_xxd.vim +++ b/src/testdir/test_xxd.vim @@ -356,7 +356,7 @@ endfunc " Various ways with wrong arguments that trigger the usage output. func Test_xxd_usage() - for arg in ['-h', '-c', '-g', '-o', '-s', '-l', '-X', '-R', 'one two three'] + for arg in ['-h', '-c', '-g', '-o', '-s', '-l', '-X', '-R', 'one two three', '----', '---'] new exe 'r! ' . s:xxd_cmd . ' ' . arg call assert_match("Usage:", join(getline(1, 3))) @@ -364,6 +364,13 @@ func Test_xxd_usage() endfor endfunc +func Test_xxd_end_of_options() + new + exe 'r! ' . s:xxd_cmd . ' -- random-file-' . rand() + call assert_match('random-file-.*: No such file or directory', join(getline(1, 3))) + bwipe! +endfunc + func Test_xxd_ignore_garbage() new exe 'r! printf "\n\r xxxx 0: 42 42" | ' . s:xxd_cmd . ' -r' diff --git a/src/version.c b/src/version.c index 4f66b3de24..5c775b0304 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 */ +/**/ + 857, /**/ 856, /**/ diff --git a/src/xxd/xxd.c b/src/xxd/xxd.c index b1050e9da4..c222885455 100644 --- a/src/xxd/xxd.c +++ b/src/xxd/xxd.c @@ -65,6 +65,7 @@ * 10.05.2024 fix another buffer-overflow when writing colored output to buffer, #14738 * 10.09.2024 Support -b and -i together, #15661 * 19.10.2024 -e did add an extra space #15899 + * 11.11.2024 improve end-of-options argument parser #9285 * * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com) * @@ -145,7 +146,7 @@ extern void perror __P((char *)); # endif #endif -char version[] = "xxd 2024-10-19 by Juergen Weigert et al."; +char version[] = "xxd 2024-11-11 by Juergen Weigert et al."; #ifdef WIN32 char osver[] = " (Win32)"; #else @@ -843,7 +844,7 @@ main(int argc, char *argv[]) else exit_with_usage(); } - else if (!strcmp(pp, "--")) /* end of options */ + else if (!strcmp(argv[1], "--")) /* end of options */ { argv++; argc--; From 129a8446d23cd9cb4445fcfea259cba5e0487d29 Mon Sep 17 00:00:00 2001 From: Lennart00 <73488709+Lennart00@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:39:30 +0100 Subject: [PATCH 072/106] runtime(tar): Update tar.vim to support permissions These changes enable tar.vim to keep permissions of files that were edited intact instead of replacing them with the default permissions. The major change for this is switching from "tar -OPxf", which reads out the contents of the selected file from an tar archive to stdout to "tar -pPxf" which extracts the selected file to the current directory with permissions intact This requirs the temporary directory to be created earlier. closes: #7379 Signed-off-by: Lennart00 <73488709+Lennart00@users.noreply.github.com> Signed-off-by: Christian Brabandt --- runtime/autoload/tar.vim | 105 +++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 43 deletions(-) diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim index 9c4f16d7f6..436e24eb67 100644 --- a/runtime/autoload/tar.vim +++ b/runtime/autoload/tar.vim @@ -1,6 +1,6 @@ " tar.vim: Handles browsing tarfiles " AUTOLOAD PORTION -" Date: Nov 14, 2023 +" Date: Nov 11, 2024 " Version: 32b (with modifications from the Vim Project) " Maintainer: This runtime file is looking for a new maintainer. " Former Maintainer: Charles E Campbell @@ -23,7 +23,7 @@ if &cp || exists("g:loaded_tar") finish endif -let g:loaded_tar= "v32a" +let g:loaded_tar= "v32b" if v:version < 702 echohl WarningMsg echo "***warning*** this version of tar needs vim 7.2" @@ -41,7 +41,7 @@ if !exists("g:tar_browseoptions") let g:tar_browseoptions= "Ptf" endif if !exists("g:tar_readoptions") - let g:tar_readoptions= "OPxf" + let g:tar_readoptions= "pPxf" endif if !exists("g:tar_cmd") let g:tar_cmd= "tar" @@ -80,7 +80,7 @@ if !exists("g:tar_copycmd") let g:tar_copycmd= g:netrw_localcopycmd endif if !exists("g:tar_extractcmd") - let g:tar_extractcmd= "tar -xf" + let g:tar_extractcmd= "tar -pxf" endif " set up shell quoting character @@ -294,6 +294,41 @@ fun! tar#Read(fname,mode) set report=10 let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','') let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','') + +" changing the directory to the temporary earlier to allow tar to extract the file with permissions intact + if !exists("*mkdir") + redraw! + echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None + let &report= repkeep + return + endif + + let curdir= getcwd() + let tmpdir= tempname() + let b:curdir= tmpdir + let b:tmpdir= curdir + if tmpdir =~ '\.' + let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') + endif + call mkdir(tmpdir,"p") + + " attempt to change to the indicated directory + try + exe "cd ".fnameescape(tmpdir) + catch /^Vim\%((\a\+)\)\=:E344/ + redraw! + echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None + let &report= repkeep + return + endtry + + " place temporary files under .../_ZIPVIM_/ + if isdirectory("_ZIPVIM_") + call s:Rmdir("_ZIPVIM_") + endif + call mkdir("_ZIPVIM_") + cd _ZIPVIM_ + if has("win32unix") && executable("cygpath") " assuming cygwin let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e') @@ -332,9 +367,10 @@ fun! tar#Read(fname,mode) if tarfile =~# '\.bz2$' exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif tarfile =~# '\.\(gz\)$' exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp - + exe "read ".fname elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)' if has("unix") && executable("file") let filekind= system("file ".shellescape(tarfile,1)) @@ -343,20 +379,27 @@ fun! tar#Read(fname,mode) endif if filekind =~ "bzip2" exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif filekind =~ "XZ" exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif filekind =~ "Zstandard" exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname else exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname endif elseif tarfile =~# '\.lrp$' exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif tarfile =~# '\.lzma$' exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif tarfile =~# '\.\(xz\|txz\)$' exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname else if tarfile =~ '^\s*-' " A file name starting with a dash is taken as an option. Prepend ./ to avoid that. @@ -364,6 +407,16 @@ fun! tar#Read(fname,mode) endif " call Decho("8: exe silent r! ".g:tar_cmd." -".g:tar_readoptions.tar_secure.shellescape(tarfile,1)." ".shellescape(fname,1).decmp) exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname + endif + + redraw! + +if v:shell_error != 0 + cd .. + call s:Rmdir("_ZIPVIM_") + exe "cd ".fnameescape(curdir) + echohl Error | echo "***error*** (tar#Read) sorry, unable to open or extract ".tarfile." with ".fname | echohl None endif if doro @@ -388,6 +441,10 @@ fun! tar#Write(fname) " call Dfunc("tar#Write(fname<".a:fname.">) b:tarfile<".b:tarfile."> tblfile_".winnr()."<".s:tblfile_{winnr()}.">") let repkeep= &report set report=10 + + " temporary buffer variable workaround because too fucking tired. but it works now + let curdir= b:curdir + let tmpdir= b:tmpdir if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-' redraw! @@ -404,44 +461,6 @@ fun! tar#Write(fname) " call Dret("tar#Write") return endif - if !exists("*mkdir") - redraw! -" call Decho("***error*** (tar#Write) sorry, mkdir() doesn't work on your system") - echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None - let &report= repkeep -" call Dret("tar#Write") - return - endif - - let curdir= getcwd() - let tmpdir= tempname() -" call Decho("orig tempname<".tmpdir.">") - if tmpdir =~ '\.' - let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') - endif -" call Decho("tmpdir<".tmpdir.">") - call mkdir(tmpdir,"p") - - " attempt to change to the indicated directory - try - exe "cd ".fnameescape(tmpdir) - catch /^Vim\%((\a\+)\)\=:E344/ - redraw! -" call Decho("***error*** (tar#Write) cannot cd to temporary directory") - echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None - let &report= repkeep -" call Dret("tar#Write") - return - endtry -" call Decho("current directory now: ".getcwd()) - - " place temporary files under .../_ZIPVIM_/ - if isdirectory("_ZIPVIM_") - call s:Rmdir("_ZIPVIM_") - endif - call mkdir("_ZIPVIM_") - cd _ZIPVIM_ -" call Decho("current directory now: ".getcwd()) let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','') let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','') From 002ccbfac4ab0b052f4d547ea4c4ffbf212e4592 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Tue, 12 Nov 2024 20:10:58 +0100 Subject: [PATCH 073/106] patch 9.1.0858: Coverity complains about dead code Problem: Coverity complains about dead code (after v9.1.0852) Solution: adjust #ifdef FEAT_CLIPBOARD Signed-off-by: Christian Brabandt --- src/register.c | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/register.c b/src/register.c index c9bc752240..3ca425b450 100644 --- a/src/register.c +++ b/src/register.c @@ -198,6 +198,7 @@ valid_yank_reg( #endif ) return TRUE; +#ifndef FEAT_CLIPBOARD // clipboard support not enabled in this build else if (regname == '*' || regname == '+') { @@ -205,6 +206,7 @@ valid_yank_reg( msg_warn_missing_clipboard(); return FALSE; } +#endif return FALSE; } diff --git a/src/version.c b/src/version.c index 5c775b0304..bb0de39e13 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 */ +/**/ + 858, /**/ 857, /**/ From 13a6605ddf3b2a166b68f2de0762f8bd72cd6fe1 Mon Sep 17 00:00:00 2001 From: GuyBrush Date: Tue, 12 Nov 2024 20:18:14 +0100 Subject: [PATCH 074/106] patch 9.1.0859: several problems with the GLVS plugin Problem: several problems with the GLVS plugin Solution: fix issues, add regression tests, require at least Vim 9.1 (GuyBrush) closes: #16036 Signed-off-by: GuyBrush Signed-off-by: Christian Brabandt --- runtime/autoload/getscript.vim | 56 +++--- src/testdir/Make_all.mak | 2 + src/testdir/test_glvs.vim | 356 +++++++++++++++++++++++++++++++++ src/version.c | 2 + 4 files changed, 388 insertions(+), 28 deletions(-) create mode 100644 src/testdir/test_glvs.vim diff --git a/runtime/autoload/getscript.vim b/runtime/autoload/getscript.vim index dced99cc46..39060508bf 100644 --- a/runtime/autoload/getscript.vim +++ b/runtime/autoload/getscript.vim @@ -11,6 +11,7 @@ " 2024 Sep 23 by Vim Project: runtime dir selection fix (#15722) " autoloading search path fix " substitution of hardcoded commands with global variables +" 2024 Nov 12 by Vim Project: fix problems on Windows (#16036) " }}} " " GetLatestVimScripts: 642 1 :AutoInstall: getscript.vim @@ -27,9 +28,9 @@ if &cp echoerr "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)" finish endif -if v:version < 702 +if v:version < 901 echohl WarningMsg - echo "***warning*** this version of GetLatestVimScripts needs vim 7.2" + echo "***warning*** this version of GetLatestVimScripts needs vim 9.1" echohl Normal finish endif @@ -57,6 +58,9 @@ endif if !exists("g:GetLatestVimScripts_wget") if executable("wget") let g:GetLatestVimScripts_wget= "wget" + elseif executable("curl.exe") + " enforce extension: windows powershell desktop version has a curl alias that hides curl.exe + let g:GetLatestVimScripts_wget= "curl.exe" elseif executable("curl") let g:GetLatestVimScripts_wget= "curl" else @@ -69,7 +73,7 @@ endif if !exists("g:GetLatestVimScripts_options") if g:GetLatestVimScripts_wget == "wget" let g:GetLatestVimScripts_options= "-q -O" - elseif g:GetLatestVimScripts_wget == "curl" + elseif g:GetLatestVimScripts_wget =~ "curl" let g:GetLatestVimScripts_options= "-s -o" else let g:GetLatestVimScripts_options= "" @@ -121,11 +125,14 @@ if g:GetLatestVimScripts_allowautoinstall let s:dotvim= s:is_windows ? "vimfiles" : ".vim" if !exists("g:GetLatestVimScripts_mv") - if s:is_windows && &shell !~ '\cbash\|pwsh\|powershell' + if &shell =~? '\\|\' + let g:GetLatestVimScripts_mv= "move -Force" + elseif s:is_windows && &shell =~? '\' " windows (but not cygwin/bash) - let g:GetLatestVimScripts_mv= "move" + let g:GetLatestVimScripts_mv= "move /Y" else - " unix + " unix or cygwin bash/zsh + " 'mv' overrides existing files without asking let g:GetLatestVimScripts_mv= "mv" endif endif @@ -160,12 +167,6 @@ fun! getscript#GetLatestVimScripts() return endif - " insure that fnameescape() is available - if !exists("*fnameescape") - echoerr "GetLatestVimScripts needs fnameescape() (provided by 7.1.299 or later)" - return - endif - " Find the .../GetLatest subdirectory under the runtimepath for datadir in split(&rtp,',') + [''] if isdirectory(datadir."/GetLatest") @@ -377,7 +378,16 @@ fun! s:GetOneScript(...) let t_ti= &t_ti let t_te= &t_te let rs = &rs + let ssl = &ssl + set t_ti= t_te= nors + " avoid issues with shellescape() on Windows + if s:is_windows && &shell =~? '\' + set noshellslash + endif + + " restore valures afterwards + defer execute("let @a = rega | let &t_ti = t_ti | let &t_te = t_te | let &rs = rs | let &ssl = ssl") " put current line on top-of-screen and interpret it into " a script identifier : used to obtain webpage @@ -394,7 +404,6 @@ fun! s:GetOneScript(...) else let curline = getline(".") if curline =~ '^\s*#' - let @a= rega " call Dret("GetOneScript : skipping a pure comment line") return endif @@ -429,7 +438,6 @@ fun! s:GetOneScript(...) " plugin author protection from downloading his/her own scripts atop their latest work if scriptid == 0 || srcid == 0 " When looking for :AutoInstall: lines, skip scripts that have 0 0 scriptname - let @a= rega " call Dret("GetOneScript : skipping a scriptid==srcid==0 line") return endif @@ -497,7 +505,6 @@ fun! s:GetOneScript(...) " call Decho("***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">") echomsg "***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">" " call Dret("GetOneScript : srch for /Click on the package/ failed") - let @a= rega return endif " call Decho('found "Click on the package to download"') @@ -513,7 +520,6 @@ fun! s:GetOneScript(...) let s:downerrors = s:downerrors + 1 " call Decho("***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">") echomsg "***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">" - let @a= rega " call Dret("GetOneScript : srch for /src_id/ failed") return endif @@ -547,11 +553,11 @@ fun! s:GetOneScript(...) " call Decho(".downloading new <".sname.">") echomsg ".downloading new <".sname.">" if has("win32") || has("win16") || has("win95") -" call Decho(".new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr.latestsrcid)."|q") - new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr.latestsrcid)|q +" call Decho(".new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr.latestsrcid)."|bw!") + new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr.latestsrcid)|bw! else -" call Decho(".exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr).latestsrcid - exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr).latestsrcid +" call Decho(".exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr.latestsrcid) + exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr.latestsrcid) endif " -------------------------------------------------------------------------- @@ -654,8 +660,8 @@ fun! s:GetOneScript(...) exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".installdir endif if tgtdir != "plugin" -" call Decho("exe silent !".g:GetLatestVimScripts_mv." plugin/".shellescape(pname)." ".tgtdir) - exe "silent !".g:GetLatestVimScripts_mv." plugin/".shellescape(pname)." ".tgtdir +" call Decho("exe silent !".g:GetLatestVimScripts_mv." ".shellescape("plugin/".pname)." ".tgtdir) + exe "silent !".g:GetLatestVimScripts_mv." ".shellescape("plugin/".pname)." ".tgtdir endif " helptags step @@ -680,13 +686,7 @@ fun! s:GetOneScript(...) " call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."], no need to update") endif - " restore options - let &t_ti = t_ti - let &t_te = t_te - let &rs = rs - let @a = rega " call Dredir("BUFFER TEST (GetOneScript)","ls!") - " call Dret("GetOneScript") endfun diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 6a7f4d3f96..bdf058c1ec 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -173,6 +173,7 @@ NEW_TESTS = \ test_gf \ test_glob2regpat \ test_global \ + test_glvs \ test_gn \ test_goto \ test_gui \ @@ -437,6 +438,7 @@ NEW_TESTS_RES = \ test_gettext_make.res \ test_getvar.res \ test_gf.res \ + test_glvs.res \ test_gn.res \ test_goto.res \ test_gui.res \ diff --git a/src/testdir/test_glvs.vim b/src/testdir/test_glvs.vim new file mode 100644 index 0000000000..765f8b5efb --- /dev/null +++ b/src/testdir/test_glvs.vim @@ -0,0 +1,356 @@ +" Tests for GetLatestVimScripts plugin + +" vim feature +set nocp +set cpo&vim + +" constants +const s:dotvim= has("win32") ? "vimfiles" : ".vim" +const s:scriptdir = $"{$HOME}/{s:dotvim}/GetLatest" +const s:vimdir = expand("