From 91d26aa338224fd0370c75fac9dc062cdcd18470 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 27 Oct 2024 19:23:34 +0100 Subject: [PATCH 1/7] patch 9.1.0815: "above" virtual text causes wrong 'colorcolumn' position Problem: "above" virtual text causes wrong 'colorcolumn' position. (@matrdr) Solution: Use the number of cells instead of bytes for vcol_off_tp. (zeertzjq) fixes: #15946 closes: #15948 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- src/drawline.c | 2 +- .../dumps/Test_prop_multibyte_above_1.dump | 16 ++++++++++++++ src/testdir/test_textprop.vim | 21 +++++++++++++++++++ src/version.c | 2 ++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/testdir/dumps/Test_prop_multibyte_above_1.dump diff --git a/src/drawline.c b/src/drawline.c index fd5d56b43e508..b49e6531332f4 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -2263,7 +2263,7 @@ win_line( } if (above) - wlv.vcol_off_tp = wlv.n_extra; + wlv.vcol_off_tp = vim_strsize(wlv.p_extra); if (lcs_eol_one < 0 && wp->w_p_wrap diff --git a/src/testdir/dumps/Test_prop_multibyte_above_1.dump b/src/testdir/dumps/Test_prop_multibyte_above_1.dump new file mode 100644 index 0000000000000..d1e1d762c3139 --- /dev/null +++ b/src/testdir/dumps/Test_prop_multibyte_above_1.dump @@ -0,0 +1,16 @@ +| +0#af5f00255#ffffff0@3|…+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@1|1| |1+0#0000000&@7| | +0&#ffd7d7255| +0&#ffffff0@45 +| +0#af5f00255&@3|…+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@1|2| | +0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45 +| +0#af5f00255&@3|…+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@1|3| |3+0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45 +| +0#af5f00255&@3|…+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@1|4| | +0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45 +| +0#af5f00255&@3|…+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@1|5| >5+0#0000000&@8|5+0&#ffd7d7255|5+0&#ffffff0| @44 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|5|,|1|-|5|7| @7|A|l@1| diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index bbb911f959305..bf561cae35c83 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -3203,6 +3203,27 @@ func Test_prop_with_text_above_below_empty() call StopVimInTerminal(buf) endfunc +func Test_prop_with_multibyte_above() + CheckRunVimInTerminal + + let lines =<< trim END + setlocal number colorcolumn=10 + call setline(1, ['11111111', '', '333333333', '', '55555555555']) + + let vt = 'test' + call prop_type_add(vt, {'highlight': 'ToDo'}) + for ln in range(1, line('$')) + call prop_add(ln, 0, {'type': vt, 'text': '…', 'text_align': 'above'}) + endfor + normal G + END + call writefile(lines, 'XscriptPropMultibyteAbove', 'D') + let buf = RunVimInTerminal('-S XscriptPropMultibyteAbove', #{rows: 16, cols: 60}) + call VerifyScreenDump(buf, 'Test_prop_multibyte_above_1', {}) + + call StopVimInTerminal(buf) +endfunc + func Test_prop_with_multibyte_below() CheckRunVimInTerminal diff --git a/src/version.c b/src/version.c index aa05ea2c3528e..3931067154574 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 */ +/**/ + 815, /**/ 814, /**/ From 912fbaf6e8f50db44ece9b3f3a1babe21e77fa49 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sun, 27 Oct 2024 20:46:42 +0100 Subject: [PATCH 2/7] runtime(doc): Remove some completed items from todo.txt closes: #15949 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- runtime/doc/todo.txt | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 530b05dd3facf..2f186548282e8 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 9.1. Last change: 2024 Sep 29 +*todo.txt* For Vim version 9.1. Last change: 2024 Oct 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -55,32 +55,17 @@ When a help item can't be found, then open 'helpfile'. Search for the tag in that file and gtive E149 only when not found. Helps for a tiny Vim installed without all the help files. -SpellCap highlight not updated - PR #12428 - Virtual text problems: -- If 'list' is on, 'below' virtual text which includes 1 or 2 characters are - gone (Issue #12028) - Virtual text aligned "above": Wrong indentation when using tabs (Issue #12232) -- Virtual text to the right of the line that isn't visible doesn't cause the - 'extends' character to show in 'list' mode. #12478 -- Virtual text to the right of the line that fits exactly on screen causes - that line and all lines below it not to be displayed (Issue #12213) -- Window screen gets wrong when a virtual text is placed on 'above' or - 'below' on an empty line (Issue #11959) - truncated Virtual text below an empty line causes display error #12493 When 'virtualedit' is "all" and 'cursorcolumn' is set, the wrong column may be highlighted. (van-de-bugger, 2018 Jan 23, #2576) -Improve profiling by caching matching functions: PR #12192 - With 'smoothscroll' set and "lastline" in 'display', moving the cursor to a wrapping line that makes the display scroll up may scroll much more than needed, thus jump-scrolling. (part of issue 12411) - -Implement foreach() PR #12166 - Errors when running tests with valgrind: - test_codestyle.vim: e.g.: command line..script /home/mool/vim/vim91/src/testdir/runtest.vim[569]..function RunTheTest[52]..Test_test_files line 6: keycode_check.vim: space before tab: Expected 0 but got 7 @@ -117,7 +102,6 @@ Upcoming larger works: Further Vim9 improvements: - Classes and Interfaces. See |vim9-classes| - - Cannot use class type of itself in the method (Issue #12369) - Getting member of variable with "any" type should be handled at runtime. Remove temporary solution from #12096 / patch 9.0.1375. - "obj.Method()" does not always work in a compiled function, assumes "obj" @@ -127,9 +111,6 @@ Further Vim9 improvements: Possibly issue #11981 can be fixed at the same time (has two examples). - Forward declaration of a class? E.g. for Clone() function. Email lifepillar 2023 Mar 26 - - When "Meta" is a class, is "const MetaAlias = Meta" allowed? It should - either work or given an error. Possibly give an error now and implement it - later (using a typedef). #12006 - how about lock/unlock? - For chaining, allow using the class name as type for function return value. @@ -147,7 +128,7 @@ Further Vim9 improvements: has(featureName), len(someString) - Implement as part of an expression: ++expr, --expr, expr++, expr--. - The use of the literal value "null" and the type specific "null_xxx" - values is confusing (#13458, #11770). + values is confusing (#13433, #11770). Information missing in terminfo: - Codes used for focus gained and lost termcodes are hard-coded in @@ -225,8 +206,6 @@ Popup windows: positioned? PopupNew? Could be used to set some options or move it out of the way. (#5737) However, it may also cause trouble, changing the popup of another plugin. -- Width is not computed correctly when minwidth and maxwidth are &columns - and padding and a scrollbar are used. (#6676) - Should popup_getoptions() also return the mask? #7774 - Add a way to use popup_menu() synchronously: instead of invoking the callback, return the choice. (Ben Jackson, #6534) @@ -296,8 +275,6 @@ Terminal emulator window: - Use CTRL-W CTRL-K to enter a digraph? #5371 - When Vim runs in the terminal and changes the title, the statusline needs to be redrawn. -- GUI: When using ":set go+=!" a system() call causes the hit-enter prompt. - (#3327) - Allow for specifying the directory, with ++cwd={dir}. - When pasting should call vterm_keyboard_start_paste(), e.g. when using K_MIDDLEMOUSE, calling insert_reg(). @@ -323,9 +300,6 @@ Cursor is after the end of the line: #12137. Crash when a variable is removed while listing variables (Issue #11435) -Autoconf: must use autoconf 2.69, later version generates lots of warnings -- try using autoconf 2.71 and fix all "obsolete" warnings #11322 - Problem with Visual highlight when 'linebreak' and 'showbreak' are set. #11272 @@ -343,8 +317,6 @@ Support dark mode for MS-Windows: #12282 Remote command escapes single quote with backslash, should be doubling the single quote in vim_strsave_escaped_ext() #12202. -PR to add custom and customlist completion types. #12228 - Can deref_func_name() and deref_function_name() be merged? Using :global with a pattern containing \zs doesn't use the line where \zs From ce35ee89864784930d16392d5fd5dea1fab17f9c Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sun, 27 Oct 2024 21:15:50 +0100 Subject: [PATCH 3/7] patch 9.1.0816: tests: not clear what tests cause asan failures Problem: tests: not clear what tests cause asan failures Solution: append testname to $ASAN_OPTIONS Mention what test causes ASAN failures by appending the testname to log_path in $ASAN_OPTIONS/$UBSAN_OPTIONS. This assumes 'log_path' is always the last sub-option in $ASAN_OPTIONS. While at it, also make the CI run with `-O0` instead of `-O1` when ASAN is enable since this causes line numbers to disappear. closes: #15927 Signed-off-by: Christian Brabandt --- .github/workflows/ci.yml | 7 +++--- src/testdir/Makefile | 46 ++++++++++++++++++++++++++++++++++------ src/version.c | 2 ++ 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0496bcdb6e777..c1cca40563ca5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -194,9 +194,9 @@ jobs: echo "TEST=unittests" fi if ${{ contains(matrix.extra, 'asan') }}; then - echo "SANITIZER_CFLAGS=-g -O1 -DABORT_ON_INTERNAL_ERROR -DEXITFREE -fsanitize-recover=all -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" - echo "ASAN_OPTIONS=print_stacktrace=1 log_path=${LOG_DIR}/asan" - echo "UBSAN_OPTIONS=print_stacktrace=1 log_path=${LOG_DIR}/ubsan" + echo "SANITIZER_CFLAGS=-g -O0 -DABORT_ON_INTERNAL_ERROR -DEXITFREE -fsanitize-recover=all -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" + echo "ASAN_OPTIONS=print_stacktrace=1:log_path=${LOG_DIR}/asan" + echo "UBSAN_OPTIONS=print_stacktrace=1:log_path=${LOG_DIR}/ubsan" echo "LSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/src/testdir/lsan-suppress.txt" fi if ${{ contains(matrix.extra, 'vimtags') }}; then @@ -304,6 +304,7 @@ jobs: if: contains(matrix.extra, 'asan') && !cancelled() run: | for f in $(grep -lR '#[[:digit:]]* *0x[[:xdigit:]]*' "${LOG_DIR}"); do + echo "$f" asan_symbolize -l "$f" false # in order to fail a job done diff --git a/src/testdir/Makefile b/src/testdir/Makefile index 3b665e707f96c..4c7a273035440 100644 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -60,6 +60,9 @@ report: $(SCRIPTS_TINY_OUT) $(NEW_TESTS_RES): $(VIMPROG) +# For $ASAN_OPTIONS and $UBSAN_OPTIONS append the testname to it. +# This assumes $ASAN_OPTIONS contains log_path as last part of the environment variable +# For Github CI, those variables are set in .github/workflows/ci.yml # Execute an individual new style test, e.g.: # make test_largefile @@ -114,7 +117,11 @@ tinytests: $(SCRIPTS_TINY_OUT) @# 200 msec is sufficient, but only modern sleep supports a fraction of @# a second, fall back to a second if it fails. @-/bin/sh -c "sleep .2 > /dev/null 2>&1 || sleep 1" - $(RUN_VIMPROG) $*.in $(REDIR_TEST_TO_NULL) + if test -n "$${ASAN_OPTIONS}"; then \ + ASAN_OPTIONS="$${ASAN_OPTIONS}_$*" UBSAN_OPTIONS="$${UBSAN_OPTIONS}_$*" $(RUN_VIMPROG) $*.in $(REDIR_TEST_TO_NULL) ; \ + else \ + $(RUN_VIMPROG) $*.in $(REDIR_TEST_TO_NULL) ; \ + fi @# Check if the test.out file matches test.ok. @/bin/sh -c "if test -f test.out; then \ @@ -145,32 +152,53 @@ newtestssilent: $(NEW_TESTS_RES) .vim.res: @echo "$(VIMPROG)" > vimcmd @echo "$(RUN_VIMTEST)" >> vimcmd - $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim $*.vim $(REDIR_TEST_TO_NULL) + if test -n "$${ASAN_OPTIONS}"; then \ + ASAN_OPTIONS="$${ASAN_OPTIONS}_$*" UBSAN_OPTIONS="$${UBSAN_OPTIONS}_$*" $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim $*.vim $(REDIR_TEST_TO_NULL) ; \ + else \ + $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim $*.vim $(REDIR_TEST_TO_NULL) ; \ + fi @rm vimcmd test_gui.res: test_gui.vim @echo "$(VIMPROG)" > vimcmd @echo "$(RUN_GVIMTEST)" >> vimcmd - $(RUN_VIMTEST) -u NONE $(NO_INITS) -S runtest.vim $< + if test -n "$${ASAN_OPTIONS}"; then \ + ASAN_OPTIONS="$${ASAN_OPTIONS}_$*" UBSAN_OPTIONS="$${UBSAN_OPTIONS}_$*" $(RUN_VIMTEST) -u NONE $(NO_INITS) -S runtest.vim $< ; \ + else \ + $(RUN_VIMTEST) -u NONE $(NO_INITS) -S runtest.vim $< ; \ + fi + @rm vimcmd test_gui_init.res: test_gui_init.vim @echo "$(VIMPROG)" > vimcmd @echo "$(RUN_GVIMTEST_WITH_GVIMRC)" >> vimcmd - $(RUN_VIMTEST) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $< + if test -n "$${ASAN_OPTIONS}"; then \ + ASAN_OPTIONS="$${ASAN_OPTIONS}_$*" UBSAN_OPTIONS="$${UBSAN_OPTIONS}_$*" $(RUN_VIMTEST) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $< ; \ + else \ + $(RUN_VIMTEST) -u gui_preinit.vim -U gui_init.vim $(NO_PLUGINS) -S runtest.vim $< ; \ + fi @rm vimcmd GEN_OPT_DEPS = gen_opt_test.vim ../optiondefs.h ../../runtime/doc/options.txt opt_test.vim: $(GEN_OPT_DEPS) - $(VIMPROG) -e -s -u NONE $(NO_INITS) --nofork --gui-dialog-file guidialog -S $(GEN_OPT_DEPS) + if test -n "$${ASAN_OPTIONS}"; then \ + ASAN_OPTIONS="$${ASAN_OPTIONS}_$*" UBSAN_OPTIONS="$${UBSAN_OPTIONS}_$*" $(VIMPROG) -e -s -u NONE $(NO_INITS) --nofork --gui-dialog-file guidialog -S $(GEN_OPT_DEPS) ; \ + else \ + $(VIMPROG) -e -s -u NONE $(NO_INITS) --nofork --gui-dialog-file guidialog -S $(GEN_OPT_DEPS) ; \ + fi @if test -f test.log; then \ cat test.log; \ exit 1; \ fi test_xxd.res: - XXD=$(XXDPROG); export XXD; $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim test_xxd.vim + if test -n "$${ASAN_OPTIONS}"; then \ + XXD=$(XXDPROG); export XXD; ASAN_OPTIONS="$${ASAN_OPTIONS}_$*" UBSAN_OPTIONS="$${UBSAN_OPTIONS}_$*" $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim test_xxd.vim ; \ + else \ + XXD=$(XXDPROG); export XXD; $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim test_xxd.vim ; \ + fi test_bench_regexp.res: test_bench_regexp.vim -rm -rf benchmark.out $(RM_ON_RUN) @@ -178,5 +206,9 @@ test_bench_regexp.res: test_bench_regexp.vim @# 200 msec is sufficient, but only modern sleep supports a fraction of @# a second, fall back to a second if it fails. @-/bin/sh -c "sleep .2 > /dev/null 2>&1 || sleep 1" - $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim $*.vim $(REDIR_TEST_TO_NULL) + if test -n "$${ASAN_OPTIONS}"; then \ + ASAN_OPTIONS="$${ASAN_OPTIONS}_$*" UBSAN_OPTIONS="$${UBSAN_OPTIONS}_$*" $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim $*.vim $(REDIR_TEST_TO_NULL) ; \ + else \ + $(RUN_VIMTEST) $(NO_INITS) -S runtest.vim $*.vim $(REDIR_TEST_TO_NULL) ; \ + fi @/bin/sh -c "if test -f benchmark.out; then cat benchmark.out; fi" diff --git a/src/version.c b/src/version.c index 3931067154574..48312818bcfd2 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 */ +/**/ + 816, /**/ 815, /**/ From 2abec431e1ab5f4f6e21c2bb490241732622a8c5 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Sun, 27 Oct 2024 21:33:09 +0100 Subject: [PATCH 4/7] runtime(defaults): Detect putty terminal and switch to dark background Vim tries to determine the default background and checks for $TERM and even checks for the "putty" value. But unfortunately, putty by default uses "xterm" as $TERM value and as such Vim uses a "light" background. So use a TermResponse autocommand to set the background for putty back to dark. Note: this only works on non-tiny builds and when defaults.vim is in use. Signed-off-by: Christian Brabandt --- runtime/defaults.vim | 5 +++++ runtime/doc/autocmd.txt | 19 ++++++++++++++----- runtime/doc/version9.txt | 4 +++- src/testdir/test_cmdline.vim | 2 ++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/runtime/defaults.vim b/runtime/defaults.vim index ff8ce8ea18f3f..459841ffcc937 100644 --- a/runtime/defaults.vim +++ b/runtime/defaults.vim @@ -115,6 +115,11 @@ if 1 \ | execute "normal! g`\"" \ | endif + " 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" + autocmd TermResponse * if v:termresponse == "\e[>0;136;0c" | set bg=dark | endif augroup END " Quite a few people accidentally type "q:" instead of ":q" and get confused diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index f200a30e5025b..6ca00a6e1efa4 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -1,4 +1,4 @@ -*autocmd.txt* For Vim version 9.1. Last change: 2024 Aug 18 +*autocmd.txt* For Vim version 9.1. Last change: 2024 Oct 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1254,10 +1254,19 @@ TerminalWinOpen Just after a terminal buffer was created, with TermResponse After the response to |t_RV| is received from the terminal. The value of |v:termresponse| can be used to do things depending on the - terminal version. Note that this event may be - triggered halfway executing another event, - especially if file I/O, a shell command or - anything else that takes time is involved. + terminal version. + This is used in |defaults.vim| to detect + putty terminal and set a dark background: > + + au TermResponse * + \ if v:termresponse == "\e[>0;136;0c" + \ set bg=dark + \ endif +< + Note: that this event may be triggered halfway + executing another event, especially if file + I/O, a shell command or anything else that + takes time is involved. *TermResponseAll* TermResponseAll After the response to |t_RV|, |t_RC|, |t_RS|, |t_RB|, |t_RF|, or |t_u7| are received from diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index af180a2238f57..2a3846669d9d8 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 22 +*version9.txt* For Vim version 9.1. Last change: 2024 Oct 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41600,6 +41600,8 @@ Changed~ - |:keeppatterns| preserves the last substitute pattern when used with |:s| - |setqflist()| and |setloclist()| can optionally try to preserve the current 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 *added-9.2* Added ~ diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index e1dbc87fe2295..30ded35b8d90f 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -1701,6 +1701,8 @@ func Test_verbose_option() CheckScreendump let lines =<< trim [SCRIPT] + " clear the TermResponse autocommand from defaults.vim + au! vimStartup TermResponse command DoSomething echo 'hello' |set ts=4 |let v = '123' |echo v call feedkeys("\r", 't') " for the hit-enter prompt set verbose=20 From 8f1d09828a92469a7fa824a8653bf689a7864d21 Mon Sep 17 00:00:00 2001 From: Peter Wolf Date: Sun, 27 Oct 2024 21:51:14 +0100 Subject: [PATCH 5/7] patch 9.1.0817: termdebug: cannot evaluate expr in a popup Problem: termdebug: cannot evaluate expr in a popup Solution: enhance termdebug plugin and allow to evaluate expressions in a popup window, add a unit test (Peter Wolf). fixes: #15877 closes: #15933 Signed-off-by: Peter Wolf Signed-off-by: Christian Brabandt --- runtime/doc/tags | 1 + runtime/doc/terminal.txt | 21 ++++- .../dist/opt/termdebug/plugin/termdebug.vim | 71 ++++++++++++--- .../Test_termdebug_evaluate_in_popup_01.dump | 20 +++++ .../Test_termdebug_evaluate_in_popup_01.vim | 9 ++ .../Test_termdebug_evaluate_in_popup_02.dump | 20 +++++ .../Test_termdebug_evaluate_in_popup_02.vim | 9 ++ src/testdir/test_termdebug.vim | 89 +++++++++++++++++++ src/version.c | 2 + 9 files changed, 230 insertions(+), 12 deletions(-) create mode 100644 src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.dump create mode 100644 src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.vim create mode 100644 src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.dump create mode 100644 src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.vim diff --git a/runtime/doc/tags b/runtime/doc/tags index 0c1b31a663b8d..75359f2695637 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -10664,6 +10664,7 @@ termdebug-stepping terminal.txt /*termdebug-stepping* termdebug-timeout terminal.txt /*termdebug-timeout* termdebug-variables terminal.txt /*termdebug-variables* termdebug_disasm_window terminal.txt /*termdebug_disasm_window* +termdebug_evaluate_in_popup terminal.txt /*termdebug_evaluate_in_popup* termdebug_map_K terminal.txt /*termdebug_map_K* termdebug_map_minus terminal.txt /*termdebug_map_minus* termdebug_map_plus terminal.txt /*termdebug_map_plus* diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index 5020ed5b458b2..6b53e0223a7d1 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 Jul 28 +*terminal.txt* For Vim version 9.1. Last change: 2024 Oct 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1537,6 +1537,7 @@ If there is no g:termdebug_config you can use: > < However, the latter form will be deprecated in future releases. + Mappings ~ The termdebug plugin enables a few default mappings. All those mappings are reset to their original values once the termdebug session concludes. @@ -1591,6 +1592,7 @@ If the current window has enough horizontal space, it will be vertically split and the Var window will be shown side by side with the source code window (and the height options won't be used). + Communication ~ *termdebug-communication* There is another, hidden, buffer, which is used for Vim to communicate with @@ -1675,10 +1677,11 @@ If there is no g:termdebug_config you can use: > However, the latter form will be deprecated in future releases. + Change default signs ~ *termdebug_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 +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. If you want to customize the breakpoint signs: > @@ -1716,4 +1719,18 @@ Set the wide value to 1 to use a vertical split without ever changing 'columns'. This is useful when the terminal can't be resized by Vim. +Evaluate in Popup Window at Cursor ~ + *termdebug_evaluate_in_popup* +By default |:Evaluate| will simply echo its output. For larger entities this +might become difficult to read or even truncated. +Alternatively, the evaluation result may be output into a popup window at the +current cursor position: > + let g:termdebug_config['evaluate_in_popup'] = v:true +This can also be used in a "one-shot" manner: > + func OnCursorHold() + let g:termdebug_config['evaluate_in_popup'] = v:true + :Evaluate + let g:termdebug_config['evaluate_in_popup'] = v:false + endfunc +< vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 377827e85738b..e7c010d4ce5c4 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -121,7 +121,9 @@ var breakpoint_locations: dict var BreakpointSigns: list var evalFromBalloonExpr: bool -var evalFromBalloonExprResult: string +var evalInPopup: bool +var evalPopupId: number +var evalExprResult: string var ignoreEvalError: bool var evalexpr: string # Remember the old value of 'signcolumn' for each buffer that it's set in, so @@ -202,7 +204,9 @@ def InitScriptVariables() BreakpointSigns = [] evalFromBalloonExpr = false - evalFromBalloonExprResult = '' + evalInPopup = false + evalPopupId = -1 + evalExprResult = '' ignoreEvalError = false evalexpr = '' # Remember the old value of 'signcolumn' for each buffer that it's set in, so @@ -1478,10 +1482,23 @@ def SendEval(expr: string) evalexpr = exprLHS enddef +# Returns whether to evaluate in a popup or not, defaults to false. +def EvaluateInPopup(): bool + if exists('g:termdebug_config') + return get(g:termdebug_config, 'evaluate_in_popup', false) + endif + return false +enddef + # :Evaluate - evaluate what is specified / under the cursor def Evaluate(range: number, arg: string) var expr = GetEvaluationExpression(range, arg) - echom $"expr: {expr}" + if EvaluateInPopup() + evalInPopup = true + evalExprResult = '' + else + echomsg $'expr: {expr}' + endif ignoreEvalError = false SendEval(expr) enddef @@ -1541,6 +1558,37 @@ def Balloon_show(expr: string) endif enddef +def Popup_format(expr: string): list + var lines = expr + ->substitute('{', '{\n', 'g') + ->substitute('}', '\n}', 'g') + ->substitute(',', ',\n', 'g') + ->split('\n') + var indentation = 0 + var formatted_lines = [] + for line in lines + var stripped = line->substitute('^\s\+', '', '') + if stripped =~ '^}' + indentation -= 2 + endif + formatted_lines->add(repeat(' ', indentation) .. stripped) + if stripped =~ '{$' + indentation += 2 + endif + endfor + return formatted_lines +enddef + +def Popup_show(expr: string) + var formatted = Popup_format(expr) + if evalPopupId != -1 + popup_close(evalPopupId) + endif + # Specifying the line is necessary, as the winbar seems to cause issues + # otherwise. I.e., the popup would be shown one line too high. + evalPopupId = popup_atcursor(formatted, {'line': 'cursor-1'}) +enddef + def HandleEvaluate(msg: string) var value = msg ->substitute('.*value="\(.*\)"', '\1', '') @@ -1555,13 +1603,12 @@ def HandleEvaluate(msg: string) #\ ->substitute('\\0x00', NullRep, 'g') #\ ->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g') ->substitute(NullRepl, '\\000', 'g') - if evalFromBalloonExpr - if empty(evalFromBalloonExprResult) - evalFromBalloonExprResult = $'{evalexpr}: {value}' + if evalFromBalloonExpr || evalInPopup + if empty(evalExprResult) + evalExprResult = $'{evalexpr}: {value}' else - evalFromBalloonExprResult ..= $' = {value}' + evalExprResult ..= $' = {value}' endif - Balloon_show(evalFromBalloonExprResult) else echomsg $'"{evalexpr}": {value}' endif @@ -1570,8 +1617,12 @@ def HandleEvaluate(msg: string) # Looks like a pointer, also display what it points to. ignoreEvalError = true SendEval($'*{evalexpr}') - else + elseif evalFromBalloonExpr + Balloon_show(evalExprResult) evalFromBalloonExpr = false + elseif evalInPopup + Popup_show(evalExprResult) + evalInPopup = false endif enddef @@ -1588,7 +1639,7 @@ def TermDebugBalloonExpr(): string return '' endif evalFromBalloonExpr = true - evalFromBalloonExprResult = '' + evalExprResult = '' ignoreEvalError = true var expr = CleanupExpr(v:beval_text) SendEval(expr) diff --git a/src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.dump b/src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.dump new file mode 100644 index 0000000000000..3dde6cc98a0dc --- /dev/null +++ b/src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.dump @@ -0,0 +1,20 @@ +|U+0&#ffffff0|s|i|n|g| |h|o|s|t| |l|i|b|t|h|r|e|a|d|_|d|b| |l|i|b|r|a|r|y| |"|/+0#00e0003&|l|i|b|/|x|8|6|_|6|4|-|l|i|n|u|x|-|g|n|u|/|l|i|b|t|h|r|e|a|d|_|d|b|.|s|o|.|1|"+0#0000000&|.| +@75 +|B|r|e|a|k|p|o|i|n|t| |1|,| |m+0#e0e0004&|a|i|n| +0#0000000&|(|a+0#00e0e07&|r|g|c|=+0#0000000&|1|,| |a+0#00e0e07&|r|g|v|=+0#0000000&|0|x|7|f@6|d|e|f|8|)| @26 +@4|a|t| |X+0#00e0003&|T|D|_|e|v|a|l|u|a|t|e|_|i|n|_|p|o|p|u|p|.|c|:+0#0000000&|9| @42 +|9| @8|r+2#0000e05&|e|t|u|r|n| +0#0000000&|0+0#e000e06&|;+0#e000002&| +0#0000000&@55 +@75 +|g+0#ffffff16#00e0003|d|b| |[|r|u|n@1|i|n|g|]| @43|1|,|1| @11|T|o|p +| +0#0000000#ffffff0@74 +@75 +@75 +@75 +@75 +|d+0#ffffff16#00e0003|e|b|u|p+0#0000001#ffd7ff255|:| |{| @3|g+0#ffffff16#00e0003|r|a|m| |[|a|c|t|i|v|e|]| @31|0|,|0|-|1| @9|A|l@1 +| +0#0000000#e0e0e08| +2#ffffff16#6c6c6c255|S|t| +0#0000001#ffd7ff255@1|x| |=| |1|,|x+2#ffffff16#6c6c6c255|t| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|F|i|n|i|s|h| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|C|o|n|t| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|S|t|o|p| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|E|v|a|l| | +0#0000000#e0e0e08@25 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1| +0#0000001#ffd7ff255@1|y| |=| |2| |o+0#0000000#ffffff0|i|n|t| |p| |=| |{|a|r|g|c|,| |2+0#e000002&|}+0#0000000&|;| @43 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|}+0#0000001#ffd7ff255| @6|o+0#0000000#ffffff0|i|n|t|*| |p|_|p|t|r| |=| |&|p|;| @45 +|0+0&#ff404010|1| +0fd7ff255@1>r+0#af5f00255&|e|t|u|r|n| +0#0000000&|0+0#e000002&|;+0#0000000&| @61 +| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @71 +|X+3&&|T|D|_|e|v|a|l|u|a|t|e|_|i|n|_|p|o|p|u|p|.|c| @33|9|,|3| @11|B|o|t +|:+0&&|E|v|a|l|u|a|t|e| |p| @63 diff --git a/src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.vim b/src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.vim new file mode 100644 index 0000000000000..959798ac41b41 --- /dev/null +++ b/src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.vim @@ -0,0 +1,9 @@ +" replace hex addresses with |0|x|f@12| +:%s/|0|x|\(\(\w\|@\)\+|\)\+/|0|x|f@12|/g + +" Only keep screen lines relevant to the actual popup and evaluation. +" Especially the top lines are too instable and cause flakiness between +" different systems and tool versions. +normal! G +normal! 8k +normal! dgg diff --git a/src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.dump b/src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.dump new file mode 100644 index 0000000000000..0e3fa33399088 --- /dev/null +++ b/src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.dump @@ -0,0 +1,20 @@ +|U+0&#ffffff0|s|i|n|g| |h|o|s|t| |l|i|b|t|h|r|e|a|d|_|d|b| |l|i|b|r|a|r|y| |"|/+0#00e0003&|l|i|b|/|x|8|6|_|6|4|-|l|i|n|u|x|-|g|n|u|/|l|i|b|t|h|r|e|a|d|_|d|b|.|s|o|.|1|"+0#0000000&|.| +@75 +|B|r|e|a|k|p|o|i|n|t| |1|,| |m+0#e0e0004&|a|i|n| +0#0000000&|(|a+0#00e0e07&|r|g|c|=+0#0000000&|1|,| |a+0#00e0e07&|r|g|v|=+0#0000000&|0|x|7|f@6|d|e|f|8|)| @26 +@4|a|t| |X+0#00e0003&|T|D|_|e|v|a|l|u|a|t|e|_|i|n|_|p|o|p|u|p|.|c|:+0#0000000&|9| @42 +|9| @8|r+2#0000e05&|e|t|u|r|n| +0#0000000&|0+0#e000e06&|;+0#e000002&| +0#0000000&@55 +@75 +|g+0#ffffff16#00e0003|d|b| |[|r|u|n@1|i|n|g|]| @43|1|,|1| @11|T|o|p +| +0#0000000#ffffff0@74 +@75 +@75 +@75 +@75 +|d+0#ffffff16#00e0003|e|b|u|p+0#0000001#ffd7ff255|_|p|t|r|:| |0|x|7|f@6|d@1|c|0| |=| |{| +0#ffffff16#00e0003@27|0|,|0|-|1| @9|A|l@1 +| +0#0000000#e0e0e08| +2#ffffff16#6c6c6c255|S|t| +0#0000001#ffd7ff255@1|x| |=| |1|,| @16|o+2#ffffff16#6c6c6c255|n|t| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|S|t|o|p| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|E|v|a|l| | +0#0000000#e0e0e08@25 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1| +0#0000001#ffd7ff255@1|y| |=| |2| @17|}+0#0000000#ffffff0|;| @43 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|}+0#0000001#ffd7ff255| @23| +0#0000000#ffffff0@45 +|0+0&#ff404010|1| +0fd7ff255@1>r+0#af5f00255&|e|t|u|r|n| +0#0000000&|0+0#e000002&|;+0#0000000&| @61 +| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @71 +|X+3&&|T|D|_|e|v|a|l|u|a|t|e|_|i|n|_|p|o|p|u|p|.|c| @33|9|,|3| @11|B|o|t +|:+0&&|E|v|a|l|u|a|t|e| |p|_|p|t|r| @59 diff --git a/src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.vim b/src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.vim new file mode 100644 index 0000000000000..959798ac41b41 --- /dev/null +++ b/src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.vim @@ -0,0 +1,9 @@ +" replace hex addresses with |0|x|f@12| +:%s/|0|x|\(\(\w\|@\)\+|\)\+/|0|x|f@12|/g + +" Only keep screen lines relevant to the actual popup and evaluation. +" Especially the top lines are too instable and cause flakiness between +" different systems and tool versions. +normal! G +normal! 8k +normal! dgg diff --git a/src/testdir/test_termdebug.vim b/src/testdir/test_termdebug.vim index b5c12aefe1907..30176cb75b618 100644 --- a/src/testdir/test_termdebug.vim +++ b/src/testdir/test_termdebug.vim @@ -1,6 +1,7 @@ " Test for the termdebug plugin source shared.vim +source screendump.vim source check.vim CheckUnix @@ -243,6 +244,94 @@ func Test_termdebug_tbreak() %bw! endfunc +func Test_termdebug_evaluate() + let bin_name = 'XTD_evaluate' + let src_name = bin_name .. '.c' + call s:generate_files(bin_name) + + edit XTD_evaluate.c + Termdebug ./XTD_evaluate + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) + call WaitForAssert({-> assert_equal(3, winnr('$'))}) + let gdb_buf = winbufnr(1) + wincmd b + + " return stmt in main + Break 22 + call term_wait(gdb_buf) + Run + call term_wait(gdb_buf, 400) + redraw! + + " Evaluate an expression + Evaluate n + call term_wait(gdb_buf) + call assert_equal(execute('1messages')->trim(), '"n": 7') + Evaluate argc + call term_wait(gdb_buf) + call assert_equal(execute('1messages')->trim(), '"argc": 1') + Evaluate isprime(n) + call term_wait(gdb_buf) + call assert_equal(execute('1messages')->trim(), '"isprime(n)": 1') + + wincmd t + quit! + redraw! + call s:cleanup_files(bin_name) + %bw! +endfunc + +func Test_termdebug_evaluate_in_popup() + CheckScreendump + let bin_name = 'XTD_evaluate_in_popup' + let src_name = bin_name .. '.c' + let code =<< trim END + struct Point { + int x; + int y; + }; + + int main(int argc, char* argv[]) { + struct Point p = {argc, 2}; + struct Point* p_ptr = &p; + return 0; + } + END + call writefile(code, src_name, 'D') + call system($'{g:GCC} -g -o {bin_name} {src_name}') + + let lines =<< trim END + edit XTD_evaluate_in_popup.c + packadd termdebug + let g:termdebug_config = {} + let g:termdebug_config['evaluate_in_popup'] = v:true + Termdebug ./XTD_evaluate_in_popup + wincmd b + Break 9 + Run + END + + call writefile(lines, 'Xscript', 'D') + let buf = RunVimInTerminal('-S Xscript', {}) + call TermWait(buf, 400) + + call term_sendkeys(buf, ":Evaluate p\") + call TermWait(buf, 400) + call VerifyScreenDump(buf, 'Test_termdebug_evaluate_in_popup_01', {}) + + call term_sendkeys(buf, ":Evaluate p_ptr\") + call TermWait(buf, 400) + call VerifyScreenDump(buf, 'Test_termdebug_evaluate_in_popup_02', {}) + + " Cleanup + call term_sendkeys(buf, ":Gdb") + call term_sendkeys(buf, ":quit!\") + call term_sendkeys(buf, ":qa!\") + call StopVimInTerminal(buf) + call delete(bin_name) + %bw! +endfunc + func Test_termdebug_mapping() %bw! call assert_true(maparg('K', 'n', 0, 1)->empty()) diff --git a/src/version.c b/src/version.c index 48312818bcfd2..90fc3b3e00c4f 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 */ +/**/ + 817, /**/ 816, /**/ From a04003a929e443813c8060242e9809135b134a4c Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sun, 27 Oct 2024 21:54:11 +0100 Subject: [PATCH 6/7] patch 9.1.0818: some global functions are only used in single files Problem: some global functions are only used in single files Solution: refactor code slightly and make some more functions static (Yegappan Lakshmanan) closes: #15951 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/misc1.c | 22 +++++++++++----------- src/proto/misc1.pro | 1 - src/proto/typval.pro | 1 - src/proto/userfunc.pro | 1 - src/proto/vim9class.pro | 1 - src/typval.c | 2 +- src/userfunc.c | 3 ++- src/version.c | 2 ++ src/vim9class.c | 2 +- 9 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/misc1.c b/src/misc1.c index 0898efb33f6e9..90cf914742b11 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -953,6 +953,17 @@ get_keystroke(void) return n; } +// For overflow detection, add a digit safely to an int value. + static int +vim_append_digit_int(int *value, int digit) +{ + int x = *value; + if (x > ((INT_MAX - digit) / 10)) + return FAIL; + *value = x * 10 + digit; + return OK; +} + /* * Get a number from the user. * When "mouse_used" is not NULL allow using the mouse. @@ -2824,17 +2835,6 @@ may_trigger_modechanged(void) #endif } -// For overflow detection, add a digit safely to an int value. - int -vim_append_digit_int(int *value, int digit) -{ - int x = *value; - if (x > ((INT_MAX - digit) / 10)) - return FAIL; - *value = x * 10 + digit; - return OK; -} - // For overflow detection, add a digit safely to a long value. int vim_append_digit_long(long *value, int digit) diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro index d64f961f011db..1a053e3dbcab0 100644 --- a/src/proto/misc1.pro +++ b/src/proto/misc1.pro @@ -53,7 +53,6 @@ int path_with_url(char_u *fname); dict_T *get_v_event(save_v_event_T *sve); void restore_v_event(dict_T *v_event, save_v_event_T *sve); void may_trigger_modechanged(void); -int vim_append_digit_int(int *value, int digit); int vim_append_digit_long(long *value, int digit); int trim_to_int(vimlong_T x); /* vim: set ft=c : */ diff --git a/src/proto/typval.pro b/src/proto/typval.pro index 1edfeb4c18073..b70618342f513 100644 --- a/src/proto/typval.pro +++ b/src/proto/typval.pro @@ -53,7 +53,6 @@ int check_for_list_or_dict_or_blob_arg(typval_T *args, int idx); int check_for_list_or_dict_or_blob_or_string_arg(typval_T *args, int idx); int check_for_opt_buffer_or_dict_arg(typval_T *args, int idx); int check_for_object_arg(typval_T *args, int idx); -int tv_class_alias(typval_T *tv); int check_for_class_or_typealias_args(typval_T *args, int idx); char_u *tv_get_string(typval_T *varp); char_u *tv_get_string_strict(typval_T *varp); diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro index 32dac661b03a0..cdcf017d362c1 100644 --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -42,7 +42,6 @@ int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typva int call_simple_func(char_u *funcname, size_t len, typval_T *rettv); char_u *printable_func_name(ufunc_T *fp); char_u *trans_function_name(char_u **pp, int *is_global, int skip, int flags); -char_u *trans_function_name_ext(char_u **pp, int *is_global, int skip, int flags, funcdict_T *fdp, partial_T **partial, type_T **type, ufunc_T **ufunc); char_u *get_scriptlocal_funcname(char_u *funcname); char_u *alloc_printable_func_name(char_u *fname); char_u *save_function_name(char_u **name, int *is_global, int skip, int flags, funcdict_T *fudi); diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro index c87fffbc8ac3b..7d11523cef200 100644 --- a/src/proto/vim9class.pro +++ b/src/proto/vim9class.pro @@ -7,7 +7,6 @@ void enum_set_internal_obj_vars(class_T *en, object_T *enval); type_T *oc_member_type(class_T *cl, int is_object, char_u *name, char_u *name_end, int *member_idx); type_T *oc_member_type_by_idx(class_T *cl, int is_object, int member_idx); void ex_enum(exarg_T *eap); -void typealias_free(typealias_T *ta); void typealias_unref(typealias_T *ta); void ex_type(exarg_T *eap); int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose); diff --git a/src/typval.c b/src/typval.c index 01ffef5e5d896..e57d8981503ce 100644 --- a/src/typval.c +++ b/src/typval.c @@ -1021,7 +1021,7 @@ check_for_object_arg(typval_T *args, int idx) /* * Returns TRUE if "tv" is a type alias for a class */ - int + static int tv_class_alias(typval_T *tv) { return tv->v_type == VAR_TYPEALIAS && diff --git a/src/userfunc.c b/src/userfunc.c index 5d167101d850b..5bf7e9558ed4d 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -34,6 +34,7 @@ static void func_clear(ufunc_T *fp, int force); static int func_free(ufunc_T *fp, int force); static char_u *untrans_function_name(char_u *name); static void handle_defer_one(funccall_T *funccal); +static char_u *trans_function_name_ext(char_u **pp, int *is_global, int skip, int flags, funcdict_T *fdp, partial_T **partial, type_T **type, ufunc_T **ufunc); void func_init(void) @@ -4266,7 +4267,7 @@ trans_function_name( * trans_function_name() with extra arguments. * "fdp", "partial", "type" and "ufunc" can be NULL. */ - char_u * + static char_u * trans_function_name_ext( char_u **pp, int *is_global, diff --git a/src/version.c b/src/version.c index 90fc3b3e00c4f..02e24d5529ce3 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 */ +/**/ + 818, /**/ 817, /**/ diff --git a/src/vim9class.c b/src/vim9class.c index d8813c6f20f78..87b4d45ea5744 100644 --- a/src/vim9class.c +++ b/src/vim9class.c @@ -2646,7 +2646,7 @@ oc_member_type_by_idx( * Type aliases (:type) */ - void + static void typealias_free(typealias_T *ta) { // ta->ta_type is freed in clear_type_list() From 3d7e567ea7392e43a90a6ffb3cd49b71a7b59d1a Mon Sep 17 00:00:00 2001 From: Konfekt Date: Sun, 27 Oct 2024 22:16:49 +0100 Subject: [PATCH 7/7] runtime(netrw): simplify gx file handling It did not work very well, at least on Debian 12, and I am not sure Git Bash and WSL, for example, were taken care of as maintenance stalled. The whole logic was somewhat convoluted with some parts repeatedly invoking failed commands. The file handling was outdated, for example, nowadays Netscape is rarely used, and also opinionated, for example mainly Microsoft Paint and Gimp for Image files. Instead, let's use (xdg-)open and similar commands on other systems which respects the user's preferences. closes: #15721 Co-authored-by: Luca Saccarola <96259932+saccarosium@users.noreply.github.com> Signed-off-by: Konfekt Signed-off-by: Christian Brabandt --- runtime/autoload/netrw.vim | 136 +++++++++------------------------ runtime/doc/pi_netrw.txt | 103 ++++++++++++++++++------- runtime/doc/tags | 2 + runtime/plugin/netrwPlugin.vim | 84 +++++++++++++++++++- 4 files changed, 199 insertions(+), 126 deletions(-) diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index 0adcc6586952e..e09716de1f0cc 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -27,6 +27,7 @@ " 2024 Sep 19 by Vim Project: mf-selection highlight uses wrong pattern (#15700) " 2024 Sep 21 by Vim Project: remove extraneous closing bracket (#15718) " 2024 Oct 21 by Vim Project: remove netrwFileHandlers (#15895) +" 2024 Oct 27 by Vim Project: clean up gx mapping (#15721) " }}} " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim @@ -538,7 +539,6 @@ if !exists("g:netrw_sort_sequence") endif call s:NetrwInit("g:netrw_special_syntax" , 0) call s:NetrwInit("g:netrw_ssh_browse_reject", '^total\s\+\d\+$') -call s:NetrwInit("g:netrw_suppress_gx_mesg", 1) call s:NetrwInit("g:netrw_use_noswf" , 1) call s:NetrwInit("g:netrw_sizestyle" ,"b") " Default values - t-w ---------- {{{3 @@ -5406,25 +5406,6 @@ fun! netrw#BrowseX(fname,remote) " call Decho("fname<".fname.">",'~'.expand("")) " call Decho("exten<".exten."> "."netrwFileHandlers#NFH_".exten."():exists=".exists("*netrwFileHandlers#NFH_".exten),'~'.expand("")) - " set up redirection (avoids browser messages) - " by default, g:netrw_suppress_gx_mesg is true - if g:netrw_suppress_gx_mesg - if &srr =~ "%s" - if has("win32") - let redir= substitute(&srr,"%s","nul","") - else - let redir= substitute(&srr,"%s","/dev/null","") - endif - elseif has("win32") - let redir= &srr . "nul" - else - let redir= &srr . "/dev/null" - endif - else - let redir= "" - endif -" call Decho("set up redirection: redir{".redir."} srr{".&srr."}",'~'.expand("")) - " extract any viewing options. Assumes that they're set apart by spaces. if exists("g:netrw_browsex_viewer") " call Decho("extract any viewing options from g:netrw_browsex_viewer<".g:netrw_browsex_viewer.">",'~'.expand("")) @@ -5447,86 +5428,14 @@ fun! netrw#BrowseX(fname,remote) " call Decho("viewer<".viewer."> viewopt<".viewopt.">",'~'.expand("")) endif - " execute the file handler -" call Decho("execute the file handler (if any)",'~'.expand("")) if exists("g:netrw_browsex_viewer") && executable(viewer) " call Decho("(netrw#BrowseX) g:netrw_browsex_viewer<".g:netrw_browsex_viewer.">",'~'.expand("")) - call s:NetrwExe("sil !".viewer." ".viewopt.s:ShellEscape(fname,1).redir) - let ret= v:shell_error - - elseif has("win32") -" call Decho("(netrw#BrowseX) win".(has("win32")? "32" : "64"),'~'.expand("")) - if executable("start") - call s:NetrwExe('sil! !start rundll32 url.dll,FileProtocolHandler '.s:ShellEscape(fname,1)) - elseif executable("rundll32") - call s:NetrwExe('sil! !rundll32 url.dll,FileProtocolHandler '.s:ShellEscape(fname,1)) - else - call netrw#ErrorMsg(s:WARNING,"rundll32 not on path",74) - endif - let ret= v:shell_error - - elseif has("win32unix") - let winfname= 'c:\cygwin'.substitute(fname,'/','\\','g') -" call Decho("(netrw#BrowseX) cygwin: winfname<".s:ShellEscape(winfname,1).">",'~'.expand("")) - if executable("start") -" call Decho("(netrw#BrowseX) win32unix+start",'~'.expand("")) - call s:NetrwExe('sil !start rundll32 url.dll,FileProtocolHandler '.s:ShellEscape(winfname,1)) - elseif executable("rundll32") -" call Decho("(netrw#BrowseX) win32unix+rundll32",'~'.expand("")) - call s:NetrwExe('sil !rundll32 url.dll,FileProtocolHandler '.s:ShellEscape(winfname,1)) - elseif executable("cygstart") -" call Decho("(netrw#BrowseX) win32unix+cygstart",'~'.expand("")) - call s:NetrwExe('sil !cygstart '.s:ShellEscape(fname,1)) - else - call netrw#ErrorMsg(s:WARNING,"rundll32 not on path",74) - endif - let ret= v:shell_error - - elseif has("unix") && $DESKTOP_SESSION == "mate" && executable("atril") -" call Decho("(netrw#BrowseX) unix and atril",'~'.expand("")) - if a:fname =~ '^https\=://' - " atril does not appear to understand how to handle html -- so use gvim to edit the document - let use_ctrlo= 0 -" call Decho("fname<".fname.">") -" call Decho("a:fname<".a:fname.">") - call s:NetrwExe("sil! !gvim ".fname.' -c "keepj keepalt file '.fnameescape(a:fname).'"') - - else - call s:NetrwExe("sil !atril ".s:ShellEscape(fname,1).redir) - endif - let ret= v:shell_error - - elseif has("unix") && executable("kfmclient") && s:CheckIfKde() -" call Decho("(netrw#BrowseX) unix and kfmclient",'~'.expand("")) - call s:NetrwExe("sil !kfmclient exec ".s:ShellEscape(fname,1)." ".redir) - let ret= v:shell_error - - elseif has("unix") && executable("exo-open") && executable("xdg-open") && executable("setsid") -" call Decho("(netrw#BrowseX) unix, exo-open, xdg-open",'~'.expand("")) - call s:NetrwExe("sil !setsid xdg-open ".s:ShellEscape(fname,1).redir.'&') - let ret= v:shell_error - - elseif has("unix") && executable("xdg-open") -" call Decho("(netrw#BrowseX) unix and xdg-open",'~'.expand("")) - call s:NetrwExe("sil !xdg-open ".s:ShellEscape(fname,1).redir.'&') - let ret= v:shell_error - - elseif has("macunix") && executable("open") -" call Decho("(netrw#BrowseX) macunix and open",'~'.expand("")) - call s:NetrwExe("sil !open ".s:ShellEscape(fname,1)." ".redir) - let ret= v:shell_error + exe 'Launch' viewer viewopt shellescape(fname, 1) else - call netrw#ErrorMsg(s:ERROR, "Couldn't find a program to open '".a:fname."'", 0) - let ret=0 - endif - - if ret - call netrw#ErrorMsg(s:ERROR, "Failed to open '".a:fname."'", 0) + " though shellescape(..., 1) is used in Open, it's insufficient + exe 'Open' escape(fname, '#%') endif - " restoring redraw! after external file handlers - redraw! - " cleanup: remove temporary file, " delete current buffer if success with handler, " return to prior buffer (directory listing) @@ -5563,12 +5472,37 @@ fun! netrw#GX() if &ft == "netrw" let fname= s:NetrwGetWord() else - let fname= expand((exists("g:netrw_gx")? g:netrw_gx : '')) + let fname= exists("g:netrw_gx")? expand(g:netrw_gx) : s:GetURL() endif " call Dret("netrw#GX <".fname.">") return fname endfun +fun! s:GetURL() abort + let URL = '' + if exists('*Netrw_get_URL_' .. &filetype) + let URL = call('Netrw_get_URL_' .. &filetype, []) + endif + if !empty(URL) | return URL | endif + " URLs end in letter, digit or forward slash + let URL = matchstr(expand(""), '\<' .. g:netrw_regex_url .. '\ze[^A-Za-z0-9/]*$') + if !empty(URL) | return URL | endif + + " Is it a file in the current work dir ... + let file = expand("") + if filereadable(file) | return file | endif + " ... or in that of the current buffer? + let path = fnamemodify(expand('%'), ':p') + if isdirectory(path) + let dir = path + elseif filereadable(path) + let dir = fnamemodify(path, ':h') + endif + if exists('dir') && filereadable(dir..'/'..file) | return dir..'/'..file | endif + + return '' +endf + " --------------------------------------------------------------------- " netrw#BrowseXVis: used by gx in visual mode to select a file for browsing {{{2 fun! netrw#BrowseXVis() @@ -6733,6 +6667,7 @@ fun! s:NetrwMaps(islocal) nnoremap U :call NetrwBookHistHandler(5,b:netrw_curdir) nnoremap v :call NetrwSplit(2) nnoremap x :call netrw#BrowseX(NetrwBrowseChgDir(0,NetrwGetWord()),1) + nmap gx x if !hasmapto('NetrwHideEdit') nmap NetrwHideEdit endif @@ -12156,13 +12091,16 @@ endfun " s:NetrwExe: executes a string using "!" {{{2 fun! s:NetrwExe(cmd) " call Dfunc("s:NetrwExe(a:cmd<".a:cmd.">)") - if has("win32") && &shell !~? 'cmd\|pwsh\|powershell' && !g:netrw_cygwin + if has("win32") " call Decho("using win32:",expand("")) let savedShell=[&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash] set shell& shellcmdflag& shellxquote& shellxescape& set shellquote& shellpipe& shellredir& shellslash& - exe a:cmd - let [&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash] = savedShell + try + exe a:cmd + finally + let [&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash] = savedShell + endtry else " call Decho("exe ".a:cmd,'~'.expand("")) exe a:cmd diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index dd73ed2637a68..a9564374f5a17 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 21 +*pi_netrw.txt* For Vim version 9.1. Last change: 2024 Oct 27 ------------------------------------------------ NETRW REFERENCE MANUAL by Charles E. Campbell @@ -8,7 +8,7 @@ Author: Charles E. Campbell Copyright: Copyright (C) 2017 Charles E Campbell *netrw-copyright* The VIM LICENSE applies to the files in this package, including - netrw.vim, pi_netrw.txt, netrwFileHandlers.vim, netrwSettings.vim, and + netrw.vim, pi_netrw.txt, netrwSettings.vim, and syntax/netrw.vim. Like anything else that's free, netrw.vim and its associated files are provided *as is* and comes with no warranty of any kind, either expressed or implied. No guarantees of @@ -1469,42 +1469,93 @@ With either form of the command, netrw will first ask for confirmation that the removal is in fact what you want to do. If netrw doesn't have permission to remove a file, it will issue an error message. - *netrw-gx* + *netrw-gx* *Open* *Launch* CUSTOMIZING BROWSING WITH A SPECIAL HANDLER *netrw-x* *netrw-handler* {{{2 Certain files, such as html, gif, jpeg, (word/office) doc, etc, files, are best seen with a special handler (ie. a tool provided with your computer's -operating system). Netrw allows one to invoke such special handlers by: > +operating system). Netrw allows one to invoke such special handlers by: - * when Exploring, hit the "x" key - * when editing, hit gx with the cursor atop the special filename -< (latter not available if the |g:netrw_nogx| variable exists) + * hitting gx with the cursor atop the file path or alternatively x + in a netrw buffer; the former can be disabled by defining the + |g:netrw_nogx| variable + * when in command line, typing :Open -Netrw determines which special handler by the following method: +One may also use visual mode (see |visual-start|) to select the text that the +special handler will use. Normally gx checks for a close-by URL or file name +to pick up the text under the cursor; one may change what |expand()| uses via the +|g:netrw_gx| variable (options include "", ""). Note that +expand("") depends on the |'isfname'| setting. Alternatively, one may +select the text to be used by gx by making a visual selection (see +|visual-block|) and then pressing gx. - * if |g:netrw_browsex_viewer| exists, then it will be used to attempt to - view files. Examples of useful settings (place into your <.vimrc>): > +The selection function can be adapted for each filetype by adding a function +Netrw_get_URL_, where is given by &filetype. +The function should return the URL or file name to be used by gx, and will +fall back to the default behavior if it returns an empty string. +For example, special handlers for links Markdown and HTML are +> +" make gx work on concealed links regardless of exact cursor position +function Netrw_get_URL_markdown() + " markdown URL such as [link text](http://ya.ru 'yandex search') + try + let save_view = winsaveview() + if searchpair('\[.\{-}\](', '', ')\zs', 'cbW', '', line('.')) > 0 + return matchstr(getline('.')[col('.')-1:], '\[.\{-}\](\zs' .. g:netrw_regex_url .. '\ze\(\s\+.\{-}\)\?)') + endif + finally + call winrestview(save_view) + return '' + endtry +endfunction + +function Netrw_get_URL_html() + " HTML URL such as Python is here + " + try + let save_view = winsaveview() + if searchpair('\|/>\)\zs', 'cbW', '', line('.')) > 0 + return matchstr(getline('.')[col('.') - 1 : ], + \ 'href=["'.."'"..']\?\zs\S\{-}\ze["'.."'"..']\?/\?>') + endif + finally + call winrestview(save_view) + return '' + endtry +endfunction +< - :let g:netrw_browsex_viewer= "kfmclient exec" -< or > - :let g:netrw_browsex_viewer= "xdg-open" +Other than a file path, the text under the cursor may be a URL. Netrw uses +by default the following regular expression to determine if the text under the +cursor is a URL: +> + g:netrw_regex_url = '\%(\%(http\|ftp\|irc\)s\?\|file\)://\S\{-}' < + +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>): If the viewer you wish to use does not support handling of a remote URL directory, set |g:netrw_browsex_support_remote| to 0. - * for Windows 32 or 64, the URL and FileProtocolHandler dlls are used. - * for Gnome (with gnome-open): gnome-open is used. - * for KDE (with kfmclient) : kfmclient is used - * for Mac OS X : open is used. + * otherwise: -The gx mapping extends to all buffers; apply "gx" while atop a word and netrw -will apply a special handler to it (like "x" works when in a netrw buffer). -One may also use visual mode (see |visual-start|) to select the text that the -special handler will use. Normally gx uses expand("") to pick up the -text under the cursor; one may change what |expand()| uses via the -|g:netrw_gx| variable (options include "", ""). Note that -expand("") depends on the |'isfname'| setting. Alternatively, one may -select the text to be used by gx by making a visual selection (see -|visual-block|) and then pressing gx. + * for Windows : explorer.exe is used + * for Mac OS X : open is used. + * for Linux : xdg-open is used. + +To open a file by the appropriate handler, type + + :Open + +No escaping, neither for the shell, nor for Vim's command-line is needed. + +To launch a specific application , often being , + + :Launch . + +Since can be arbitrarily complex, in particular contain many file +paths, the escaping is left to the user. Associated setting variables: |g:netrw_gx| control how gx picks up the text under the cursor diff --git a/runtime/doc/tags b/runtime/doc/tags index 75359f2695637..9e93a7538942b 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -5566,6 +5566,7 @@ KeyInputPre autocmd.txt /*KeyInputPre* Kibaale uganda.txt /*Kibaale* Korean mbyte.txt /*Korean* L motion.txt /*L* +Launch pi_netrw.txt /*Launch* Linux-backspace options.txt /*Linux-backspace* List eval.txt /*List* Lists eval.txt /*Lists* @@ -5621,6 +5622,7 @@ OS390-open-source os_390.txt /*OS390-open-source* Object vim9class.txt /*Object* OffTheSpot mbyte.txt /*OffTheSpot* OnTheSpot mbyte.txt /*OnTheSpot* +Open pi_netrw.txt /*Open* Operator-pending intro.txt /*Operator-pending* Operator-pending-mode intro.txt /*Operator-pending-mode* OptionSet autocmd.txt /*OptionSet* diff --git a/runtime/plugin/netrwPlugin.vim b/runtime/plugin/netrwPlugin.vim index c70e6518fffc4..59fb7e727ee74 100644 --- a/runtime/plugin/netrwPlugin.vim +++ b/runtime/plugin/netrwPlugin.vim @@ -1,9 +1,10 @@ " netrwPlugin.vim: Handles file transfer and remote directory listing across a network " PLUGIN SECTION " Maintainer: This runtime file is looking for a new maintainer. -" Date: Feb 09, 2021 +" Date: Sep 09, 2021 " Last Change: " 2024 May 08 by Vim Project: cleanup legacy Win9X checks +" 2024 Oct 27 by Vim Project: cleanup gx mapping " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim " Copyright: Copyright (C) 1999-2021 Charles E. Campbell {{{1 @@ -31,6 +32,87 @@ set cpo&vim " --------------------------------------------------------------------- " Public Interface: {{{1 +" Commands Launch/URL {{{2 +" surpress output of command; use bang for GUI applications + +" set up redirection (avoids browser messages) +" by default, g:netrw_suppress_gx_mesg is true +if get(g:, ':netrw_suppress_gx_mesg', 1) + if &srr =~# "%s" + let s:redir = printf(&srr, has("win32") ? "nul" : "/dev/null") + else + let s:redir= &srr .. (has("win32") ? "nul" : "/dev/null") + endif +else + let s:redir= "" +endif + +if has('unix') + if has('win32unix') + " If cygstart provided, then assume Cygwin and use cygstart --hide; see man cygstart. + if executable('cygstart') + command -complete=shellcmd -nargs=1 -bang Launch + \ exe 'silent ! cygstart --hide' trim() s:redir | redraw! + elseif !empty($MSYSTEM) && executable('start') + " MSYS2/Git Bash comes by default without cygstart; see + " https://www.msys2.org/wiki/How-does-MSYS2-differ-from-Cygwin + " Instead it provides /usr/bin/start script running `cmd.exe //c start` + " Adding "" //b` sets void title, hides cmd window and blocks path conversion + " of /b to \b\ " by MSYS2; see https://www.msys2.org/docs/filesystem-paths/ + command -complete=shellcmd -nargs=1 -bang Launch + \ exe 'silent !start "" //b' trim() s:redir | redraw! + else + " imitate /usr/bin/start script for other environments and hope for the best + command -complete=shellcmd -nargs=1 -bang Launch + \ exe 'silent !cmd //c start "" //b' trim() s:redir | redraw! + endif + elseif exists('$WSL_DISTRO_NAME') " use cmd.exe to start GUI apps in WSL + command -complete=shellcmd -nargs=1 -bang Launch execute ':silent !'.. + \ (( =~? '\v<\f+\.(exe|com|bat|cmd)>') ? + \ 'cmd.exe /c start "" /b' trim() : + \ 'nohup ' trim() s:redir '&') + \ | redraw! + else + command -complete=shellcmd -nargs=1 -bang Launch + \ exe ':silent ! nohup' trim() s:redir '&' | redraw! + endif +elseif has('win32') + command -complete=shellcmd -nargs=1 -bang Launch + \ exe 'silent !'.. (&shell =~? '\' ? '' : 'cmd.exe /c') + \ 'start /b ' trim() s:redir | redraw! +endif +if exists(':Launch') == 2 + " Git Bash + if has('win32unix') + " start suffices + let s:cmd = '' + " Windows / WSL + elseif executable('explorer.exe') + let s:cmd = 'explorer.exe' + " Linux / BSD + elseif executable('xdg-open') + let s:cmd = 'xdg-open' + " MacOS + elseif executable('open') + let s:cmd = 'open' + else + s:cmd = '' + endif + function s:Open(cmd, file) + if empty(a:cmd) && !exists('g:netrw_browsex_viewer') + echoerr "No program to open this path found. See :help Open for more information." + else + Launch cmd shellescape(a:file, 1) + endif + endfunction + command -complete=file -nargs=1 Open call s:Open(s:cmd, ) +endif + +if !exists('g:netrw_regex_url') + let g:netrw_regex_url = '\%(\%(http\|ftp\|irc\)s\?\|file\)://\S\{-}' +endif + +" " }}} " Local Browsing Autocmds: {{{2 augroup FileExplorer au!