| 1 | module help_display_module |
| 2 | use iso_fortran_env, only: input_unit |
| 3 | use terminal_io_module, only: terminal_clear_screen, terminal_hide_cursor, terminal_show_cursor, & |
| 4 | terminal_move_cursor, terminal_write |
| 5 | use input_handler_module, only: get_key_input |
| 6 | use editor_state_module |
| 7 | implicit none |
| 8 | private |
| 9 | |
| 10 | public :: show_help, show_tags_modal, display_tags_header, show_fuss_hints |
| 11 | |
| 12 | contains |
| 13 | |
| 14 | subroutine show_help(editor) |
| 15 | type(editor_state_t), intent(in) :: editor |
| 16 | character(len=100), allocatable :: help_lines(:) |
| 17 | integer :: n_lines, viewport_start, viewport_size |
| 18 | integer :: row, max_rows |
| 19 | character(len=32) :: key_input |
| 20 | integer :: status |
| 21 | logical :: done |
| 22 | |
| 23 | max_rows = editor%screen_rows |
| 24 | |
| 25 | ! Build help content array |
| 26 | call build_help_content(help_lines, n_lines) |
| 27 | |
| 28 | ! Initialize viewport |
| 29 | viewport_start = 1 |
| 30 | viewport_size = max_rows - 4 ! Leave room for header and footer |
| 31 | |
| 32 | done = .false. |
| 33 | do while (.not. done) |
| 34 | ! Clear screen and hide cursor |
| 35 | call terminal_clear_screen() |
| 36 | call terminal_hide_cursor() |
| 37 | |
| 38 | ! Header |
| 39 | call terminal_move_cursor(1, 1) |
| 40 | call terminal_write("FACSIMILE HELP - Navigate: ↑↓/jk/PgUp/PgDn, Quit: q/ESC") |
| 41 | call terminal_move_cursor(2, 1) |
| 42 | call terminal_write(repeat("=", 70)) |
| 43 | |
| 44 | ! Display visible portion of help |
| 45 | call display_help_viewport(help_lines, n_lines, viewport_start, viewport_size, 3) |
| 46 | |
| 47 | ! Footer with scroll indicator |
| 48 | row = max_rows - 1 |
| 49 | call terminal_move_cursor(row, 1) |
| 50 | call terminal_write(repeat("=", 70)) |
| 51 | row = max_rows |
| 52 | call terminal_move_cursor(row, 1) |
| 53 | if (n_lines > viewport_size) then |
| 54 | write(key_input, '(a,i0,a,i0,a,i0,a,i0,a)') "Lines ", viewport_start, "-", & |
| 55 | min(viewport_start + viewport_size - 1, n_lines), " of ", n_lines, & |
| 56 | " (", int(real(viewport_start) * 100.0 / real(max(1, n_lines - viewport_size + 1))), "%)" |
| 57 | call terminal_write(trim(key_input)) |
| 58 | else |
| 59 | call terminal_write("All content visible") |
| 60 | end if |
| 61 | |
| 62 | ! Show cursor |
| 63 | call terminal_move_cursor(max_rows, 1) |
| 64 | call terminal_show_cursor() |
| 65 | |
| 66 | ! Handle navigation |
| 67 | call get_key_input(key_input, status) |
| 68 | if (status == 0) then |
| 69 | select case(trim(key_input)) |
| 70 | case('q', 'Q', 'esc', 'ctrl-/', 'ctrl-?') |
| 71 | done = .true. |
| 72 | case('up', 'k') |
| 73 | if (viewport_start > 1) viewport_start = viewport_start - 1 |
| 74 | case('down', 'j') |
| 75 | if (viewport_start + viewport_size - 1 < n_lines) viewport_start = viewport_start + 1 |
| 76 | case('pageup') |
| 77 | viewport_start = max(1, viewport_start - viewport_size) |
| 78 | case('pagedown') |
| 79 | if (viewport_start + viewport_size - 1 < n_lines) then |
| 80 | viewport_start = min(n_lines - viewport_size + 1, viewport_start + viewport_size) |
| 81 | end if |
| 82 | case('home') |
| 83 | viewport_start = 1 |
| 84 | case('end') |
| 85 | if (n_lines > viewport_size) then |
| 86 | viewport_start = n_lines - viewport_size + 1 |
| 87 | end if |
| 88 | end select |
| 89 | end if |
| 90 | end do |
| 91 | |
| 92 | ! Cleanup |
| 93 | if (allocated(help_lines)) deallocate(help_lines) |
| 94 | |
| 95 | ! Redraw will happen after returning |
| 96 | end subroutine show_help |
| 97 | |
| 98 | subroutine build_help_content(lines, n_lines) |
| 99 | character(len=100), allocatable, intent(out) :: lines(:) |
| 100 | integer, intent(out) :: n_lines |
| 101 | integer :: i |
| 102 | |
| 103 | ! Count total lines needed (sections + items + spacing) |
| 104 | n_lines = 0 |
| 105 | n_lines = n_lines + 11 + 2 ! NAVIGATION |
| 106 | n_lines = n_lines + 6 + 2 ! SELECTION |
| 107 | n_lines = n_lines + 11 + 2 ! EDITING |
| 108 | n_lines = n_lines + 4 + 2 ! CLIPBOARD |
| 109 | n_lines = n_lines + 3 + 2 ! LINES |
| 110 | n_lines = n_lines + 9 + 2 ! SEARCH & REPLACE |
| 111 | n_lines = n_lines + 5 + 2 ! MULTIPLE CURSORS (increased from 4) |
| 112 | n_lines = n_lines + 6 + 2 ! SPECIAL |
| 113 | n_lines = n_lines + 7 + 2 ! TABS |
| 114 | n_lines = n_lines + 7 + 2 ! PANES |
| 115 | n_lines = n_lines + 10 + 2 ! GIT |
| 116 | n_lines = n_lines + 5 + 2 ! FILE |
| 117 | n_lines = n_lines + 7 + 2 ! LSP (added code actions) |
| 118 | |
| 119 | allocate(lines(n_lines)) |
| 120 | i = 1 |
| 121 | |
| 122 | ! NAVIGATION |
| 123 | lines(i) = "NAVIGATION"; i = i + 1 |
| 124 | lines(i) = " arrows move cursor"; i = i + 1 |
| 125 | lines(i) = " ctrl-a/home smart home (toggle)"; i = i + 1 |
| 126 | lines(i) = " ctrl-e/end end of line"; i = i + 1 |
| 127 | lines(i) = " ctrl-home/end file start/end"; i = i + 1 |
| 128 | lines(i) = " alt-left/right word jump"; i = i + 1 |
| 129 | lines(i) = " alt-[/alt-] jump to matching bracket"; i = i + 1 |
| 130 | lines(i) = " pageup/down page scroll"; i = i + 1 |
| 131 | lines(i) = " ctrl-g go to line:column"; i = i + 1 |
| 132 | lines(i) = " click position cursor"; i = i + 1 |
| 133 | lines(i) = " alt-click add/remove cursor"; i = i + 1 |
| 134 | lines(i) = ""; i = i + 1 |
| 135 | |
| 136 | ! SELECTION |
| 137 | lines(i) = "SELECTION"; i = i + 1 |
| 138 | lines(i) = " shift-arrows character selection"; i = i + 1 |
| 139 | lines(i) = " shift-alt-l/r word selection"; i = i + 1 |
| 140 | lines(i) = " shift-ctrl-a/e select to line start/end"; i = i + 1 |
| 141 | lines(i) = " shift-home/end select to line boundaries"; i = i + 1 |
| 142 | lines(i) = " shift-pageup/down page selection"; i = i + 1 |
| 143 | lines(i) = " esc clear selection"; i = i + 1 |
| 144 | lines(i) = ""; i = i + 1 |
| 145 | |
| 146 | ! EDITING |
| 147 | lines(i) = "EDITING"; i = i + 1 |
| 148 | lines(i) = " backspace/ctrl-h delete backward"; i = i + 1 |
| 149 | lines(i) = " delete delete forward"; i = i + 1 |
| 150 | lines(i) = " tab insert 4 spaces/indent"; i = i + 1 |
| 151 | lines(i) = " shift-tab dedent selection/line"; i = i + 1 |
| 152 | lines(i) = " ctrl-k kill line forward"; i = i + 1 |
| 153 | lines(i) = " ctrl-u kill line backward"; i = i + 1 |
| 154 | lines(i) = " ctrl-y yank from stack"; i = i + 1 |
| 155 | lines(i) = " alt-bksp delete word backward"; i = i + 1 |
| 156 | lines(i) = " alt-d delete word forward"; i = i + 1 |
| 157 | lines(i) = " ctrl-j join lines"; i = i + 1 |
| 158 | lines(i) = " ctrl-t transpose characters"; i = i + 1 |
| 159 | lines(i) = ""; i = i + 1 |
| 160 | |
| 161 | ! CLIPBOARD |
| 162 | lines(i) = "CLIPBOARD (uses system clipboard)"; i = i + 1 |
| 163 | lines(i) = " ctrl-x cut line/selection"; i = i + 1 |
| 164 | lines(i) = " ctrl-c copy line/selection"; i = i + 1 |
| 165 | lines(i) = " ctrl-v paste"; i = i + 1 |
| 166 | lines(i) = ""; i = i + 1 |
| 167 | |
| 168 | ! LINES |
| 169 | lines(i) = "LINES"; i = i + 1 |
| 170 | lines(i) = " alt-up/down move line"; i = i + 1 |
| 171 | lines(i) = " alt-shift-up/down duplicate line"; i = i + 1 |
| 172 | lines(i) = ""; i = i + 1 |
| 173 | |
| 174 | ! SEARCH & REPLACE |
| 175 | lines(i) = "SEARCH & REPLACE"; i = i + 1 |
| 176 | lines(i) = " ctrl-f search forward"; i = i + 1 |
| 177 | lines(i) = " ctrl-r find and replace"; i = i + 1 |
| 178 | lines(i) = " n next match (after ctrl-f)"; i = i + 1 |
| 179 | lines(i) = " N previous match (after ctrl-f)"; i = i + 1 |
| 180 | lines(i) = " ctrl-d select word & find next match"; i = i + 1 |
| 181 | lines(i) = " esc exit match mode / clear selections"; i = i + 1 |
| 182 | lines(i) = " alt-c (in search) toggle case sensitive"; i = i + 1 |
| 183 | lines(i) = " alt-w (in search) toggle whole word match"; i = i + 1 |
| 184 | lines(i) = ""; i = i + 1 |
| 185 | |
| 186 | ! MULTIPLE CURSORS |
| 187 | lines(i) = "MULTIPLE CURSORS"; i = i + 1 |
| 188 | lines(i) = " ctrl-d select word & add cursor at next match"; i = i + 1 |
| 189 | lines(i) = " alt-click add/remove cursor at position"; i = i + 1 |
| 190 | lines(i) = " ctrl-alt-up/down add cursor on line above/below"; i = i + 1 |
| 191 | lines(i) = " esc reduce to single cursor"; i = i + 1 |
| 192 | lines(i) = ""; i = i + 1 |
| 193 | |
| 194 | ! SPECIAL |
| 195 | lines(i) = "SPECIAL"; i = i + 1 |
| 196 | lines(i) = " alt-' cycle quotes"; i = i + 1 |
| 197 | lines(i) = " alt-shift-' remove brackets/quotes"; i = i + 1 |
| 198 | lines(i) = " ctrl-z undo"; i = i + 1 |
| 199 | lines(i) = " ctrl-]/ctrl-shift-z redo"; i = i + 1 |
| 200 | lines(i) = " ctrl-l clear/redraw screen"; i = i + 1 |
| 201 | lines(i) = ""; i = i + 1 |
| 202 | |
| 203 | ! TABS |
| 204 | lines(i) = "TABS"; i = i + 1 |
| 205 | lines(i) = " ctrl-t new empty tab"; i = i + 1 |
| 206 | lines(i) = " ctrl-w close current tab"; i = i + 1 |
| 207 | lines(i) = " ctrl-1 to ctrl-9 jump to tab 1-9 (or alt-1 to alt-9)"; i = i + 1 |
| 208 | lines(i) = " ctrl-0 jump to tab 10 (or alt-0)"; i = i + 1 |
| 209 | lines(i) = " ctrl-pageup previous tab (or ctrl-alt-left)"; i = i + 1 |
| 210 | lines(i) = " ctrl-pagedown next tab (or ctrl-alt-right)"; i = i + 1 |
| 211 | lines(i) = ""; i = i + 1 |
| 212 | |
| 213 | ! PANES |
| 214 | lines(i) = "PANES"; i = i + 1 |
| 215 | lines(i) = " alt-v split pane vertically"; i = i + 1 |
| 216 | lines(i) = " alt-s split pane horizontally"; i = i + 1 |
| 217 | lines(i) = " alt-q close current pane only"; i = i + 1 |
| 218 | lines(i) = " ctrl-w close pane (then tab if last)"; i = i + 1 |
| 219 | lines(i) = " alt-h/j/k/l navigate left/down/up/right (Vim style)"; i = i + 1 |
| 220 | lines(i) = " ctrl-shift-arrows navigate between panes (alternative)"; i = i + 1 |
| 221 | lines(i) = ""; i = i + 1 |
| 222 | |
| 223 | ! GIT (in fuss mode) |
| 224 | lines(i) = "GIT (in fuss mode - ctrl-b)"; i = i + 1 |
| 225 | lines(i) = " a stage file/add"; i = i + 1 |
| 226 | lines(i) = " u unstage file"; i = i + 1 |
| 227 | lines(i) = " m commit with message"; i = i + 1 |
| 228 | lines(i) = " p push to remote"; i = i + 1 |
| 229 | lines(i) = " f fetch from remote"; i = i + 1 |
| 230 | lines(i) = " l pull from remote"; i = i + 1 |
| 231 | lines(i) = " t create tag"; i = i + 1 |
| 232 | lines(i) = " d diff file in new tab"; i = i + 1 |
| 233 | lines(i) = " enter open file in editor"; i = i + 1 |
| 234 | lines(i) = ""; i = i + 1 |
| 235 | |
| 236 | ! FILE |
| 237 | lines(i) = "FILE"; i = i + 1 |
| 238 | lines(i) = " ctrl-b toggle file browser (fuss mode)"; i = i + 1 |
| 239 | lines(i) = " ctrl-s save"; i = i + 1 |
| 240 | lines(i) = " ctrl-q quit"; i = i + 1 |
| 241 | lines(i) = " ctrl-/ or ctrl-? show this help"; i = i + 1 |
| 242 | lines(i) = ""; i = i + 1 |
| 243 | |
| 244 | ! LSP (Language Server Protocol) |
| 245 | lines(i) = "LSP (Language Server Protocol)"; i = i + 1 |
| 246 | lines(i) = " ctrl-space code completion"; i = i + 1 |
| 247 | lines(i) = " F12/alt-g go to definition"; i = i + 1 |
| 248 | lines(i) = " shift-F12/alt-r find all references"; i = i + 1 |
| 249 | lines(i) = " alt-, (alt-comma) jump back (navigation history)"; i = i + 1 |
| 250 | lines(i) = " F2 rename symbol"; i = i + 1 |
| 251 | lines(i) = " F10/alt-. code actions (quick fixes)"; i = i + 1 |
| 252 | lines(i) = " F4/alt-o document symbols (outline)"; i = i + 1 |
| 253 | lines(i) = " F6/alt-p workspace symbols (search project)"; i = i + 1 |
| 254 | lines(i) = " F8/alt-e toggle diagnostics panel (errors)"; i = i + 1 |
| 255 | lines(i) = " ctrl-p command palette"; i = i + 1 |
| 256 | lines(i) = ""; i = i + 1 |
| 257 | |
| 258 | n_lines = i - 1 |
| 259 | end subroutine build_help_content |
| 260 | |
| 261 | subroutine display_help_viewport(lines, n_lines, start_line, viewport_size, start_row) |
| 262 | character(len=*), intent(in) :: lines(:) |
| 263 | integer, intent(in) :: n_lines, start_line, viewport_size, start_row |
| 264 | integer :: i, row, end_line |
| 265 | |
| 266 | row = start_row |
| 267 | end_line = min(start_line + viewport_size - 1, n_lines) |
| 268 | |
| 269 | do i = start_line, end_line |
| 270 | call terminal_move_cursor(row, 1) |
| 271 | call terminal_write(lines(i)) |
| 272 | row = row + 1 |
| 273 | end do |
| 274 | end subroutine display_help_viewport |
| 275 | |
| 276 | subroutine show_tags_modal(editor, tags, n_tags) |
| 277 | type(editor_state_t), intent(in) :: editor |
| 278 | character(len=256), intent(in) :: tags(:) |
| 279 | integer, intent(in) :: n_tags |
| 280 | integer :: row, i, max_display |
| 281 | character(len=32) :: key_input |
| 282 | integer :: status |
| 283 | |
| 284 | ! Clear screen and hide cursor |
| 285 | call terminal_clear_screen() |
| 286 | call terminal_hide_cursor() |
| 287 | |
| 288 | ! Title |
| 289 | row = 1 |
| 290 | call terminal_move_cursor(row, 1) |
| 291 | call terminal_write("EXISTING GIT TAGS - Press any key to continue") |
| 292 | row = row + 1 |
| 293 | call terminal_move_cursor(row, 1) |
| 294 | call terminal_write(repeat("=", 60)) |
| 295 | row = row + 2 |
| 296 | |
| 297 | ! Display tags |
| 298 | if (n_tags == 0) then |
| 299 | call terminal_move_cursor(row, 1) |
| 300 | call terminal_write(" (no tags found)") |
| 301 | row = row + 2 |
| 302 | else |
| 303 | ! Show up to screen_rows - 6 tags (leave room for header/footer) |
| 304 | max_display = min(n_tags, editor%screen_rows - 6) |
| 305 | do i = 1, max_display |
| 306 | call terminal_move_cursor(row, 3) |
| 307 | call terminal_write(trim(tags(i))) |
| 308 | row = row + 1 |
| 309 | end do |
| 310 | |
| 311 | if (n_tags > max_display) then |
| 312 | row = row + 1 |
| 313 | call terminal_move_cursor(row, 3) |
| 314 | call terminal_write("... and " // trim(int_to_str(n_tags - max_display)) // " more") |
| 315 | row = row + 1 |
| 316 | end if |
| 317 | row = row + 1 |
| 318 | end if |
| 319 | |
| 320 | ! Footer |
| 321 | if (row < editor%screen_rows - 1) then |
| 322 | row = editor%screen_rows - 1 |
| 323 | call terminal_move_cursor(row, 1) |
| 324 | call terminal_write(repeat("=", 60)) |
| 325 | end if |
| 326 | |
| 327 | ! Show cursor at bottom |
| 328 | call terminal_move_cursor(editor%screen_rows, 1) |
| 329 | call terminal_show_cursor() |
| 330 | |
| 331 | ! Wait for any key press |
| 332 | do |
| 333 | call get_key_input(key_input, status) |
| 334 | if (status == 0) exit ! Got a valid key, exit loop |
| 335 | end do |
| 336 | end subroutine show_tags_modal |
| 337 | |
| 338 | ! Helper function to convert integer to string |
| 339 | function int_to_str(val) result(str) |
| 340 | integer, intent(in) :: val |
| 341 | character(len=20) :: str |
| 342 | write(str, '(I0)') val |
| 343 | end function int_to_str |
| 344 | |
| 345 | ! Display fuss mode hints (compact help for ctrl-b mode) |
| 346 | subroutine show_fuss_hints(editor) |
| 347 | type(editor_state_t), intent(in) :: editor |
| 348 | integer :: row |
| 349 | character(len=32) :: key_input |
| 350 | integer :: status |
| 351 | |
| 352 | ! Clear screen and hide cursor |
| 353 | call terminal_clear_screen() |
| 354 | call terminal_hide_cursor() |
| 355 | |
| 356 | ! Title |
| 357 | row = 1 |
| 358 | call terminal_move_cursor(row, 1) |
| 359 | call terminal_write("FUSS MODE HINTS - Press any key to close") |
| 360 | row = row + 1 |
| 361 | call terminal_move_cursor(row, 1) |
| 362 | call terminal_write(repeat("=", 60)) |
| 363 | row = row + 2 |
| 364 | |
| 365 | ! Navigation |
| 366 | call terminal_move_cursor(row, 1) |
| 367 | call terminal_write("NAVIGATION") |
| 368 | row = row + 1 |
| 369 | call terminal_move_cursor(row, 3) |
| 370 | call terminal_write("j/k move to previous/next sibling") |
| 371 | row = row + 1 |
| 372 | call terminal_move_cursor(row, 3) |
| 373 | call terminal_write("→/← expand/collapse or enter/exit directory") |
| 374 | row = row + 1 |
| 375 | call terminal_move_cursor(row, 3) |
| 376 | call terminal_write("o/enter open file in editor") |
| 377 | row = row + 1 |
| 378 | call terminal_move_cursor(row, 3) |
| 379 | call terminal_write("space toggle directory expand/collapse") |
| 380 | row = row + 2 |
| 381 | |
| 382 | ! Git Operations |
| 383 | call terminal_move_cursor(row, 1) |
| 384 | call terminal_write("GIT OPERATIONS") |
| 385 | row = row + 1 |
| 386 | call terminal_move_cursor(row, 3) |
| 387 | call terminal_write("a stage file") |
| 388 | row = row + 1 |
| 389 | call terminal_move_cursor(row, 3) |
| 390 | call terminal_write("u unstage file") |
| 391 | row = row + 1 |
| 392 | call terminal_move_cursor(row, 3) |
| 393 | call terminal_write("d diff file in new tab") |
| 394 | row = row + 1 |
| 395 | call terminal_move_cursor(row, 3) |
| 396 | call terminal_write("m commit with message") |
| 397 | row = row + 1 |
| 398 | call terminal_move_cursor(row, 3) |
| 399 | call terminal_write("p push to remote") |
| 400 | row = row + 1 |
| 401 | call terminal_move_cursor(row, 3) |
| 402 | call terminal_write("f fetch from remote") |
| 403 | row = row + 1 |
| 404 | call terminal_move_cursor(row, 3) |
| 405 | call terminal_write("l pull from remote") |
| 406 | row = row + 1 |
| 407 | call terminal_move_cursor(row, 3) |
| 408 | call terminal_write("t create and push tag") |
| 409 | row = row + 2 |
| 410 | |
| 411 | ! Exit |
| 412 | call terminal_move_cursor(row, 1) |
| 413 | call terminal_write("EXIT") |
| 414 | row = row + 1 |
| 415 | call terminal_move_cursor(row, 3) |
| 416 | call terminal_write("esc/ctrl-b close fuss mode") |
| 417 | row = row + 1 |
| 418 | |
| 419 | ! Footer |
| 420 | if (row < editor%screen_rows - 1) then |
| 421 | row = editor%screen_rows - 1 |
| 422 | call terminal_move_cursor(row, 1) |
| 423 | call terminal_write(repeat("=", 60)) |
| 424 | end if |
| 425 | |
| 426 | ! Show cursor at bottom |
| 427 | call terminal_move_cursor(editor%screen_rows, 1) |
| 428 | call terminal_show_cursor() |
| 429 | |
| 430 | ! Wait for any key press |
| 431 | do |
| 432 | call get_key_input(key_input, status) |
| 433 | if (status == 0) exit ! Got a valid key, exit loop |
| 434 | end do |
| 435 | end subroutine show_fuss_hints |
| 436 | |
| 437 | ! Display tags header without waiting for input (for split view with prompt) |
| 438 | subroutine display_tags_header(editor, tags, n_tags) |
| 439 | type(editor_state_t), intent(in) :: editor |
| 440 | character(len=256), intent(in) :: tags(:) |
| 441 | integer, intent(in) :: n_tags |
| 442 | integer :: row, i, max_display |
| 443 | |
| 444 | ! Clear screen |
| 445 | call terminal_clear_screen() |
| 446 | call terminal_hide_cursor() |
| 447 | |
| 448 | ! Title |
| 449 | row = 1 |
| 450 | call terminal_move_cursor(row, 1) |
| 451 | call terminal_write("EXISTING GIT TAGS") |
| 452 | row = row + 1 |
| 453 | call terminal_move_cursor(row, 1) |
| 454 | call terminal_write(repeat("=", 50)) |
| 455 | row = row + 1 |
| 456 | |
| 457 | ! Display tags (reserve bottom 2 lines for prompt) |
| 458 | if (n_tags == 0) then |
| 459 | call terminal_move_cursor(row, 1) |
| 460 | call terminal_write(" (no tags found)") |
| 461 | else |
| 462 | ! Show up to screen_rows - 4 tags (leave room for header + prompt area) |
| 463 | max_display = min(n_tags, editor%screen_rows - 4) |
| 464 | do i = 1, max_display |
| 465 | call terminal_move_cursor(row, 3) |
| 466 | call terminal_write(trim(tags(i))) |
| 467 | row = row + 1 |
| 468 | end do |
| 469 | |
| 470 | if (n_tags > max_display) then |
| 471 | call terminal_move_cursor(row, 3) |
| 472 | call terminal_write("... and " // trim(int_to_str(n_tags - max_display)) // " more") |
| 473 | end if |
| 474 | end if |
| 475 | |
| 476 | ! Separator line before prompt area |
| 477 | call terminal_move_cursor(editor%screen_rows - 1, 1) |
| 478 | call terminal_write(repeat("-", 50)) |
| 479 | end subroutine display_tags_header |
| 480 | |
| 481 | end module help_display_module |