svn commit: r1932925 - subversion/trunk/subversion/svnbrowse

[email protected]
Newsgroups gmane.comp.version-control.subversion.svn
Message-ID <177574614025.1072893.1859891539228082898@svn03-he-fi>
Author: rinrab
Date: Thu Apr  9 14:49:00 2026
New Revision: 1932925

Log:
svnbrowse: More shortcuts for scrolling and moving around the list.

### Current controls ###

- kj, arrows - up/down
- CTRL-P, CTRL-N - also up/down, common in vim list views
- enter - enter, Unix terminals also produce '\n' via CTRL+M.
- backspace, u, '-' - up a directory. I think backspace would be pretty
  intuative as the default shortcut. u and '-' are stolen from vim's netrw.
  Well technically u is defined as "Change to recently-visited directory" but
  it's almost the same as going up and we're not going to implement history
  anytime soon.
- CTRL+Y/CTRL+E - scrolls one line up/down
- CTRL+U/CTRL+D - scrolls half-page up/down
- CTRL+B/CTRL+F (forward/backwards), page-up/page-down - scrolls whole page
  up/down
- g/HOME - select first element 
- G/END - select last element 
- z - center selection
- q/ESC - get out of here

TODO: Add repetition by entering a number+action that can be repeated (like
movement by one line). Also CTRL+U/CTRL+D should remember it for usages without
a number. (do we need all of that?)

Note: According to [1], it's a bad practise to use shortcuts like CTRL+arrow or
CTRL+SHIFT+KEY - TUI apps should only use basic combinations or
CTRL+alphabetical symbol.

If there is a useful keybind that I missed, please feel free to extend the
code.

* subversion/svnbrowse/svnbrowse.c
  (view_on_event): Factor out scrollsize local variable and implement movement
   from above.
* subversion/svnbrowse/model.c
  (svn_browse__model_scroll_in_view): Forbid scrolling into negatives.

[1] https://invisible-island.net/ncurses/ncurses.faq.html#modified_keys

Modified:
   subversion/trunk/subversion/svnbrowse/model.c
   subversion/trunk/subversion/svnbrowse/svnbrowse.c

Modified: subversion/trunk/subversion/svnbrowse/model.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/model.c	Thu Apr  9 13:51:29 2026	(r1932924)
+++ subversion/trunk/subversion/svnbrowse/model.c	Thu Apr  9 14:49:00 2026	(r1932925)
@@ -144,6 +144,9 @@ svn_browse__model_scroll_in_view(svn_bro
   state->scroller_offset = min(state->scroller_offset,
                                state->selection);
 
+  /* forbid scrolling into negatives */
+  state->scroller_offset = max(state->scroller_offset, 0);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/svnbrowse.c	Thu Apr  9 13:51:29 2026	(r1932924)
+++ subversion/trunk/subversion/svnbrowse/svnbrowse.c	Thu Apr  9 14:49:00 2026	(r1932925)
@@ -126,6 +126,9 @@ view_make(svn_browse__model_t *model, ap
 static svn_error_t *
 view_on_event(svn_browse__view_t *view, int ch, apr_pool_t *scratch_pool)
 {
+  /* scrollable height is one row less than the whole view */
+  int scrollsize = getmaxy(stdscr) - 1;
+
   /* ch is received from getch() which would read the next character/key with
    * the following additional rules:
    * 1. as we configured it to use keypad(), arrows and other special keys
@@ -139,10 +142,12 @@ view_on_event(svn_browse__view_t *view,
     {
       case KEY_UP:
       case 'k':
+      case CTRL('p'):
         SVN_ERR(svn_browse__model_move_selection(view->model, -1));
         break;
       case KEY_DOWN:
       case 'j':
+      case CTRL('n'):
         SVN_ERR(svn_browse__model_move_selection(view->model, 1));
         break;
       case '\n':
@@ -154,13 +159,45 @@ view_on_event(svn_browse__view_t *view,
       case 'u':
         SVN_ERR(svn_browse__model_go_up(view->model, scratch_pool));
         break;
+      case CTRL('e'):
+        view->model->current->scroller_offset += 1;
+        break;
+      case CTRL('y'):
+        view->model->current->scroller_offset -= 1;
+        break;
+      case CTRL('d'):
+        SVN_ERR(svn_browse__model_move_selection(view->model, scrollsize / 2));
+        break;
+      case CTRL('f'):
+      case KEY_NPAGE:
+        SVN_ERR(svn_browse__model_move_selection(view->model, scrollsize));
+        break;
+      case CTRL('u'):
+        SVN_ERR(svn_browse__model_move_selection(view->model, -scrollsize / 2));
+        break;
+      case CTRL('b'):
+      case KEY_PPAGE:
+        SVN_ERR(svn_browse__model_move_selection(view->model, -scrollsize));
+        break;
+      case 'g':
+      case KEY_HOME:
+        view->model->current->selection = 0;
+        break;
+      case 'G':
+      case KEY_END:
+        view->model->current->selection =
+            view->model->current->list->nelts - 1;
+        break;
+      case 'z':
+        view->model->current->scroller_offset =
+            view->model->current->selection - scrollsize / 2;
+        break;
       case 'q':
       case KEY_ESC:
         return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
     }
 
-  /* scrollable height is one row less than the whole view */
-  SVN_ERR(svn_browse__model_scroll_in_view(view->model, getmaxy(stdscr) - 1));
+  SVN_ERR(svn_browse__model_scroll_in_view(view->model, scrollsize));
 
   return SVN_NO_ERROR;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.