markdown · 5079 bytes Raw Blame History

Tabs Implementation Plan for Facsimile

Overview

Add full tab support to facsimile, bridging the gap between GUI and terminal editors. Each tab represents an independent file buffer with its own cursor state and undo history.

Requirements

Core Features

  • Multiple file buffers open simultaneously
  • Tab bar at top of screen showing all open tabs
  • Active tab highlighted visually
  • Each tab maintains independent state:
    • Buffer content
    • Cursor position(s)
    • Undo/redo history
    • Viewport position
    • File path

Keybindings

  • alt-1 through alt-9: Jump to tab 1-9
  • ctrl-alt-left: Previous tab (with wrap-around)
  • ctrl-alt-right: Next tab (with wrap-around)
  • Check for conflicts with existing bindings (DONE - no conflicts)

Fuss Integration

  • Opening file in fuss mode creates new tab by default
  • New tab becomes active immediately
  • Fuss mode persists (already implemented)

UI/UX

  • Tab bar shows: [1: file1.txt] [2: file2.f90*] [3: README.md]
  • Active tab uses reverse video (char(27) // '[7m')
  • Modified files indicated with * suffix
  • Tab bar takes 1 row at top
  • Adjust editor viewport to account for tab bar (starts at row 2)
  • Tab bar updates automatically when switching tabs

Architecture Design

Data Structures

Tab Type (new)

type :: tab_t
    character(len=:), allocatable :: filename
    type(buffer_t) :: buffer
    type(cursor_t), allocatable :: cursors(:)
    integer :: active_cursor
    integer :: viewport_line
    integer :: viewport_column
    logical :: modified
end type tab_t

Editor State Updates

type(tab_t), allocatable :: tabs(:)
integer :: active_tab_index
integer :: max_tabs = 10  ! Support up to 10 tabs initially

File Changes

src/editor_state_module.f90

  • Add tab_t type definition
  • Add tabs array and active_tab_index to editor_state_t
  • Add procedures: create_tab, switch_tab, close_tab

src/terminal/renderer_module.f90

  • Add render_tab_bar() subroutine
  • Adjust main viewport to start at row 2 instead of row 1
  • Update render_screen() to call render_tab_bar()

src/commands/command_handler_module.f90

  • Add alt-1 through alt-9 handlers
  • Add ctrl-alt-left/right handlers
  • Modify open_file_in_editor() to create new tab
  • Add save/restore logic for tab switching

src/buffer_module.f90

  • Ensure buffer can be deep-copied for tab state
  • May need clone_buffer() function

Implementation Phases

Phase 1: Core Tab Infrastructure

  1. Define tab_t type
  2. Add tabs array to editor state
  3. Create basic tab management functions:
    • create_new_tab(editor, filename)
    • switch_to_tab(editor, tab_index)
    • get_current_tab(editor)

Phase 2: Tab Bar Rendering

  1. Implement render_tab_bar()
  2. Display tab index and filename
  3. Highlight active tab
  4. Show modification indicator
  5. Adjust viewport for tab bar

Phase 3: Navigation Keybindings

  1. Parse alt- key sequences
  2. Implement tab switching logic
  3. Add ctrl-alt-left/right navigation
  4. Save/restore cursor and viewport state

Phase 4: Fuss Integration

  1. Modify open_file_in_editor() to create tab
  2. Set new tab as active
  3. Test opening multiple files from fuss

Phase 5: Polish & Documentation

  1. Update ctrl-? help menu
  2. Test edge cases (max tabs, closing tabs, etc.)
  3. Handle unsaved changes warnings
  4. Performance testing with many tabs

Edge Cases to Handle

  • Opening same file in multiple tabs (allow or prevent?)
  • Maximum tab limit (10 initially)
  • Tab overflow (show scroll indicator if >10 tabs?)
  • Closing active tab (switch to next/previous)
  • Closing all tabs (keep at least one empty buffer?)
  • Modified file indicator updates
  • Tab bar width overflow (truncate long filenames)

Testing Plan

Manual Tests

  1. Create 3 tabs, verify each has independent buffer
  2. Switch between tabs with alt-1, alt-2, alt-3
  3. Navigate with ctrl-alt-left/right
  4. Open files from fuss, verify new tabs created
  5. Modify files in different tabs, verify * indicator
  6. Close tabs, verify proper cleanup

Integration Tests

  1. Tab switching preserves cursor position
  2. Tab switching preserves undo history
  3. Fuss mode works correctly with multiple tabs open
  4. Tab bar updates when files modified
  5. Keybindings don't conflict with existing shortcuts

Success Criteria

  • Can open 10 files in separate tabs
  • Each tab maintains independent state
  • Alt- switches tabs instantly
  • Ctrl-alt-left/right cycles through tabs
  • Tab bar clearly shows which tab is active
  • Opening file from fuss creates new tab
  • Modified files show * indicator in tab bar
  • Help menu documents all tab features
  • No performance degradation with 10 tabs open

Future Enhancements (Not in Scope)

  • Tab reordering (drag/drop or keyboard)
  • Split panes (horizontal/vertical)
  • Tab groups or sessions
  • Persistent tab state between sessions
  • Tab close keybinding (ctrl-w?)
  • New empty tab keybinding (ctrl-t?)
View source
1 # Tabs Implementation Plan for Facsimile
2
3 ## Overview
4 Add full tab support to facsimile, bridging the gap between GUI and terminal editors. Each tab represents an independent file buffer with its own cursor state and undo history.
5
6 ## Requirements
7
8 ### Core Features
9 - [x] Multiple file buffers open simultaneously
10 - [x] Tab bar at top of screen showing all open tabs
11 - [x] Active tab highlighted visually
12 - [x] Each tab maintains independent state:
13 - Buffer content
14 - Cursor position(s)
15 - Undo/redo history
16 - Viewport position
17 - File path
18
19 ### Keybindings
20 - [x] `alt-1` through `alt-9`: Jump to tab 1-9
21 - [x] `ctrl-alt-left`: Previous tab (with wrap-around)
22 - [x] `ctrl-alt-right`: Next tab (with wrap-around)
23 - [x] Check for conflicts with existing bindings (DONE - no conflicts)
24
25 ### Fuss Integration
26 - [x] Opening file in fuss mode creates new tab by default
27 - [x] New tab becomes active immediately
28 - [x] Fuss mode persists (already implemented)
29
30 ### UI/UX
31 - [x] Tab bar shows: `[1: file1.txt] [2: file2.f90*] [3: README.md]`
32 - [x] Active tab uses reverse video (char(27) // '[7m')
33 - [x] Modified files indicated with `*` suffix
34 - [x] Tab bar takes 1 row at top
35 - [x] Adjust editor viewport to account for tab bar (starts at row 2)
36 - [x] Tab bar updates automatically when switching tabs
37
38 ## Architecture Design
39
40 ### Data Structures
41
42 #### Tab Type (new)
43 ```fortran
44 type :: tab_t
45 character(len=:), allocatable :: filename
46 type(buffer_t) :: buffer
47 type(cursor_t), allocatable :: cursors(:)
48 integer :: active_cursor
49 integer :: viewport_line
50 integer :: viewport_column
51 logical :: modified
52 end type tab_t
53 ```
54
55 #### Editor State Updates
56 ```fortran
57 type(tab_t), allocatable :: tabs(:)
58 integer :: active_tab_index
59 integer :: max_tabs = 10 ! Support up to 10 tabs initially
60 ```
61
62 ### File Changes
63
64 #### src/editor_state_module.f90
65 - Add tab_t type definition
66 - Add tabs array and active_tab_index to editor_state_t
67 - Add procedures: create_tab, switch_tab, close_tab
68
69 #### src/terminal/renderer_module.f90
70 - Add render_tab_bar() subroutine
71 - Adjust main viewport to start at row 2 instead of row 1
72 - Update render_screen() to call render_tab_bar()
73
74 #### src/commands/command_handler_module.f90
75 - Add alt-1 through alt-9 handlers
76 - Add ctrl-alt-left/right handlers
77 - Modify open_file_in_editor() to create new tab
78 - Add save/restore logic for tab switching
79
80 #### src/buffer_module.f90
81 - Ensure buffer can be deep-copied for tab state
82 - May need clone_buffer() function
83
84 ## Implementation Phases
85
86 ### Phase 1: Core Tab Infrastructure
87 1. Define tab_t type
88 2. Add tabs array to editor state
89 3. Create basic tab management functions:
90 - `create_new_tab(editor, filename)`
91 - `switch_to_tab(editor, tab_index)`
92 - `get_current_tab(editor)`
93
94 ### Phase 2: Tab Bar Rendering
95 1. Implement `render_tab_bar()`
96 2. Display tab index and filename
97 3. Highlight active tab
98 4. Show modification indicator
99 5. Adjust viewport for tab bar
100
101 ### Phase 3: Navigation Keybindings
102 1. Parse alt-<number> key sequences
103 2. Implement tab switching logic
104 3. Add ctrl-alt-left/right navigation
105 4. Save/restore cursor and viewport state
106
107 ### Phase 4: Fuss Integration
108 1. Modify `open_file_in_editor()` to create tab
109 2. Set new tab as active
110 3. Test opening multiple files from fuss
111
112 ### Phase 5: Polish & Documentation
113 1. Update ctrl-? help menu
114 2. Test edge cases (max tabs, closing tabs, etc.)
115 3. Handle unsaved changes warnings
116 4. Performance testing with many tabs
117
118 ## Edge Cases to Handle
119
120 - Opening same file in multiple tabs (allow or prevent?)
121 - Maximum tab limit (10 initially)
122 - Tab overflow (show scroll indicator if >10 tabs?)
123 - Closing active tab (switch to next/previous)
124 - Closing all tabs (keep at least one empty buffer?)
125 - Modified file indicator updates
126 - Tab bar width overflow (truncate long filenames)
127
128 ## Testing Plan
129
130 ### Manual Tests
131 1. Create 3 tabs, verify each has independent buffer
132 2. Switch between tabs with alt-1, alt-2, alt-3
133 3. Navigate with ctrl-alt-left/right
134 4. Open files from fuss, verify new tabs created
135 5. Modify files in different tabs, verify * indicator
136 6. Close tabs, verify proper cleanup
137
138 ### Integration Tests
139 1. Tab switching preserves cursor position
140 2. Tab switching preserves undo history
141 3. Fuss mode works correctly with multiple tabs open
142 4. Tab bar updates when files modified
143 5. Keybindings don't conflict with existing shortcuts
144
145 ## Success Criteria
146
147 - [ ] Can open 10 files in separate tabs
148 - [ ] Each tab maintains independent state
149 - [ ] Alt-<number> switches tabs instantly
150 - [ ] Ctrl-alt-left/right cycles through tabs
151 - [ ] Tab bar clearly shows which tab is active
152 - [ ] Opening file from fuss creates new tab
153 - [ ] Modified files show * indicator in tab bar
154 - [ ] Help menu documents all tab features
155 - [ ] No performance degradation with 10 tabs open
156
157 ## Future Enhancements (Not in Scope)
158
159 - Tab reordering (drag/drop or keyboard)
160 - Split panes (horizontal/vertical)
161 - Tab groups or sessions
162 - Persistent tab state between sessions
163 - Tab close keybinding (ctrl-w?)
164 - New empty tab keybinding (ctrl-t?)