Commit Graph
37594 Commits
Author SHA1 Message Date
Justin M. Keyes 7d2249c579 docs: misc, :bcd, slug() 2026-08-06 10:27:29 +02:00
Barrett Ruth 8b0f33a1ab feat(dir): set buffer-local CWD #41174 2026-08-06 03:39:53 -04:00
Jan Edmund LazoandBram Moolenaar 54373e2453 vim-patch:8.2.1204: Vim9: true and false not recognized in Vim9 script (#41185)
Problem:    Vim9: true and false not recognized in Vim9 script.
Solution:   Recognize true and false.

https://github.com/vim/vim/commit/5d2eb0fff0fbe905da2c57fd73f7f127a73d1c99

Co-authored-by: Bram Moolenaar <Bram@vim.org>
2026-08-06 11:48:00 +08:00
zeertzjqandBogdan Barbu 139ffd91de vim-patch:8c93e2d: runtime(make): variables in make target lists use wrong highlighting (#41183)
Problem:  Variables in make target lists are highlighted as targets when
          the prerequisite list is non-empty.
Solution: Match target lists separately from prerequisite regions so
          that contained identifiers are highlighted correctly.  Add
          regression test.

closes: vim/vim#20947

https://github.com/vim/vim/commit/8c93e2d50dacabcd66cc4cb9573da497e98d3c26

Co-authored-by: Bogdan Barbu <l4b.bogdan.barbu@gmail.com>
2026-08-06 08:06:25 +08:00
a19dcb3108 vim-patch:9.2.0914: diff: undo after :diffget into an empty buffer leaves a line behind (#41181)
Problem:  After :diffget into an empty buffer, undo does not restore the
          empty buffer, the last line stays behind (Narendran
          Gopalakrishnan)
Solution: Include the empty line of the empty buffer in the undo
          information, it is deleted once the first line was obtained
          (Hirohito Higashi).

fixes:  vim/vim#20950
closes: vim/vim#20951

https://github.com/vim/vim/commit/c44f35ca1a4d8c0c78f327800fe2677c91c6cecb

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 07:17:17 +08:00
88c13ee43c vim-patch:9.2.0909: insert completion is slow to collect many matches (#41167)
Problem:  ins_compl_add() checks for a duplicate by scanning the whole
          match list, making collection of N matches quadratic.
Solution: Look matches up in a hashtab instead; each entry counts the
          matches with that string (Samuel Schlesinger).

closes: vim/vim#20926

https://github.com/vim/vim/commit/31b7b1a7da4e282ebdf09f3c1c3e16ded7b76e8a

Co-authored-by: Samuel Schlesinger <sgschlesinger@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-06 06:36:22 +08:00
Olivia Kinnear 6107629c5b feat(fs): vim.fs.normalize{plain:boolean} #41127
`opts.plain=true` does not expand tildes in addition to environment
variables, unlike `opts.expand_env=false`.

`opts.expand_env=false` is soft-deprecated.
2026-08-05 16:11:13 -04:00
github-actions[bot] f599e2b8ab docs: update version.c #41129
vim-patch:fe712ced6 Fix duplicated code that only appears in git.
vim-patch:8.2.1032: error message for declaring a variable cannot be translated
vim-patch:8.2.4344: Amiga: header file included twice
vim-patch:9.1.0979: VMS: type warning with $XDG_VIMRC_FILE
vim-patch:8f214168b runtime(doc): Update os-support section for Amiga OS
vim-patch:9.1.1894: global_runtime_dir appends /after directory when using XDG
vim-patch:9.2.0029: STRLEN() used for a string literal
vim-patch:4ed08ee60 runtime(doc): document Solaris as supported OS
vim-patch:9.2.0897: GTK3 X11 redraws are not coalesced
vim-patch:9.2.0900: FocusGained still triggered when closing dialog
vim-patch:bc71c0b3f runtime(doc): remove todo entries that are fixed
vim-patch:9.2.0903: Vim9: cannot use an exported function of an autoload import
vim-patch:9.2.0905: MS-Windows: ghost cursor with ligatures
vim-patch:78ebe0f42 CI: bump clang to v22 in ci-linux_asan

vim-patch:8.2.0972: Vim9 script variable declarations need a type
vim-patch:8.2.0973: Vim9: type is not checked when assigning to a script variable
vim-patch:8.2.1003: Vim9: return type of sort() is too generic
vim-patch:8.2.1024: Vim9: no error for using "let g:var = val"
vim-patch:8.2.1028: Vim9: no error for declaring buffer, window, etc. variable
vim-patch:8.2.3722: Amiga: superfluous messages for freeing lots of yanked text
vim-patch:8.2.3837: QNX: crash when compiled with GUI but using terminal
vim-patch:8.2.3881: QNX: crash when compiled with GUI but using terminal

vim-patch:9.1.0337: Missing entry for XDG vimrc file in :version
vim-patch:9.1.0345: Problem: gvimrc not sourced from XDG_CONFIG_HOME
vim-patch:9.1.0393: 'viewdir' not respecting $XDG_CONFIG_HOME
vim-patch:9.1.0680: VMS does not have defined uintptr_t
vim-patch:9.1.1803: Amiga: build errors
2026-08-05 15:37:48 -04:00
Justin M. Keyes ab80ea92cc fix(ui2): pager handling #41179
- Avoid shared state. Pass `focus` to set_pos()/expand_msg() instead of
  a shared `pager_focus` flag: the flag is only cleared when set_pos()
  actually enters the pager, so ":messages" from inside the pager left
  it set.
- pager_shown(): the pager window is invalid after leaving it with "q".
- Reuse pager_shown() in expand_msg().
2026-08-05 15:07:19 -04:00
Erdiansyah a29a9130a9 fix(ui2): do not steal focus when consecutive cmds emit messages #41062
Problem:  A message emitted while a previous expanded message is still
          visible opens the pager and enters it, moving focus away from
          the buffer window without an explicit request (#41061).
Solution: Only enter the pager when it was explicitly requested ("g<",
          :messages, or entered from the expanded cmdline). An unfocused
          pager is dismissed by the cmdline key handler, which stays armed
          across the cmdline and no longer dismisses on non-typed keys
          (#39221).
2026-08-05 14:07:59 -04:00
Oleh Kostiuk 23525dd4e3 fix(editorconfig): avoid trim_trailing_whitespace in insert-mode #41175
Problem:
During insert-mode / replace-mode, `autowrite` may trigger. If it does, the
cursor position can shift due to the automatic removal of trailing spaces on the
current line. When I resume typing, the space between the last word and the new
word is suddenly gone.

Solution:
Disable the "remove trailing spaces" handler during Insert (or a similar) mode.
Autosave logic is not affected.
2026-08-05 14:06:28 -04:00
Barrett Ruth 69664a0aca fix(zip): preserve alternate file #41178 2026-08-05 13:37:24 -04:00
Barrett Ruth 9127ed41a5 fix(dir): preserve alternate file #41177 2026-08-05 13:36:58 -04:00
Tanishq e2c0c63452 fix(statusline): don't clobber global statusline during autocmd #41169
Problem:
With `laststatus=3`, a pager float shares the main grid's statusline
row. Setting a diagnostic fires `DiagnosticChanged`, whose handler calls
`nvim__redraw({ statusline = true })`.

Analysis:
Inside the autocmd, `curwin` is temporarily switched to the tiled window
showing that buffer, so `win_redr_status()` paints its statusline over
the pager's `[Pager]` statusline on the shared row. After the autocmd,
`curwin` is restored but the pager statusline is never repainted.

Solution:
Use `ctx_saved_curwin()` decide whether to draw the global statusline,
matching `win_redr_stl_expr()` and `update_screen()`. No behavior change
if no buffer-context switch is active.
2026-08-05 13:35:09 -04:00
Chris Hebert e58f29ca3e fix(terminal): OSC 52 multiline copy replaces newlines with NUL #41097
Problem: An OSC 52 sequence from a :terminal job passes the decoded
payload to the clipboard provider as a single list item. Command-line
providers (pbcopy, xclip, ...) receive it with channel semantics, where
a newline inside an item is sent as NUL (:h chansend()), so multiline
copies arrive with NUL bytes instead of newlines.

Solution: Split the payload on newlines into a proper list of lines.
A trailing newline yields a final empty item, which chansend() turns
back into a newline, so payloads round-trip exactly.
2026-08-05 06:37:02 -04:00
zeertzjq 2e3785a702 Merge pull request #41166 from zeertzjq/vim-f620c30
vim-patch: runtime file updates
2026-08-05 07:50:18 +08:00
zeertzjqandBogdan Barbu 743a8d448c vim-patch:5a1124e: runtime(c): compound literal braces are highlighted as errors
Problem: Braces in C compound literals and initializers inside parentheses
         and brackets are highlighted as errors.

Solution: Recognize those initializer blocks while preserving syntax recovery
          for malformed parentheses.

fixes:  vim/vim#18709
closes: vim/vim#20842

https://github.com/vim/vim/commit/5a1124e4f59fafa0c774db956ae1e86bdd259442

Co-authored-by: Bogdan Barbu <l4b.bogdan.barbu@gmail.com>
2026-08-05 07:02:22 +08:00
zeertzjqandChristian Brabandt e795115351 vim-patch:aeac948: runtime: Update Syntax Menus
Update makemenu.vim and re-generate synmenu.vim (using make menu).

closes:  vim/vim#20932
related: vim/vim#20930

https://github.com/vim/vim/commit/aeac948c6273076f666b473862af70e8b7e6c653

Co-authored-by: Christian Brabandt <cb@256bit.org>
2026-08-05 07:00:46 +08:00
zeertzjqandDoug Kearns 7fd2c868f7 vim-patch:f620c30: runtime(dart): Update compiler plugins
Use the unified dart command for all.

closes: vim/vim#20936

https://github.com/vim/vim/commit/f620c3001891e6f0abb1c97932af94d021c4e9a0

Co-authored-by: Doug Kearns <dougkearns@gmail.com>
2026-08-05 07:00:46 +08:00
glepnir 6d8401f8d5 fix(ui): missing vertical separator for a winbar only window (#41151)
Problem: A winbar-only window with zero text height still occupies one row,
         but win_update() returns early on w_view_height == 0 and skips the
         vertical separator.

Solution: Also draw the vertical separator in the early return path.
2026-08-05 06:42:39 +08:00
Justin M. Keyes 2f9ef98a33 test(chdir): cleanup #41161
Problem:
Some assertions are erroneously skipped for `not is_os('win')`.

Solution:
Update tests. Deduplicate logic.
2026-08-04 15:38:22 -04:00
Willaaaaaaa 7b03df5d54 feat(lua): vim.fs.slug() #41005
Problem:
Several subsystems need to derive a short, filesystem-safe identifier from an
arbitrary path, and each reinvents it ad-hoc:
- `'undodir'` and `swapfiles` encode the full path into a single filename, which
  may exceed filesystem length-limits.
- `:connect ssh://` needs the SSH ControlPath socket name to stay under the
  104-byte `sun_path` limit on macOS; today the path overflows it.
- the upcoming :terminal state dir.
- arbitrary plugin purposes.

Solution:
Provide `vim.fs.slug()`, which generates a bounded, one-way filename from an
arbitrary string. The input is normalized so equivalent paths produce the
same result. An 8-char hash is appended for uniqueness
2026-08-04 15:24:35 -04:00
Justin M. Keyes 90786766d2 Merge #33320 :bcd (buffer-local directory) 2026-08-04 15:10:30 -04:00
Justin M. Keyes 9cd4dd1c19 fix(:bcd): do not "inherit" buffer-local dir
Problem:
Buffer-local CWD (:bcd) is "sticky", similar to window-local CWD (:lcd).
But this contradicts one of its main benefits: per-buffer "project root"
for LSP, OSC7.

Other problems:
- A buffer created with :edit/:enew/:new silently inherits b_localdir
  (and b_prevdir) from the previous buffer.
- curbuf_reusable() refuses to recycle a scratch buffer that has
  `b_localdir`.
- After :new/:vnew/:tabnew the CWD sticks to previous buffer's
  `b_localdir` even though the new curbuf has none, so :new is not
  equivalent to ":split | enew", and getcwd() disagrees with
  haslocaldir().
- Requires "which buffer spawned this buffer" semantics that no other
  buffer-local state has.

Solution:
Drop sticky/inherit behavior of buffer-local CWD (:bcd).

- do_ecmd: always apply the new curbuf's dir (`fix_current_dir`), like
  `do_autochdir` already does. :tabnew from a :bcd buffer now reverts to
  global CWD (and fires DirChanged), same as :tabnew from a :lcd window.
- curbuf_reusable(): recycling a scratch buffer frees its b_localdir.

To get sticky/inherit behavior of CWD, use `:lcd`.
2026-08-04 20:48:44 +02:00
Justin M. Keyes 46ca236525 fix(cwd): validate getcwd(…, -1) 2026-08-04 20:48:44 +02:00
Justin M. Keyes db2e86fba4 refactor(editor): cleanup change-directory (:bcd) logic 2026-08-04 20:48:05 +02:00
saherandJustin M. Keyes ea3868bcf9 feat(editor): :bcd changes buffer-local directory
Problem:
No way to set a buffer-local directory.
Use-cases:
- "Root dir" for LSP (and the "project" concept).
- `:terminal` OSC 7

Solution:
Add `:bcd` command.

- Extend `getcwd()` to take a third arg; `getcwd(-1, -1, bunfr)` returns
  the buffer-local working directory.
- Buffer-local directories have less priority than window-local
  ones, and more priority than tab-local ones.

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-08-04 20:09:48 +02:00
Justin M. Keyes 838f130e6a fix(types): emmylua warning about params field 2026-08-04 20:09:48 +02:00
Justin M. Keyes 9c5afe6606 test: unreliable "nvim.zip … incorrect password" #41159
Problem:

    FAILED   …/plugin/zip_spec.lua @ 442: nvim.zip reports an incorrect archive password
    Expected values to be equal.
    Expected:
    true
    Actual:
    false
    stack traceback:
    …/plugin/zip_spec.lua:453: in function <…/plugin/zip_spec.lua:442>

Solution:
The message is scheduled, so poll for it.
2026-08-04 18:00:13 +00:00
not_compiled f6de99d028 fix(highlight): make Ignore hidden by default #41115
Problem:
Ignore is linked to Normal by default, making the text visible instead
of hidden.

Solution:
Replace the default link with an explicit highlight definition using
ctermfg=0 guifg=bg.
2026-08-04 13:43:22 -04:00
Justin M. Keyes ceccca7780 fix(options): crash on ":let &l:autoread = v:true" #41158
Problem:
Assigning to the local value of a global-local boolean option
('autoread', 'autocomplete', 'fsync') aborts:

    Assertion failed: (curval.type == newval.type), function
    ex_let_option, file vars.c, line 1408.

    ex_let_one
    ex_let_vars
    ex_let
    execute_cmd0
    do_cmdline
    call_user_func
    ...
    eval_map_expr
    vgetorpeek
    vgetc
    state_enter
    main

A global-local option may have local value `kObjectTypeUnset`, but
`ex_let_option()` guards only `kObjectTypeNil`.

Solution:
When curval is Unset, resolve it to the inherited global value.
2026-08-04 13:28:26 -04:00
glepnir 387bd0fbe7 refactor(window): use window handle in frame layout log (#41153)
Problem: The frame layout debug log uses the obsolete window ID field.

Solution: Use the window handle field when printing window information.
2026-08-04 11:39:59 +00:00
Justin M. Keyes 597555ebc0 fix(options): crash on ":let &t_Co = v:true" #41152
Problem:
Assigning a Boolean or special value (v:true/v:false/v:null/v:none) to a TTY
option aborts:

    Assertion failed: (curval.type == newval.type), function ex_let_option, file vars.c, line 1408.
    3   libsystem_c.dylib   __assert_rtn + 284
    4   nvim                ex_let_one + 3308
    5   nvim                ex_let_vars + 112
    6   nvim                ex_let + 2356
    7   nvim                execute_cmd0 + 252
    8   nvim                do_cmdline + 9076
    9   nvim                call_user_func + 3320
    10  nvim                call_func + 2076
    11  nvim                get_func_tv + 696
    12  nvim                eval_func + 380
    20  nvim                eval_to_string_eap + 276
    21  nvim                eval_map_expr + 444
    22  nvim                vgetorpeek + 3172
    23  nvim                vgetc + 764

Solution:
Apply the string-type check to TTY options too, so a Boolean/special value
gives "E928: String required" instead of aborting. Valid string/number
assignments to `t_*` pseudo-options still silently no-op.
2026-08-04 11:06:47 +00:00
Justin M. Keyes dab5fab948 Merge #41114 from epithet/default-ruler-as-expression 2026-08-04 06:51:34 -04:00
Justin M. Keyes 8589447159 feat(detach): opt-in to "server keeps running" #41133
Problem:
By default, `nvim` does not survive if its host terminal dies. This is
inconvenient if you want to use Nvim as a "session manager" (like tmux).

Solution:
Let users opt-in to the "survive" behavior via `:detach!` (bang "!").
This marks the current UI as "detachable", so the server will not
self-exit if the UI channel closes.
2026-08-04 06:20:16 -04:00
Sébastien Hoffmann ca07e505f9 refactor(ruler)!: replace C implementation with 'rulerformat' expression
Problem:
The default 'ruler' is implemented in C instead of the 'statusline' DSL.

Solution:
Replace the C implementation with a default 'rulerformat' expression.
This is a continuation of #1248 and #33036.

Advantages:
- configuration is more discoverable, the default being a useful example
- users and plugins can augment the default
- code reuse and less C code to maintain
- ui2: due to the use of an item group with `minwid`, it can expand
  instead of truncating when the content gets too long, which is
  particularly useful for locales with long translations of Top/Bot/All

Implementation details:
As is the case for 'statusline', when trying to set 'rulerformat' to an
empty string, the default expression is restored instead, mimicking how
previously the default C implementation would have been activated.
Just like before, `:set rulerformat=` and `:set rulerformat&` have the
same effect, and the ruler is disabled with `:set noruler`.

The default expression uses an item group with `%=`, unlike the fallback
in the previous default statusline `%-14.(%l,%c%V%) %P`, because the
total width and how it is configured is immediately clear without
documentation, it is a more useful pattern in general that works when
both sides have flexible width, and it also works for vim, which is
useful for configuration sharing/reuse.

A truncation marker `%<` is added at the end to mimic how at small
screen widths, the scroll percentage would disappear first, so that the
cursor position can remain fully visible.

BREAKING CHANGES:
- `&rulerformat` can no longer be set to an empty string
- ui2: the default ruler is no longer of fixed width, but can expand
- at very small screen widths (< 36 columns)
  - ui2: it will no longer try to shrink white-space before truncating
  - it truncates gradually from the right, whereas previously, the
    scroll percentage would disappear all at once
- l10n can no longer add a space after the comma between line and column
  (this was only done for one language: Ukrainian)
2026-08-04 12:12:23 +02:00
bfredl 0abc9ccc19 Merge pull request #40772 from Rawan10101/wasm-browser
feat(wasm-emcc): add browser support for Neovim
2026-08-04 12:11:17 +02:00
Barrett Ruth a29297ac53 docs(api): buffer columns are byte indices #41137 2026-08-04 05:19:54 -04:00
Rocco Vaccone d0644230f1 fix(lsp): ignore (and log once) invalid documentSelector globs #41055
Problem:
Client:_get_registrations() errors if a documentSelector pattern is not
a valid glob (e.g. "**/**.dart" from dartls). The error discards
already-matched registrations and propagates to supports_method() and
the client/registerCapability handler, disabling capabilities unrelated
to the offending pattern.

Solution:
Skip invalid globs. Treat them as non-matching, and log once per client.

(Similar approach was taken for filewatcher globs: 4d9e5acfb5)
2026-08-04 05:14:15 -04:00
Justin M. Keyes c875b16714 Merge #41112 from erdivartanovich/dir-failed-open-recovery 2026-08-04 05:04:07 -04:00
zeertzjq 30b4c1b40d fix(ctx): missing options copy when loading hidden buffer #41149
It's necessary to copy the global 'fileencoding' to the buffer-local
value before entering the buffer, otherwise 'fileencoding' is changed
when reading the file, which will mark the file as modified.
2026-08-04 04:50:36 -04:00
Justin M. Keyes 434792787b Merge #41093 from barrettruth/feat/zip-finish 2026-08-04 04:46:33 -04:00
Christian Clason 942daa05c9 build(deps): bump luajit to 1edc3e52b 2026-08-04 10:14:18 +02:00
Sébastien Hoffmann 9be130304d refactor(statusline): simplify and remove dead code
- Remove code that is never executed because the ruler is never rendered
  separately for a window with visible statusline or when `ls=3`, in
  other words: the variables `part_of_status` and `in_status_line` were
  always false for the ruler and badly named for the statusline itself.
- Leave `maxwidth` unchanged after calling `stl_alloc_click_defs`.
- Don't reuse the window's click definitions for the ruler. Even though
  it doesn't seem to be a bug because statusline and ruler are never
  shown at the same time for the same window, the ruler currently
  doesn't support clicks anyway.
- Disentangle the different cases, in particular statusline- from ruler-
  specific code. Another example: `wp->w_wincol`, `wp->w_winrow`, and
  `wp->w_width` are always used together, but this was hard to see.
2026-08-04 06:36:58 +02:00
Sébastien Hoffmann 259e6fa9cc fix(ruler)!: consistent width in last line and statusline
Problem: Traditionally, the ruler in the last line is one cell shorter
than in the statusline, leaving the last cell of the screen blank.
According to code comments, this is in order to prevent unwanted
scrolling on "some" (unspecified, but presumably ancient) terminals.
Berkeley vi is more specific in its `vs_modeline` function: dumb
terminals with hardware scroll, SunOS 4.1.1 and Ultrix 4.2 curses.
(n)curses still has a similar limitation in `(w)addstr`, but apparently
only for historical reasons.

Maintaining the different widths leads to awkward inconsistencies when
the ruler is configured with 'rulerformat', except for the special case
where it contains a top-level `%=`. Shifting the ruler in the last line
to the left would be a solution, but the empty cell at the end doesn't
seem to be relevant anymore.

Solution: extend the ruler in the last line all the way to the right
edge of the screen, just like in the statusline. The exact same amount
of place will be available to the rest of the UI as before.

BREAKING CHANGE:
- the default ruler width is now 18 cells
- the last cell of the screen is no longer empty

Closes #41076
2026-08-04 06:36:58 +02:00
Sébastien Hoffmann 81261804a8 fix(ruler): always clear ruler when disabled
Problem: the ruler is not cleared in the following circumstances:
- ui1 is running
- 'rulerformat' is configured
- the default ruler was not previously visible in the last line, for
  example because 'rulerformat' is configured in init.lua
- 'ruler' is disabled without using the command-line, for example via
  key-binding (entering the command-line would clear the ruler)

The corresponding test case did not fail because 'rulerformat' was set
while the default ruler was shown.

Solution: use a dedicated variable for tracking whether the ui1 ruler
was previously shown in the last line. `did_ruler_col` is now only used
for setting `msg_col`, which is not implemented in the case where
'rulerformat' is configured.

Reorder the test code to make the individual checks more independent
from each other, and to reflect the future where 'rulerformat' will
never be empty. Note that the check where 'rulerformat' was configured
relied on the default ruler not being cleared and a stale "0," still
being shown in front of the new ruler - this is also fixed with ui2.
2026-08-04 06:36:58 +02:00
Sébastien Hoffmann dc21aa07f7 fix(ruler): no window-local highlights for last line 'rulerformat'
Fixes #38777 in case 'rulerformat' is set.

See PR 38879. Original message:
Problem:  When the 'ruler' is in the last line of the screen, it takes
          local highlight definitions of the current window, tripping an
          assert (since c1648cf).
Solution: Don't use window-local highlight definitions when the ruler is
          not part of a statusline.
2026-08-04 06:36:57 +02:00
zeertzjqandDoug Kearns 8d2b50c0ce vim-patch:c0da866: runtime: Add TOML entry to the syntax menu (#41145)
fixes:  vim/vim#20927
closes: vim/vim#20930

https://github.com/vim/vim/commit/c0da86685a416c08c90155acbd8aa7cf67103a70

Co-authored-by: Doug Kearns <dougkearns@gmail.com>
2026-08-04 08:41:13 +08:00
zeertzjqandSamuel Schlesinger 6303d3680c vim-patch:9.2.0906: slow transstr() with long strings (#41144)
Problem:  transstr() appends with STRCAT()/STRLEN() from the start of
          the result on every iteration, making it quadratic to the
          length of the string.
Solution: Keep a tail pointer and append at it. (Samuel Schlesinger).

closes: vim/vim#20925

https://github.com/vim/vim/commit/124c86868c253a5ec1347e7cbe102504d2d66a07

Co-authored-by: Samuel Schlesinger <sgschlesinger@gmail.com>
2026-08-04 08:40:46 +08:00
zeertzjq 21a0227d2f vim-patch:9.2.0904: "zb" scrolls incorrectly with cursor just above fold (#41143)
Problem:  "zb" scrolls incorrectly with cursor just above fold.
Solution: Handle boff.lnum being set to the last line of a fold
          (zeertzjq).

With the cursor just above fold, botline_forw() moves boff.lnum to the
last line of the fold, but curwin->w_botline is at the first line of the
fold, so the boff.lnum == curwin->w_botline condition never holds.

Instead, check that boff.lnum has just moved to or past w_botline by
comparing its previous value with w_botline.

Also make a similar change to the loff.lnum check above for symmetry.
That one doesn't change behavior, as topline_back() sets loff.lnum to
the first line of a fold.

related: neovim/neovim#41122
closes:  vim/vim#20923

https://github.com/vim/vim/commit/aee686334c2137f8a94b04de130a3f51d928a7ed
2026-08-03 23:43:09 +00:00