patch 9.2.0502: runtime(netrw): bookmark handling can be improved

Commit: 
https://github.com/vim/vim/commit/35b767a090cc7b918dcafc9feb1a78cf0938d6bc
Author: J. Paulo Seibt <[email protected]>
Date:   Tue May 19 18:51:14 2026 +0000

    patch 9.2.0502: runtime(netrw): bookmark handling can be improved
    
    Problem:  To goto or delete a bookmark, one needs to prefix a count
              for the bookmark number (e.g., "2gb" to open 
bookmarkhttps://github.com/vim/vim/issues/2).
              As the bookmark list gets or deletes entries, the numbers
              keep changing, requiring listing the bookmarks with qb to
              discover the desired bookmark number. Typing gb or mB
              without a count targets g:netrw_bookmarklist[-1].
    Solution: If no count is given to gb or mB, list all bookmarks and
              prompt for a number using inputlist(), similar to tag jump
              with g].
    
    closes: #20211
    
    Signed-off-by: J. Paulo Seibt <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt
index 3f744bc8f..6f20073d5 100644
--- a/runtime/doc/pi_netrw.txt
+++ b/runtime/doc/pi_netrw.txt
@@ -1047,7 +1047,7 @@ QUICK REFERENCE: MAPS                             
*netrw-browse-maps* {{{2
           C    Setting the editing window                           |netrw-C|
           d    Make a directory                                     |netrw-d|
           D    Attempt to remove the file(s)/directory(ies)         |netrw-D|
-          gb   Go to previous bookmarked directory                  |netrw-gb|
+          gb   Go to bookmark                                       |netrw-gb|
           gd   Force treatment as directory                         |netrw-gd|
           gf   Force treatment as file                              |netrw-gf|
           gh   Quick hide/unhide of dot-files                       |netrw-gh|
@@ -1056,11 +1056,12 @@ QUICK REFERENCE: MAPS                           
*netrw-browse-maps* {{{2
           i    Cycle between thin, long, wide, and tree listings    |netrw-i|
           I    Toggle the displaying of the banner                  |netrw-I|
           mb   Bookmark current directory                           |netrw-mb|
+          mB   Delete bookmark                                      |netrw-mB|
           mc   Copy marked files to marked-file target directory    |netrw-mc|
           md   Apply diff to marked files (up to 3)                 |netrw-md|
           me   Place marked files on arg list and edit them         |netrw-me|
           mf   Mark a file                                          |netrw-mf|
-          mF   Unmark files                                         |netrw-mF|
+          mF   Unmark buffer-local files                            |netrw-mF|
           mg   Apply vimgrep to marked files                        |netrw-mg|
           mh   Toggle marked file suffices' presence on hiding list |netrw-mh|
           mm   Move marked files to marked-file target directory    |netrw-mm|
@@ -1365,13 +1366,16 @@ Currently, this only works for local files.
 Associated setting variables: |g:netrw_chgperm|
 
 
-CHANGING TO A BOOKMARKED DIRECTORY                     *netrw-gb*  {{{2
+CHANGING TO A BOOKMARKED PATH                  *netrw-gb*  {{{2
 
-To change directory back to a bookmarked directory, use
+To change to a bookmarked path, use
 
-       {cnt}gb
+       [{cnt}]gb
 
 Any count may be used to reference any of the bookmarks.
+If {cnt} is omitted, it shows a list of the current bookmarks
+and prompts for a bookmark number to go to.
+
 Note that |netrw-qb| shows both bookmarks and history; to go
 to a location stored in the history see |netrw-u| and |netrw-U|.
 
@@ -1434,10 +1438,13 @@ DELETING BOOKMARKS                                      
*netrw-mB* {{{2
 
 To delete a bookmark, use >
 
-       {cnt}mB
+       [{cnt}]mB
 
 If there are marked files, then mB will remove them from the
 bookmark list.
+If no files are marked and {cnt} is omitted, it shows a list
+of the current bookmarks and prompts for a bookmark number
+to delete.
 
 Alternatively, one may use :NetrwMB! (see |netrw-:NetrwMB|). >
 
diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw.vim 
b/runtime/pack/dist/opt/netrw/autoload/netrw.vim
index 1fdbeeb8f..89db6e3ca 100644
--- a/runtime/pack/dist/opt/netrw/autoload/netrw.vim
+++ b/runtime/pack/dist/opt/netrw/autoload/netrw.vim
@@ -2707,7 +2707,7 @@ endfunction
 
 "  s:NetrwBookHistHandler: {{{2
 "    0: (user: <mb>)   bookmark current directory
-"    1: (user: <gb>)   change to the bookmarked directory
+"    1: (user: <gb>)   change to the bookmarked path
 "    2: (user: <qb>)   list bookmarks
 "    3: (browsing)     records current directory history
 "    4: (user: <u>)    go up   (previous) directory, using history
@@ -2737,11 +2737,33 @@ function s:NetrwBookHistHandler(chg,curdir)
         endtry
 
     elseif a:chg == 1
-        " change to the bookmarked directory
-        if exists("g:netrw_bookmarklist[v:count-1]")
-            exe "NetrwKeepj e ".fnameescape(g:netrw_bookmarklist[v:count-1])
+        " change to bookmarked path
+        if exists("g:netrw_bookmarklist") && !empty(g:netrw_bookmarklist)
+            let len_bookmarklist = len(g:netrw_bookmarklist)
+            let bookmark_num = v:count
+
+            " v:count value is set to zero if no count (prefix) is given to 
the `gb` map
+            if bookmark_num == 0
+                " list bookmarks and prompt for a bookmark number
+                let goto_list = [" # | Goto Bookmark:"]
+                let i = 0
+                while i < len_bookmarklist
+                    call add(goto_list, printf("%3d| %s", i + 1, 
g:netrw_bookmarklist[i]))
+                    let i += 1
+                endwhile
+                let bookmark_num = inputlist(goto_list)
+            endif
+
+            if bookmark_num > 0
+                if bookmark_num <= len_bookmarklist
+                    exe "NetrwKeepj e " . 
fnameescape(g:netrw_bookmarklist[bookmark_num - 1])
+                else
+                    echomsg "Sorry, bookmark#" . bookmark_num . " doesn't 
exist!"
+                endif
+            endif
+            " Exit silently if user cancels with `q` or empty after inputlist()
         else
-            echomsg "Sorry, bookmark#".v:count." doesn't exist!"
+            echo "Bookmark list is empty."
         endif
 
     elseif a:chg == 2
@@ -2842,16 +2864,38 @@ function s:NetrwBookHistHandler(chg,curdir)
         endif
 
     elseif a:chg == 6
-        if exists("s:netrwmarkfilelist_{curbufnr}")
+        if exists("s:netrwmarkfilelist_{curbufnr}") && 
!empty(s:netrwmarkfilelist_{curbufnr})
             call s:NetrwBookmark(1)
             echo "removed marked files from bookmarks"
+        elseif exists("g:netrw_bookmarklist") && !empty(g:netrw_bookmarklist)
+            let len_bookmarklist = len(g:netrw_bookmarklist)
+            let bookmark_num = v:count
+
+            " v:count value is set to zero if no count (prefix) is given to 
the `gb` map
+            if bookmark_num == 0
+                " list bookmarks and prompt for a bookmark number
+                let goto_list = [" # | Delete Bookmark:"]
+                let i = 0
+                while i < len_bookmarklist
+                    call add(goto_list, printf("%3d| %s", i + 1, 
g:netrw_bookmarklist[i]))
+                    let i += 1
+                endwhile
+                let bookmark_num = inputlist(goto_list)
+            endif
+
+            if bookmark_num > 0
+                if bookmark_num <= len_bookmarklist
+                    let bookmark_path = g:netrw_bookmarklist[bookmark_num - 1]
+                    call s:MergeBookmarks()
+                    NetrwKeepj call remove(g:netrw_bookmarklist, bookmark_num 
- 1)
+                    echo "removed " . bookmark_path . " from 
g:netrw_bookmarklist."
+                else
+                    echomsg "Sorry, bookmark#" . bookmark_num . " doesn't 
exist!"
+                endif
+            endif
+            " Exit silently if user cancels with `q` or empty after inputlist()
         else
-            " delete the v:count'th bookmark
-            let iremove = v:count
-            let dremove = g:netrw_bookmarklist[iremove - 1]
-            call s:MergeBookmarks()
-            NetrwKeepj call remove(g:netrw_bookmarklist,iremove-1)
-            echo "removed ".dremove." from g:netrw_bookmarklist"
+            echo "Bookmark list is empty."
         endif
 
         try
diff --git a/runtime/pack/dist/opt/netrw/doc/netrw.txt 
b/runtime/pack/dist/opt/netrw/doc/netrw.txt
index 168deed34..2c5d6d822 100644
--- a/runtime/pack/dist/opt/netrw/doc/netrw.txt
+++ b/runtime/pack/dist/opt/netrw/doc/netrw.txt
@@ -1047,7 +1047,7 @@ QUICK REFERENCE: MAPS                             
*netrw-browse-maps* {{{2
           C    Setting the editing window                           |netrw-C|
           d    Make a directory                                     |netrw-d|
           D    Attempt to remove the file(s)/directory(ies)         |netrw-D|
-          gb   Go to previous bookmarked directory                  |netrw-gb|
+          gb   Go to bookmark                                       |netrw-gb|
           gd   Force treatment as directory                         |netrw-gd|
           gf   Force treatment as file                              |netrw-gf|
           gh   Quick hide/unhide of dot-files                       |netrw-gh|
@@ -1056,11 +1056,12 @@ QUICK REFERENCE: MAPS                           
*netrw-browse-maps* {{{2
           i    Cycle between thin, long, wide, and tree listings    |netrw-i|
           I    Toggle the displaying of the banner                  |netrw-I|
           mb   Bookmark current directory                           |netrw-mb|
+          mB   Delete bookmark                                      |netrw-mB|
           mc   Copy marked files to marked-file target directory    |netrw-mc|
           md   Apply diff to marked files (up to 3)                 |netrw-md|
           me   Place marked files on arg list and edit them         |netrw-me|
           mf   Mark a file                                          |netrw-mf|
-          mF   Unmark files                                         |netrw-mF|
+          mF   Unmark buffer-local files                            |netrw-mF|
           mg   Apply vimgrep to marked files                        |netrw-mg|
           mh   Toggle marked file suffices' presence on hiding list |netrw-mh|
           mm   Move marked files to marked-file target directory    |netrw-mm|
@@ -1365,13 +1366,16 @@ Currently, this only works for local files.
 Associated setting variables: |g:netrw_chgperm|
 
 
-CHANGING TO A BOOKMARKED DIRECTORY                     *netrw-gb*  {{{2
+CHANGING TO A BOOKMARKED PATH                  *netrw-gb*  {{{2
 
-To change directory back to a bookmarked directory, use
+To change to a bookmarked path, use
 
-       {cnt}gb
+       [{cnt}]gb
 
 Any count may be used to reference any of the bookmarks.
+If {cnt} is omitted, it shows a list of the current bookmarks
+and prompts for a bookmark number to go to.
+
 Note that |netrw-qb| shows both bookmarks and history; to go
 to a location stored in the history see |netrw-u| and |netrw-U|.
 
@@ -1434,10 +1438,13 @@ DELETING BOOKMARKS                                      
*netrw-mB* {{{2
 
 To delete a bookmark, use >
 
-       {cnt}mB
+       [{cnt}]mB
 
 If there are marked files, then mB will remove them from the
 bookmark list.
+If no files are marked and {cnt} is omitted, it shows a list
+of the current bookmarks and prompts for a bookmark number
+to delete.
 
 Alternatively, one may use :NetrwMB! (see |netrw-:NetrwMB|). >
 
diff --git a/src/testdir/test_plugin_netrw.vim 
b/src/testdir/test_plugin_netrw.vim
index 7cd2aa89e..76fa41092 100644
--- a/src/testdir/test_plugin_netrw.vim
+++ b/src/testdir/test_plugin_netrw.vim
@@ -330,7 +330,9 @@ func Test_netrw_parse_special_char_user()
   call assert_equal(result.path, 'test.txt')
 endfunction
 
-func Test_netrw_empty_buffer_fastpath_wipe()
+" Note: Test_netrw_a_empty_buffer_fastpath_wipe() should run before
+"       any other tests that open a netrw buffer (e.g, :Explore).
+func Test_netrw_a_empty_buffer_fastpath_wipe()
   " SetUp() may have opened some buffers
   let previous = bufnr('$')
   let g:netrw_fastbrowse=0
@@ -717,7 +719,44 @@ func Test_netrw_bookmark_marked_file()
 
   let g:netrw_keepdir = save_keepdir
   if save_bookmarklist is v:null
-    unlet g:netrw_bookmarklist
+    unlet! g:netrw_bookmarklist
+  else
+    let g:netrw_bookmarklist = save_bookmarklist
+  endif
+
+  bw!
+endfunc
+
+" Typing gb or mB without a count should prompt
+" for a bookmark number through an inputlist().
+" Expected dialog output (gb): # | Goto Bookmark:
+"                               1| /foo/bar/baz
+"
+" Expected dialog output (mB): # | Delete Bookmark:
+"                               1| /foo/bar/baz
+func Test_netrw_bookmark_goto_delete_prompt()
+  let save_home = g:netrw_home
+  let save_bookmarklist = exists('g:netrw_bookmarklist') ? 
g:netrw_bookmarklist : v:null
+
+  let g:netrw_home = getcwd()
+  let g:netrw_bookmarklist = ['/foo/bar/baz']
+  Explore .
+
+  " Inject 'q' to cancel the inputlist() prompt
+  call feedkeys('q', 't')
+  let dialog_out = execute('normal gb')
+  call assert_match('Goto Bookmark:', dialog_out)
+
+  call feedkeys('q', 't')
+  let dialog_out = execute('normal mB')
+  call assert_match('Delete Bookmark:', dialog_out)
+
+  " Tear down
+  call delete(g:netrw_home . '/.netrwbook')
+  call delete(g:netrw_home . '/.netrwhist')
+  let g:netrw_home = save_home
+  if save_bookmarklist is v:null
+    unlet! g:netrw_bookmarklist
   else
     let g:netrw_bookmarklist = save_bookmarklist
   endif
@@ -780,4 +819,5 @@ func Test_netrw_injection()
     unlet! g:netrw_home g:netrw_dirhistmax g:netrw_dirhistcnt 
g:netrw_dirhist_1 g:injected
   endtry
 endfunc
+
 " vim:ts=8 sts=2 sw=2 et
diff --git a/src/version.c b/src/version.c
index e6bc4886c..2e75367bf 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    502,
 /**/
     501,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1wPPfj-00DPyZ-3w%40256bit.org.

Raspunde prin e-mail lui