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; }
