fortrangoingonforty/facsimile / 5c5a6f9

Browse files

fix multiple rename issue

Authored by espadonne
SHA
5c5a6f9f332b266862a2c254437bca84d09758c5
Parents
b44a816
Tree
92fb770

11 changed files

StatusFile+-
M app/main.f90 0 50
M src/commands/command_handler_module.f90 107 9
M src/lsp/diagnostics_module.f90 1 19
M src/lsp/lsp_protocol_module.f90 1 11
M src/lsp/lsp_server_manager_module.f90 15 319
M src/terminal/input_handler_module.f90 59 91
M src/ui/help_display_module.f90 7 7
M src/ui/rename_prompt_module.f90 0 25
M src/workspace/workspace_module.f90 3 53
M tests/scratch_files/calculator.py 1 0
M tests/scratch_files/long_errors.py 1 1
app/main.f90modified
@@ -119,62 +119,42 @@ program facsimile
119
         ! User selected a workspace from welcome menu (not browse)
119
         ! User selected a workspace from welcome menu (not browse)
120
         ! This handles favorites, recents, and CURRENT DIRECTORY
120
         ! This handles favorites, recents, and CURRENT DIRECTORY
121
         if (allocated(selected_path) .and. .not. is_browse) then
121
         if (allocated(selected_path) .and. .not. is_browse) then
122
-            write(0, '(A)') '[DEBUG WELCOME] selected_path allocated, value: ' // selected_path
123
-            write(0, '(A,L1)') '[DEBUG WELCOME] is_browse: ', is_browse
124
-
125
             ! Check if user selected CURRENT DIRECTORY option
122
             ! Check if user selected CURRENT DIRECTORY option
126
             if (selected_path == "CWD") then
123
             if (selected_path == "CWD") then
127
-                write(0, '(A)') '[DEBUG WELCOME] CWD selected, getting workspace path'
128
                 ! Get actual current working directory
124
                 ! Get actual current working directory
129
                 call get_workspace_path(selected_path)
125
                 call get_workspace_path(selected_path)
130
-                write(0, '(A)') '[DEBUG WELCOME] Workspace path: ' // selected_path
131
                 arg = selected_path
126
                 arg = selected_path
132
             else
127
             else
133
-                write(0, '(A)') '[DEBUG WELCOME] Not CWD, using selected_path directly'
134
                 arg = selected_path
128
                 arg = selected_path
135
             end if
129
             end if
136
 
130
 
137
             ! Check if it's a directory
131
             ! Check if it's a directory
138
-            write(0, '(A)') '[DEBUG WELCOME] Testing if directory: ' // trim(arg)
139
             call execute_command_line("test -d '" // trim(arg) // &
132
             call execute_command_line("test -d '" // trim(arg) // &
140
                 "' && echo 'Directory' > /tmp/.fac_filetype || " // &
133
                 "' && echo 'Directory' > /tmp/.fac_filetype || " // &
141
                 "echo 'File' > /tmp/.fac_filetype", wait=.true.)
134
                 "echo 'File' > /tmp/.fac_filetype", wait=.true.)
142
             call read_file_type(status)
135
             call read_file_type(status)
143
-            write(0, '(A,I0)') '[DEBUG WELCOME] read_file_type status: ', status
144
             if (status == 0) then
136
             if (status == 0) then
145
                 ! Directory - workspace mode
137
                 ! Directory - workspace mode
146
-                write(0, '(A)') '[DEBUG WELCOME] Setting is_workspace_mode = TRUE'
147
                 is_workspace_mode = .true.
138
                 is_workspace_mode = .true.
148
                 call workspace_get_path(trim(arg), workspace_dir)
139
                 call workspace_get_path(trim(arg), workspace_dir)
149
-                write(0, '(A)') '[DEBUG WELCOME] workspace_dir: ' // trim(workspace_dir)
150
             else
140
             else
151
                 ! Invalid selection (favorites/recents should only have directories)
141
                 ! Invalid selection (favorites/recents should only have directories)
152
                 write(error_unit, '(A)') 'Error: Selected path is not a directory'
142
                 write(error_unit, '(A)') 'Error: Selected path is not a directory'
153
                 stop 1
143
                 stop 1
154
             end if
144
             end if
155
-        else
156
-            write(0, '(A,L1)') '[DEBUG WELCOME] selected_path allocated: ', allocated(selected_path)
157
-            if (allocated(selected_path)) then
158
-                write(0, '(A)') '[DEBUG WELCOME] selected_path value: ' // selected_path
159
-            end if
160
-            write(0, '(A,L1)') '[DEBUG WELCOME] is_browse: ', is_browse
161
         end if
145
         end if
162
     end if
146
     end if
163
 
147
 
164
     ! Handle workspace mode
148
     ! Handle workspace mode
165
-    write(0, '(A,L1)') '[DEBUG WORKSPACE] is_workspace_mode: ', is_workspace_mode
166
     if (is_workspace_mode) then
149
     if (is_workspace_mode) then
167
-        write(0, '(A)') '[DEBUG WORKSPACE] In workspace mode, workspace_dir: ' // trim(workspace_dir)
168
         ! Check if workspace exists, create if not
150
         ! Check if workspace exists, create if not
169
         if (.not. workspace_exists(workspace_dir)) then
151
         if (.not. workspace_exists(workspace_dir)) then
170
-            write(0, '(A)') '[DEBUG WORKSPACE] Workspace does not exist, creating'
171
             call workspace_init(workspace_dir, workspace_success)
152
             call workspace_init(workspace_dir, workspace_success)
172
             if (.not. workspace_success) then
153
             if (.not. workspace_success) then
173
                 write(error_unit, '(A)') 'Error: Failed to create workspace'
154
                 write(error_unit, '(A)') 'Error: Failed to create workspace'
174
                 stop 1
155
                 stop 1
175
             end if
156
             end if
176
         else
157
         else
177
-            write(0, '(A)') '[DEBUG WORKSPACE] Workspace exists, loading'
178
             ! Load existing workspace
158
             ! Load existing workspace
179
             call workspace_load(workspace_dir, workspace_success)
159
             call workspace_load(workspace_dir, workspace_success)
180
             if (.not. workspace_success) then
160
             if (.not. workspace_success) then
@@ -182,8 +162,6 @@ program facsimile
182
                 stop 1
162
                 stop 1
183
             end if
163
             end if
184
         end if
164
         end if
185
-    else
186
-        write(0, '(A)') '[DEBUG WORKSPACE] NOT in workspace mode'
187
     end if
165
     end if
188
 
166
 
189
     ! Initialize editor
167
     ! Initialize editor
@@ -204,46 +182,23 @@ program facsimile
204
     call init_buffer(buffer)
182
     call init_buffer(buffer)
205
 
183
 
206
     ! Set workspace path
184
     ! Set workspace path
207
-    write(0, '(A,L1)') '[DEBUG RESTORE CHECK] is_workspace_mode: ', is_workspace_mode
208
     if (is_workspace_mode) then
185
     if (is_workspace_mode) then
209
-        write(0, '(A)') '[DEBUG RESTORE CHECK] workspace_dir: ' // trim(workspace_dir)
210
         ! Use detected/created workspace directory
186
         ! Use detected/created workspace directory
211
         allocate(character(len=len_trim(workspace_dir)) :: editor%workspace_path)
187
         allocate(character(len=len_trim(workspace_dir)) :: editor%workspace_path)
212
         editor%workspace_path = trim(workspace_dir)
188
         editor%workspace_path = trim(workspace_dir)
213
 
189
 
214
-        ! DEBUG: Print before restoration (unit 0 = stderr)
215
-        write(0, '(A)') '[DEBUG RESTORE] About to restore workspace from: ' // trim(editor%workspace_path)
216
-        write(0, '(A)') '[DEBUG RESTORE] Workspace JSON path: ' // trim(editor%workspace_path) // '/.fac/workspace.json'
217
-
218
         ! Restore workspace state (tabs, cursor positions, etc.)
190
         ! Restore workspace state (tabs, cursor positions, etc.)
219
         call workspace_restore_state(editor, editor%workspace_path, workspace_success)
191
         call workspace_restore_state(editor, editor%workspace_path, workspace_success)
220
 
192
 
221
-        ! DEBUG: Print restoration results
222
-        write(0, '(A,L1)') '[DEBUG RESTORE] Workspace restore success: ', workspace_success
223
-        if (allocated(editor%tabs)) then
224
-            write(0, '(A,I0)') '[DEBUG RESTORE] Number of tabs restored: ', size(editor%tabs)
225
-        else
226
-            write(0, '(A)') '[DEBUG RESTORE] No tabs allocated after restore'
227
-        end if
228
-        write(0, '(A,I0)') '[DEBUG RESTORE] Active tab index: ', editor%active_tab_index
229
-
230
         ! Sync restored active tab's buffer to main buffer
193
         ! Sync restored active tab's buffer to main buffer
231
         if (workspace_success .and. allocated(editor%tabs) .and. editor%active_tab_index > 0) then
194
         if (workspace_success .and. allocated(editor%tabs) .and. editor%active_tab_index > 0) then
232
             if (editor%active_tab_index <= size(editor%tabs)) then
195
             if (editor%active_tab_index <= size(editor%tabs)) then
233
                 if (allocated(editor%tabs(editor%active_tab_index)%panes) .and. &
196
                 if (allocated(editor%tabs(editor%active_tab_index)%panes) .and. &
234
                     size(editor%tabs(editor%active_tab_index)%panes) > 0) then
197
                     size(editor%tabs(editor%active_tab_index)%panes) > 0) then
235
                     ! Copy active pane's buffer to main buffer (replaces the empty init)
198
                     ! Copy active pane's buffer to main buffer (replaces the empty init)
236
-                    write(0, '(A)') '[DEBUG RESTORE] Copying restored tab buffer to main buffer'
237
                     call copy_buffer(buffer, editor%tabs(editor%active_tab_index)%panes(1)%buffer)
199
                     call copy_buffer(buffer, editor%tabs(editor%active_tab_index)%panes(1)%buffer)
238
-                else
239
-                    write(0, '(A)') '[DEBUG RESTORE] Active tab has no panes!'
240
                 end if
200
                 end if
241
-            else
242
-                write(0, '(A,I0,A,I0)') '[DEBUG RESTORE] Active tab index ', editor%active_tab_index, &
243
-                    ' exceeds tab count ', size(editor%tabs)
244
             end if
201
             end if
245
-        else
246
-            write(0, '(A)') '[DEBUG RESTORE] Skipping buffer sync - conditions not met'
247
         end if
202
         end if
248
     else
203
     else
249
         ! Single-file mode - use current directory
204
         ! Single-file mode - use current directory
@@ -515,11 +470,6 @@ contains
515
         use terminal_io_module, only: terminal_write
470
         use terminal_io_module, only: terminal_write
516
         type(lsp_message_t), intent(in) :: notification
471
         type(lsp_message_t), intent(in) :: notification
517
         integer, intent(in) :: server_index
472
         integer, intent(in) :: server_index
518
-        character(len=256) :: debug_msg
519
-
520
-        ! Debug: Log when diagnostics are received
521
-        write(debug_msg, '(A,I0)') "[DEBUG] Received diagnostics from server ", server_index
522
-        call terminal_write(debug_msg)  ! Debug output enabled
523
 
473
 
524
         ! Parse and store diagnostics with server attribution (for multi-LSP)
474
         ! Parse and store diagnostics with server attribution (for multi-LSP)
525
         ! This keeps diagnostics from different servers separate
475
         ! This keeps diagnostics from different servers separate
src/commands/command_handler_module.f90modified
@@ -1386,15 +1386,15 @@ contains
1386
 
1386
 
1387
                                             ! Check if rename response modified the buffer
1387
                                             ! Check if rename response modified the buffer
1388
                                             if (g_lsp_modified_buffer) then
1388
                                             if (g_lsp_modified_buffer) then
1389
-                                                ! Sync buffer from tab (LSP modified tab buffer)
1389
+                                                ! LSP now modifies pane buffer directly, sync FROM pane TO local buffer and tab
1390
-                                                call copy_buffer(buffer, editor%tabs(editor%active_tab_index)%buffer)
1391
-
1392
-                                                ! Also sync to active pane buffer if panes exist
1393
                                                 if (allocated(editor%tabs(editor%active_tab_index)%panes) .and. &
1390
                                                 if (allocated(editor%tabs(editor%active_tab_index)%panes) .and. &
1394
                                                     size(editor%tabs(editor%active_tab_index)%panes) > 0) then
1391
                                                     size(editor%tabs(editor%active_tab_index)%panes) > 0) then
1395
                                                     pane_idx = editor%tabs(editor%active_tab_index)%active_pane_index
1392
                                                     pane_idx = editor%tabs(editor%active_tab_index)%active_pane_index
1396
                                                     if (pane_idx > 0 .and. pane_idx <= size(editor%tabs(editor%active_tab_index)%panes)) then
1393
                                                     if (pane_idx > 0 .and. pane_idx <= size(editor%tabs(editor%active_tab_index)%panes)) then
1397
-                                                        call copy_buffer(editor%tabs(editor%active_tab_index)%panes(pane_idx)%buffer, buffer)
1394
+                                                        ! Copy FROM pane buffer TO local buffer (for rendering)
1395
+                                                        call copy_buffer(buffer, editor%tabs(editor%active_tab_index)%panes(pane_idx)%buffer)
1396
+                                                        ! Also sync to tab buffer (to keep them consistent)
1397
+                                                        call copy_buffer(editor%tabs(editor%active_tab_index)%buffer, buffer)
1398
                                                     end if
1398
                                                     end if
1399
                                                 end if
1399
                                                 end if
1400
 
1400
 
@@ -6313,14 +6313,16 @@ contains
6313
     subroutine apply_file_edits_obj(editor, uri, edits_arr, changes_applied)
6313
     subroutine apply_file_edits_obj(editor, uri, edits_arr, changes_applied)
6314
         use json_module, only: json_value_t, json_array_size, json_get_array_element, &
6314
         use json_module, only: json_value_t, json_array_size, json_get_array_element, &
6315
                                json_get_object, json_get_string, json_get_number, json_has_key
6315
                                json_get_object, json_get_string, json_get_number, json_has_key
6316
+        use text_buffer_module, only: buffer_to_string
6317
+        use lsp_server_manager_module, only: notify_file_changed
6316
         type(editor_state_t), intent(inout) :: editor
6318
         type(editor_state_t), intent(inout) :: editor
6317
         character(len=*), intent(in) :: uri
6319
         character(len=*), intent(in) :: uri
6318
         type(json_value_t), intent(in) :: edits_arr
6320
         type(json_value_t), intent(in) :: edits_arr
6319
         integer, intent(inout) :: changes_applied
6321
         integer, intent(inout) :: changes_applied
6320
 
6322
 
6321
         type(json_value_t) :: edit_obj, range_obj, start_obj, end_obj
6323
         type(json_value_t) :: edit_obj, range_obj, start_obj, end_obj
6322
-        character(len=:), allocatable :: filename, new_text
6324
+        character(len=:), allocatable :: filename, new_text, buffer_content
6323
-        integer :: num_edits, i, j, tab_idx
6325
+        integer :: num_edits, i, j, tab_idx, server_idx, pane_idx
6324
         integer :: start_line, start_char, end_line, end_char
6326
         integer :: start_line, start_char, end_line, end_char
6325
 
6327
 
6326
         ! Convert URI to filename
6328
         ! Convert URI to filename
@@ -6356,6 +6358,25 @@ contains
6356
             return
6358
             return
6357
         end if
6359
         end if
6358
 
6360
 
6361
+        ! Get the active pane for this tab (panes contain the actual buffers)
6362
+        pane_idx = editor%tabs(tab_idx)%active_pane_index
6363
+        if (pane_idx < 1 .or. .not. allocated(editor%tabs(tab_idx)%panes)) then
6364
+            pane_idx = 1  ! Default to first pane
6365
+        end if
6366
+        if (pane_idx > size(editor%tabs(tab_idx)%panes)) then
6367
+            if (allocated(filename)) deallocate(filename)
6368
+            return
6369
+        end if
6370
+
6371
+        ! Debug: log tab_idx finding
6372
+        open(newunit=server_idx, file='/tmp/fac_tab_debug.log', status='unknown', &
6373
+             position='append', action='write')
6374
+        write(server_idx, '(A,I3,A,I3)') 'Found tab_idx=', tab_idx, ' pane_idx=', pane_idx
6375
+        write(server_idx, '(A,A)') 'Extracted filename: ', trim(filename)
6376
+        write(server_idx, '(A,A)') 'Tab filename: ', trim(editor%tabs(tab_idx)%filename)
6377
+        write(server_idx, '(A)') '---'
6378
+        close(server_idx)
6379
+
6359
         ! Apply edits in reverse order (to preserve line numbers)
6380
         ! Apply edits in reverse order (to preserve line numbers)
6360
         num_edits = json_array_size(edits_arr)
6381
         num_edits = json_array_size(edits_arr)
6361
 
6382
 
@@ -6379,15 +6400,53 @@ contains
6379
                 new_text = json_get_string(edit_obj, 'newText')
6400
                 new_text = json_get_string(edit_obj, 'newText')
6380
 
6401
 
6381
                 if (allocated(new_text)) then
6402
                 if (allocated(new_text)) then
6382
-                    ! Apply the edit to the buffer
6403
+                    ! Apply the edit to the pane buffer (not tab buffer!)
6383
-                    call apply_single_edit(editor%tabs(tab_idx)%buffer, &
6404
+                    call apply_single_edit(editor%tabs(tab_idx)%panes(pane_idx)%buffer, &
6384
                         start_line, start_char, end_line, end_char, new_text)
6405
                         start_line, start_char, end_line, end_char, new_text)
6385
                     changes_applied = changes_applied + 1
6406
                     changes_applied = changes_applied + 1
6407
+
6408
+                    ! Debug: check buffer size after edit
6409
+                    block
6410
+                        character(len=:), allocatable :: check_content
6411
+                        integer :: check_unit
6412
+                        check_content = buffer_to_string(editor%tabs(tab_idx)%panes(pane_idx)%buffer)
6413
+                        open(newunit=check_unit, file='/tmp/fac_after_edit.log', status='unknown', &
6414
+                             position='append', action='write')
6415
+                        write(check_unit, '(A,I8)') 'After edit, buffer len: ', len(check_content)
6416
+                        close(check_unit)
6417
+                        if (allocated(check_content)) deallocate(check_content)
6418
+                    end block
6419
+
6386
                     deallocate(new_text)
6420
                     deallocate(new_text)
6387
                 end if
6421
                 end if
6388
             end if
6422
             end if
6389
         end do
6423
         end do
6390
 
6424
 
6425
+        ! Sync the changed document back to all LSP servers
6426
+        if (changes_applied > 0) then
6427
+            buffer_content = buffer_to_string(editor%tabs(tab_idx)%panes(pane_idx)%buffer)
6428
+            if (allocated(buffer_content)) then
6429
+                ! Debug: log what we're about to sync
6430
+                open(newunit=server_idx, file='/tmp/fac_sync_debug.log', status='unknown', &
6431
+                     position='append', action='write')
6432
+                write(server_idx, '(A,I4)') 'Sync after changes_applied=', changes_applied
6433
+                write(server_idx, '(A,I8)') 'Buffer content length: ', len(buffer_content)
6434
+                write(server_idx, '(A,A)') 'First 100 chars: ', buffer_content(1:min(100,len(buffer_content)))
6435
+                write(server_idx, '(A)') '---'
6436
+                close(server_idx)
6437
+
6438
+                ! Notify all active LSP servers about the document change
6439
+                ! Use the absolute path from the URI (filename variable) not the tab's relative path
6440
+                do server_idx = 1, editor%lsp_manager%num_servers
6441
+                    if (editor%lsp_manager%servers(server_idx)%initialized) then
6442
+                        call notify_file_changed(editor%lsp_manager, server_idx, &
6443
+                            'file://' // filename, buffer_content)
6444
+                    end if
6445
+                end do
6446
+                deallocate(buffer_content)
6447
+            end if
6448
+        end if
6449
+
6391
         if (allocated(filename)) deallocate(filename)
6450
         if (allocated(filename)) deallocate(filename)
6392
     end subroutine apply_file_edits_obj
6451
     end subroutine apply_file_edits_obj
6393
 
6452
 
@@ -6398,23 +6457,62 @@ contains
6398
         character(len=*), intent(in) :: new_text
6457
         character(len=*), intent(in) :: new_text
6399
 
6458
 
6400
         integer :: start_pos, end_pos, delete_count
6459
         integer :: start_pos, end_pos, delete_count
6460
+        integer :: debug_unit
6461
+        character(len=256) :: debug_msg
6401
 
6462
 
6402
         ! Calculate buffer positions
6463
         ! Calculate buffer positions
6403
         start_pos = get_buffer_position(buffer, start_line, start_char)
6464
         start_pos = get_buffer_position(buffer, start_line, start_char)
6404
         end_pos = get_buffer_position(buffer, end_line, end_char)
6465
         end_pos = get_buffer_position(buffer, end_line, end_char)
6405
 
6466
 
6467
+        ! Debug logging
6468
+        open(newunit=debug_unit, file='/tmp/fac_edit_debug.log', status='unknown', &
6469
+             position='append', action='write')
6470
+        write(debug_msg, '(A,I4,A,I4,A,I4,A,I4)') 'Edit range: line ', start_line, &
6471
+              ' char ', start_char, ' to line ', end_line, ' char ', end_char
6472
+        write(debug_unit, '(A)') trim(debug_msg)
6473
+        write(debug_msg, '(A,I6,A,I6,A,I4)') 'Buffer pos: start=', start_pos, &
6474
+              ' end=', end_pos, ' delete_count=', end_pos - start_pos
6475
+        write(debug_unit, '(A)') trim(debug_msg)
6476
+        write(debug_msg, '(A,I4,A,A,A)') 'New text len=', len(new_text), ' text="', new_text, '"'
6477
+        write(debug_unit, '(A)') trim(debug_msg)
6478
+        write(debug_unit, '(A)') '---'
6479
+        close(debug_unit)
6480
+
6406
         if (start_pos <= 0 .or. end_pos <= 0) return
6481
         if (start_pos <= 0 .or. end_pos <= 0) return
6407
 
6482
 
6408
         ! Delete the old text
6483
         ! Delete the old text
6409
         delete_count = end_pos - start_pos
6484
         delete_count = end_pos - start_pos
6485
+
6486
+        ! Debug: log gap buffer state before operations
6487
+        open(newunit=debug_unit, file='/tmp/fac_gap_debug.log', status='unknown', &
6488
+             position='append', action='write')
6489
+        write(debug_unit, '(A,I6,A,I6,A,I6)') 'BEFORE: gap_start=', buffer%gap_start, &
6490
+              ' gap_end=', buffer%gap_end, ' size=', buffer%size
6491
+        close(debug_unit)
6492
+
6410
         if (delete_count > 0) then
6493
         if (delete_count > 0) then
6411
             call buffer_delete(buffer, start_pos, delete_count)
6494
             call buffer_delete(buffer, start_pos, delete_count)
6412
         end if
6495
         end if
6413
 
6496
 
6497
+        ! Debug: log gap buffer state after delete
6498
+        open(newunit=debug_unit, file='/tmp/fac_gap_debug.log', status='unknown', &
6499
+             position='append', action='write')
6500
+        write(debug_unit, '(A,I6,A,I6,A,I6)') 'AFTER DELETE: gap_start=', buffer%gap_start, &
6501
+              ' gap_end=', buffer%gap_end, ' size=', buffer%size
6502
+        close(debug_unit)
6503
+
6414
         ! Insert the new text
6504
         ! Insert the new text
6415
         if (len(new_text) > 0) then
6505
         if (len(new_text) > 0) then
6416
             call buffer_insert(buffer, start_pos, new_text)
6506
             call buffer_insert(buffer, start_pos, new_text)
6417
         end if
6507
         end if
6508
+
6509
+        ! Debug: log gap buffer state after insert
6510
+        open(newunit=debug_unit, file='/tmp/fac_gap_debug.log', status='unknown', &
6511
+             position='append', action='write')
6512
+        write(debug_unit, '(A,I6,A,I6,A,I6)') 'AFTER INSERT: gap_start=', buffer%gap_start, &
6513
+              ' gap_end=', buffer%gap_end, ' size=', buffer%size
6514
+        write(debug_unit, '(A)') '---'
6515
+        close(debug_unit)
6418
     end subroutine apply_single_edit
6516
     end subroutine apply_single_edit
6419
 
6517
 
6420
     ! Execute a command from the command palette
6518
     ! Execute a command from the command palette
src/lsp/diagnostics_module.f90modified
@@ -108,16 +108,11 @@ contains
108
         character(len=:), allocatable :: uri
108
         character(len=:), allocatable :: uri
109
         integer :: i, n_diagnostics, file_idx
109
         integer :: i, n_diagnostics, file_idx
110
         type(diagnostic_t) :: diag
110
         type(diagnostic_t) :: diag
111
-        character(len=512) :: debug_msg
112
 
111
 
113
         ! Get URI
112
         ! Get URI
114
         if (.not. json_has_key(params, "uri")) return
113
         if (.not. json_has_key(params, "uri")) return
115
         uri = json_get_string(params, "uri")
114
         uri = json_get_string(params, "uri")
116
 
115
 
117
-        ! Debug: Log URI
118
-        write(debug_msg, '(A,A)') "[DIAG] Parsing diagnostics for URI: ", trim(uri)
119
-        call terminal_write(debug_msg)
120
-
121
         ! Find or create file entry
116
         ! Find or create file entry
122
         file_idx = find_or_create_file(store, uri)
117
         file_idx = find_or_create_file(store, uri)
123
 
118
 
@@ -132,10 +127,6 @@ contains
132
             diagnostics_array = json_get_array(params, "diagnostics")
127
             diagnostics_array = json_get_array(params, "diagnostics")
133
             n_diagnostics = json_array_size(diagnostics_array)
128
             n_diagnostics = json_array_size(diagnostics_array)
134
 
129
 
135
-            ! Debug: Log number of diagnostics
136
-            write(debug_msg, '(A,I0,A)') "[DIAG] Found ", n_diagnostics, " diagnostics"
137
-            call terminal_write(debug_msg)
138
-
139
             if (n_diagnostics > 0) then
130
             if (n_diagnostics > 0) then
140
                 allocate(store%files(file_idx)%items(n_diagnostics))
131
                 allocate(store%files(file_idx)%items(n_diagnostics))
141
                 store%files(file_idx)%count = n_diagnostics
132
                 store%files(file_idx)%count = n_diagnostics
@@ -208,17 +199,12 @@ contains
208
         character(len=:), allocatable :: uri
199
         character(len=:), allocatable :: uri
209
         integer :: i, n_diagnostics, file_idx, old_count, new_count, j
200
         integer :: i, n_diagnostics, file_idx, old_count, new_count, j
210
         type(diagnostic_t) :: diag
201
         type(diagnostic_t) :: diag
211
-        type(diagnostic_t), allocatable :: old_items(:), new_items(:)
202
+        type(diagnostic_t), allocatable :: old_items(:)
212
-        character(len=512) :: debug_msg
213
 
203
 
214
         ! Get URI
204
         ! Get URI
215
         if (.not. json_has_key(params, "uri")) return
205
         if (.not. json_has_key(params, "uri")) return
216
         uri = json_get_string(params, "uri")
206
         uri = json_get_string(params, "uri")
217
 
207
 
218
-        ! Debug: Log URI
219
-        write(debug_msg, '(A,A,A,I0)') "[DIAG] Parsing diagnostics for URI: ", trim(uri), " from server ", server_index
220
-        call terminal_write(debug_msg)
221
-
222
         ! Find or create file entry
208
         ! Find or create file entry
223
         file_idx = find_or_create_file(store, uri)
209
         file_idx = find_or_create_file(store, uri)
224
 
210
 
@@ -255,10 +241,6 @@ contains
255
             n_diagnostics = json_array_size(diagnostics_array)
241
             n_diagnostics = json_array_size(diagnostics_array)
256
         end if
242
         end if
257
 
243
 
258
-        ! Debug: Log number of diagnostics
259
-        write(debug_msg, '(A,I0,A,I0,A)') "[DIAG] Found ", n_diagnostics, " new + ", old_count, " existing diagnostics"
260
-        call terminal_write(debug_msg)
261
-
262
         ! Allocate combined array
244
         ! Allocate combined array
263
         new_count = old_count + n_diagnostics
245
         new_count = old_count + n_diagnostics
264
         if (new_count > 0) then
246
         if (new_count > 0) then
src/lsp/lsp_protocol_module.f90modified
@@ -106,16 +106,6 @@ contains
106
         ! Convert root_path to absolute path
106
         ! Convert root_path to absolute path
107
         abs_root_path = make_absolute_path(root_path)
107
         abs_root_path = make_absolute_path(root_path)
108
 
108
 
109
-        block
110
-            integer :: debug_unit
111
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
112
-            write(debug_unit, '(A)') '>>> create_initialize_request <<<'
113
-            write(debug_unit, '(A)') 'root_path (input): ' // trim(root_path)
114
-            write(debug_unit, '(A)') 'abs_root_path: ' // abs_root_path
115
-            write(debug_unit, '(A)') 'rootUri: file://' // abs_root_path
116
-            close(debug_unit)
117
-        end block
118
-
119
         params = json_create_object()
109
         params = json_create_object()
120
         call json_add_number(params, "processId", real(process_id, real64))
110
         call json_add_number(params, "processId", real(process_id, real64))
121
         call json_add_string(params, "rootPath", abs_root_path)
111
         call json_add_string(params, "rootPath", abs_root_path)
@@ -238,7 +228,7 @@ contains
238
         changes = json_create_array()
228
         changes = json_create_array()
239
         change = json_create_object()
229
         change = json_create_object()
240
         call json_add_string(change, "text", text)
230
         call json_add_string(change, "text", text)
241
-        ! TODO: Add change to array
231
+        call json_array_add_element(changes, change)
242
         call json_add_array(params, "contentChanges", changes)
232
         call json_add_array(params, "contentChanges", changes)
243
 
233
 
244
         msg%params = params
234
         msg%params = params
src/lsp/lsp_server_manager_module.f90modified
@@ -375,16 +375,6 @@ contains
375
             return
375
             return
376
         end if
376
         end if
377
 
377
 
378
-        block
379
-            integer :: debug_unit
380
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
381
-            write(debug_unit, '(A)') '>>> STARTING LSP SERVER <<<'
382
-            write(debug_unit, '(A)') 'Language: ' // trim(language)
383
-            write(debug_unit, '(A)') 'Command: ' // trim(command)
384
-            write(debug_unit, '(A)') 'Root path: ' // trim(root_path)
385
-            close(debug_unit)
386
-        end block
387
-
388
         ! Expand server array
378
         ! Expand server array
389
         allocate(new_servers(manager%num_servers + 1))
379
         allocate(new_servers(manager%num_servers + 1))
390
         if (manager%num_servers > 0) then
380
         if (manager%num_servers > 0) then
@@ -467,98 +457,20 @@ contains
467
         procedure(response_callback), optional :: callback
457
         procedure(response_callback), optional :: callback
468
         character(len=:), allocatable :: json_msg
458
         character(len=:), allocatable :: json_msg
469
 
459
 
470
-        block
460
+        if (server_index < 1 .or. server_index > manager%num_servers) return
471
-            integer :: debug_unit
472
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
473
-            write(debug_unit, '(A)') '>>> send_request: START <<<'
474
-            write(debug_unit, '(A,I0)') 'server_index = ', server_index
475
-            write(debug_unit, '(A,I0)') 'num_servers = ', manager%num_servers
476
-            close(debug_unit)
477
-        end block
478
-
479
-        if (server_index < 1 .or. server_index > manager%num_servers) then
480
-            block
481
-                integer :: debug_unit
482
-                open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
483
-                write(debug_unit, '(A)') '>>> send_request: EARLY RETURN - invalid server_index <<<'
484
-                close(debug_unit)
485
-            end block
486
-            return
487
-        end if
488
 
461
 
489
         if (.not. manager%servers(server_index)%initialized .and. &
462
         if (.not. manager%servers(server_index)%initialized .and. &
490
-            .not. manager%servers(server_index)%initializing) then
463
+            .not. manager%servers(server_index)%initializing) return
491
-            block
492
-                integer :: debug_unit
493
-                open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
494
-                write(debug_unit, '(A)') '>>> send_request: EARLY RETURN - server not initialized <<<'
495
-                write(debug_unit, '(A,L1)') 'initialized = ', manager%servers(server_index)%initialized
496
-                write(debug_unit, '(A,L1)') 'initializing = ', manager%servers(server_index)%initializing
497
-                close(debug_unit)
498
-            end block
499
-            return
500
-        end if
501
-
502
-        block
503
-            integer :: debug_unit
504
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
505
-            write(debug_unit, '(A)') '>>> send_request: Formatting JSON <<<'
506
-            close(debug_unit)
507
-        end block
508
 
464
 
509
         json_msg = format_json_rpc(msg)
465
         json_msg = format_json_rpc(msg)
510
-
511
-        block
512
-            integer :: debug_unit
513
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
514
-            write(debug_unit, '(A)') '>>> send_request: Sending message <<<'
515
-            write(debug_unit, '(A)') 'JSON (first 500 chars): ' // json_msg(1:min(500,len(json_msg)))
516
-            close(debug_unit)
517
-        end block
518
-
519
         call send_raw_message(manager%servers(server_index), json_msg)
466
         call send_raw_message(manager%servers(server_index), json_msg)
520
 
467
 
521
-        block
522
-            integer :: debug_unit
523
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
524
-            write(debug_unit, '(A)') '>>> send_request: Tracking request <<<'
525
-            close(debug_unit)
526
-        end block
527
-
528
         ! Track request and register callback
468
         ! Track request and register callback
529
         call track_request(manager%servers(server_index), msg%id)
469
         call track_request(manager%servers(server_index), msg%id)
530
 
470
 
531
-        block
532
-            integer :: debug_unit
533
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
534
-            write(debug_unit, '(A,L1)') '>>> send_request: callback present = ', present(callback)
535
-            close(debug_unit)
536
-        end block
537
-
538
         if (present(callback)) then
471
         if (present(callback)) then
539
-            block
540
-                integer :: debug_unit
541
-                open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
542
-                write(debug_unit, '(A)') '>>> send_request: Calling register_callback <<<'
543
-                close(debug_unit)
544
-            end block
545
-
546
             call register_callback(manager, msg%id, callback)
472
             call register_callback(manager, msg%id, callback)
547
-
548
-            block
549
-                integer :: debug_unit
550
-                open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
551
-                write(debug_unit, '(A)') '>>> send_request: register_callback DONE <<<'
552
-                close(debug_unit)
553
-            end block
554
         end if
473
         end if
555
-
556
-        block
557
-            integer :: debug_unit
558
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
559
-            write(debug_unit, '(A)') '>>> send_request: DONE <<<'
560
-            close(debug_unit)
561
-        end block
562
     end subroutine send_request
474
     end subroutine send_request
563
 
475
 
564
     subroutine send_notification(server, msg)
476
     subroutine send_notification(server, msg)
@@ -569,52 +481,15 @@ contains
569
         if (.not. server%initialized .and. .not. server%initializing) return
481
         if (.not. server%initialized .and. .not. server%initializing) return
570
 
482
 
571
         json_msg = format_json_rpc(msg)
483
         json_msg = format_json_rpc(msg)
572
-
573
-        ! Debug log for didOpen notifications
574
-        if (index(msg%method, 'didOpen') > 0) then
575
-            block
576
-                integer :: debug_unit
577
-                open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
578
-                write(debug_unit, '(A)') '>>> Sending didOpen notification <<<'
579
-                write(debug_unit, '(A)') 'JSON (first 800 chars): ' // json_msg(1:min(800,len(json_msg)))
580
-                close(debug_unit)
581
-            end block
582
-        end if
583
-
584
         call send_raw_message(server, json_msg)
484
         call send_raw_message(server, json_msg)
585
     end subroutine send_notification
485
     end subroutine send_notification
586
 
486
 
587
     subroutine send_raw_message(server, message)
487
     subroutine send_raw_message(server, message)
588
         type(lsp_server_t), intent(inout) :: server
488
         type(lsp_server_t), intent(inout) :: server
589
         character(len=*), intent(in) :: message
489
         character(len=*), intent(in) :: message
590
-        integer :: result, debug_unit
490
+        integer :: result
591
-
592
-        ! Check if handle is valid
593
-        block
594
-            integer :: debug_unit2
595
-            open(newunit=debug_unit2, file='/tmp/fac_keys.log', position='append', action='write')
596
-            write(debug_unit2, '(A)') '>>> send_raw_message: START <<<'
597
-            write(debug_unit2, '(A,L1)') 'c_associated(server%handle) = ', c_associated(server%handle)
598
-            close(debug_unit2)
599
-        end block
600
-
601
-        if (.not. c_associated(server%handle)) then
602
-            block
603
-                integer :: debug_unit2
604
-                open(newunit=debug_unit2, file='/tmp/fac_keys.log', position='append', action='write')
605
-                write(debug_unit2, '(A)') '>>> send_raw_message: EARLY RETURN - handle is NULL <<<'
606
-                close(debug_unit2)
607
-            end block
608
-            return
609
-        end if
610
 
491
 
611
-        ! Log outgoing messages for debugging
492
+        if (.not. c_associated(server%handle)) return
612
-        open(newunit=debug_unit, file='/tmp/fac_lsp_out.log', position='append', action='write')
613
-        write(debug_unit, '(A)') '>>> OUTGOING MESSAGE >>>'
614
-        write(debug_unit, '(A)') trim(message)
615
-        write(debug_unit, '(A)') '<<< END MESSAGE <<<'
616
-        write(debug_unit, '(A)') ''
617
-        close(debug_unit)
618
 
493
 
619
         result = lsp_send_message_f(server%handle, message//c_null_char, len(message))
494
         result = lsp_send_message_f(server%handle, message//c_null_char, len(message))
620
 
495
 
@@ -675,18 +550,6 @@ contains
675
 
550
 
676
             ! Extract and parse message
551
             ! Extract and parse message
677
             message = server%read_buffer(1:message_end)
552
             message = server%read_buffer(1:message_end)
678
-
679
-            ! Log incoming message
680
-            block
681
-                integer :: debug_unit
682
-                open(newunit=debug_unit, file='/tmp/fac_lsp_in.log', position='append', action='write')
683
-                write(debug_unit, '(A)') '>>> INCOMING MESSAGE >>>'
684
-                write(debug_unit, '(A)') trim(message)
685
-                write(debug_unit, '(A)') '<<< END MESSAGE <<<'
686
-                write(debug_unit, '(A)') ''
687
-                close(debug_unit)
688
-            end block
689
-
690
             msg = parse_lsp_message(message)
553
             msg = parse_lsp_message(message)
691
 
554
 
692
             ! Handle the message
555
             ! Handle the message
@@ -818,19 +681,13 @@ contains
818
         server%initialized = .true.
681
         server%initialized = .true.
819
         server%initializing = .false.
682
         server%initializing = .false.
820
 
683
 
821
-        write(error_unit, '(a,a)') "LSP server initialized: ", server%language
822
-
823
         ! Send all queued didOpen notifications
684
         ! Send all queued didOpen notifications
824
         if (allocated(server%pending_didopens) .and. server%num_pending_didopens > 0) then
685
         if (allocated(server%pending_didopens) .and. server%num_pending_didopens > 0) then
825
             block
686
             block
826
-                integer :: i, debug_unit
687
+                integer :: i
827
                 type(lsp_message_t) :: didopen_msg
688
                 type(lsp_message_t) :: didopen_msg
828
                 character(len=:), allocatable :: lang, file_uri
689
                 character(len=:), allocatable :: lang, file_uri
829
 
690
 
830
-                open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
831
-                write(debug_unit, '(A,I0,A)') '>>> Flushing ', server%num_pending_didopens, ' queued didOpen notifications <<<'
832
-                close(debug_unit)
833
-
834
                 do i = 1, server%num_pending_didopens
691
                 do i = 1, server%num_pending_didopens
835
                     if (allocated(server%pending_didopens(i)%filename) .and. &
692
                     if (allocated(server%pending_didopens(i)%filename) .and. &
836
                         allocated(server%pending_didopens(i)%content)) then
693
                         allocated(server%pending_didopens(i)%content)) then
@@ -840,14 +697,6 @@ contains
840
                         didopen_msg = create_did_open_notification( &
697
                         didopen_msg = create_did_open_notification( &
841
                             file_uri, lang, 1, &
698
                             file_uri, lang, 1, &
842
                             server%pending_didopens(i)%content)
699
                             server%pending_didopens(i)%content)
843
-
844
-                        open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
845
-                        write(debug_unit, '(A,A)') '  - Sent didOpen for: ', trim(server%pending_didopens(i)%filename)
846
-                        write(debug_unit, '(A,A)') '  - URI: ', trim(file_uri)
847
-                        write(debug_unit, '(A,I0)') '  - Content length: ', len(server%pending_didopens(i)%content)
848
-                        write(debug_unit, '(A,A)') '  - Language: ', trim(lang)
849
-                        close(debug_unit)
850
-
851
                         call send_notification(server, didopen_msg)
700
                         call send_notification(server, didopen_msg)
852
                     end if
701
                     end if
853
                 end do
702
                 end do
@@ -865,9 +714,6 @@ contains
865
         type(lsp_message_t), intent(in) :: msg
714
         type(lsp_message_t), intent(in) :: msg
866
         integer :: srv_idx, i
715
         integer :: srv_idx, i
867
 
716
 
868
-        ! Debug: log all notifications
869
-        write(error_unit, '(A,A)') "[LSP DEBUG] Received notification: ", msg%method
870
-
871
         ! Find the server index for this server
717
         ! Find the server index for this server
872
         srv_idx = 0
718
         srv_idx = 0
873
         do i = 1, manager%num_servers
719
         do i = 1, manager%num_servers
@@ -882,12 +728,9 @@ contains
882
 
728
 
883
         select case(msg%method)
729
         select case(msg%method)
884
         case("textDocument/publishDiagnostics")
730
         case("textDocument/publishDiagnostics")
885
-            write(error_unit, '(A,I0)') "[LSP DEBUG] Processing publishDiagnostics from server ", srv_idx
886
             ! Forward to diagnostics handler if set (with server index)
731
             ! Forward to diagnostics handler if set (with server index)
887
             if (associated(manager%diagnostics_handler)) then
732
             if (associated(manager%diagnostics_handler)) then
888
                 call manager%diagnostics_handler(msg, srv_idx)
733
                 call manager%diagnostics_handler(msg, srv_idx)
889
-            else
890
-                write(error_unit, '(A)') "[LSP DEBUG] No diagnostics handler set!"
891
             end if
734
             end if
892
         case("window/showMessage")
735
         case("window/showMessage")
893
             ! TODO: Show message to user
736
             ! TODO: Show message to user
@@ -940,87 +783,19 @@ contains
940
         procedure(response_callback) :: callback
783
         procedure(response_callback) :: callback
941
         type(callback_entry_t), allocatable :: new_callbacks(:)
784
         type(callback_entry_t), allocatable :: new_callbacks(:)
942
 
785
 
943
-        block
944
-            integer :: debug_unit
945
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
946
-            write(debug_unit, '(A)') '>>> register_callback: START <<<'
947
-            write(debug_unit, '(A,I0)') 'request_id = ', request_id
948
-            write(debug_unit, '(A,I0)') 'num_callbacks = ', manager%num_callbacks
949
-            close(debug_unit)
950
-        end block
951
-
952
-        block
953
-            integer :: debug_unit
954
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
955
-            write(debug_unit, '(A)') '>>> register_callback: Allocating new_callbacks <<<'
956
-            close(debug_unit)
957
-        end block
958
-
959
         allocate(new_callbacks(manager%num_callbacks + 1))
786
         allocate(new_callbacks(manager%num_callbacks + 1))
960
 
787
 
961
-        block
962
-            integer :: debug_unit
963
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
964
-            write(debug_unit, '(A)') '>>> register_callback: Copying old callbacks <<<'
965
-            close(debug_unit)
966
-        end block
967
-
968
         if (manager%num_callbacks > 0) then
788
         if (manager%num_callbacks > 0) then
969
             new_callbacks(1:manager%num_callbacks) = manager%callbacks
789
             new_callbacks(1:manager%num_callbacks) = manager%callbacks
970
         end if
790
         end if
971
 
791
 
972
-        block
973
-            integer :: debug_unit
974
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
975
-            write(debug_unit, '(A)') '>>> register_callback: Setting new callback <<<'
976
-            close(debug_unit)
977
-        end block
978
-
979
         new_callbacks(manager%num_callbacks + 1)%request_id = request_id
792
         new_callbacks(manager%num_callbacks + 1)%request_id = request_id
980
         new_callbacks(manager%num_callbacks + 1)%callback => callback
793
         new_callbacks(manager%num_callbacks + 1)%callback => callback
981
 
794
 
982
-        block
983
-            integer :: debug_unit
984
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
985
-            write(debug_unit, '(A)') '>>> register_callback: Deallocating old callbacks <<<'
986
-            close(debug_unit)
987
-        end block
988
-
989
         if (allocated(manager%callbacks)) deallocate(manager%callbacks)
795
         if (allocated(manager%callbacks)) deallocate(manager%callbacks)
990
-
991
-        block
992
-            integer :: debug_unit
993
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
994
-            write(debug_unit, '(A)') '>>> register_callback: Reallocating manager%callbacks <<<'
995
-            close(debug_unit)
996
-        end block
997
-
998
         allocate(manager%callbacks(size(new_callbacks)))
796
         allocate(manager%callbacks(size(new_callbacks)))
999
-
1000
-        block
1001
-            integer :: debug_unit
1002
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1003
-            write(debug_unit, '(A)') '>>> register_callback: Copying new_callbacks <<<'
1004
-            close(debug_unit)
1005
-        end block
1006
-
1007
         manager%callbacks = new_callbacks
797
         manager%callbacks = new_callbacks
1008
-
1009
-        block
1010
-            integer :: debug_unit
1011
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1012
-            write(debug_unit, '(A)') '>>> register_callback: Incrementing num_callbacks <<<'
1013
-            close(debug_unit)
1014
-        end block
1015
-
1016
         manager%num_callbacks = manager%num_callbacks + 1
798
         manager%num_callbacks = manager%num_callbacks + 1
1017
-
1018
-        block
1019
-            integer :: debug_unit
1020
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1021
-            write(debug_unit, '(A)') '>>> register_callback: DONE <<<'
1022
-            close(debug_unit)
1023
-        end block
1024
     end subroutine register_callback
799
     end subroutine register_callback
1025
 
800
 
1026
     subroutine remove_callback(manager, index)
801
     subroutine remove_callback(manager, index)
@@ -1191,17 +966,6 @@ contains
1191
 
966
 
1192
         command = manager%configs(config_index)%command
967
         command = manager%configs(config_index)%command
1193
 
968
 
1194
-        block
1195
-            integer :: debug_unit
1196
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1197
-            write(debug_unit, '(A)') '>>> STARTING LSP SERVER (from config) <<<'
1198
-            write(debug_unit, '(A)') 'Name: ' // trim(manager%configs(config_index)%name)
1199
-            write(debug_unit, '(A)') 'Language: ' // trim(manager%configs(config_index)%language)
1200
-            write(debug_unit, '(A)') 'Command: ' // trim(command)
1201
-            write(debug_unit, '(A)') 'Root path: ' // trim(root_path)
1202
-            close(debug_unit)
1203
-        end block
1204
-
1205
         ! Expand server array
969
         ! Expand server array
1206
         allocate(new_servers(manager%num_servers + 1))
970
         allocate(new_servers(manager%num_servers + 1))
1207
         if (manager%num_servers > 0) then
971
         if (manager%num_servers > 0) then
@@ -1280,14 +1044,6 @@ contains
1280
 
1044
 
1281
         ! If server not initialized yet, queue the notification
1045
         ! If server not initialized yet, queue the notification
1282
         if (.not. manager%servers(server_index)%initialized) then
1046
         if (.not. manager%servers(server_index)%initialized) then
1283
-            block
1284
-                integer :: debug_unit
1285
-                open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1286
-                write(debug_unit, '(A)') '>>> notify_file_opened: Queuing (server not ready) <<<'
1287
-                write(debug_unit, '(A)') 'File: ' // trim(filename)
1288
-                close(debug_unit)
1289
-            end block
1290
-
1291
             ! Add to pending queue
1047
             ! Add to pending queue
1292
             if (allocated(manager%servers(server_index)%pending_didopens)) then
1048
             if (allocated(manager%servers(server_index)%pending_didopens)) then
1293
                 ! Grow array
1049
                 ! Grow array
@@ -1322,14 +1078,6 @@ contains
1322
             return
1078
             return
1323
         end if
1079
         end if
1324
 
1080
 
1325
-        block
1326
-            integer :: debug_unit
1327
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1328
-            write(debug_unit, '(A)') '>>> notify_file_opened: Sending immediately <<<'
1329
-            write(debug_unit, '(A)') 'File: ' // trim(filename)
1330
-            close(debug_unit)
1331
-        end block
1332
-
1333
         ! Server is ready, send immediately
1081
         ! Server is ready, send immediately
1334
         language = get_language_for_file(filename)
1082
         language = get_language_for_file(filename)
1335
         block
1083
         block
@@ -1338,14 +1086,6 @@ contains
1338
             msg = create_did_open_notification(file_uri, language, 1, content)
1086
             msg = create_did_open_notification(file_uri, language, 1, content)
1339
         end block
1087
         end block
1340
 
1088
 
1341
-        block
1342
-            integer :: debug_unit
1343
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1344
-            write(debug_unit, '(A)') '>>> didOpen content length: ' // trim(adjustl(char(len(content))))
1345
-            write(debug_unit, '(A)') '>>> didOpen language: ' // trim(language)
1346
-            close(debug_unit)
1347
-        end block
1348
-
1349
         call send_notification(manager%servers(server_index), msg)
1089
         call send_notification(manager%servers(server_index), msg)
1350
     end subroutine notify_file_opened
1090
     end subroutine notify_file_opened
1351
 
1091
 
@@ -1359,6 +1099,16 @@ contains
1359
         integer, intent(in), optional :: version
1099
         integer, intent(in), optional :: version
1360
         type(lsp_message_t) :: msg
1100
         type(lsp_message_t) :: msg
1361
         integer :: doc_version
1101
         integer :: doc_version
1102
+        integer :: debug_unit
1103
+
1104
+        ! Debug logging
1105
+        open(newunit=debug_unit, file='/tmp/fac_didchange_debug.log', status='unknown', &
1106
+             position='append', action='write')
1107
+        write(debug_unit, '(A,I2,A)') 'notify_file_changed called for server ', server_index, ':'
1108
+        write(debug_unit, '(A,A)') '  URI: ', trim(filename)
1109
+        write(debug_unit, '(A,I8)') '  Content length: ', len(content)
1110
+        write(debug_unit, '(A)') '---'
1111
+        close(debug_unit)
1362
 
1112
 
1363
         if (server_index < 1 .or. server_index > manager%num_servers) return
1113
         if (server_index < 1 .or. server_index > manager%num_servers) return
1364
         if (.not. manager%servers(server_index)%initialized) return
1114
         if (.not. manager%servers(server_index)%initialized) return
@@ -1395,9 +1145,6 @@ contains
1395
         end if
1145
         end if
1396
 
1146
 
1397
         call send_notification(manager%servers(server_index), msg)
1147
         call send_notification(manager%servers(server_index), msg)
1398
-
1399
-        ! Debug output
1400
-        write(error_unit, '(A,A)') "[LSP DEBUG] Sent didSave for: ", trim(filename)
1401
     end subroutine notify_file_saved
1148
     end subroutine notify_file_saved
1402
 
1149
 
1403
     ! Send textDocument/didClose notification
1150
     ! Send textDocument/didClose notification
@@ -1477,55 +1224,14 @@ contains
1477
         type(lsp_message_t) :: msg
1224
         type(lsp_message_t) :: msg
1478
         character(len=:), allocatable :: uri
1225
         character(len=:), allocatable :: uri
1479
 
1226
 
1480
-        block
1481
-            integer :: debug_unit
1482
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1483
-            write(debug_unit, '(A)') '>>> request_definition: START <<<'
1484
-            close(debug_unit)
1485
-        end block
1486
-
1487
         request_id = -1
1227
         request_id = -1
1488
         if (server_index < 1 .or. server_index > manager%num_servers) return
1228
         if (server_index < 1 .or. server_index > manager%num_servers) return
1489
         if (.not. manager%servers(server_index)%initialized) return
1229
         if (.not. manager%servers(server_index)%initialized) return
1490
 
1230
 
1491
-        block
1492
-            integer :: debug_unit
1493
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1494
-            write(debug_unit, '(A)') '>>> request_definition: Creating URI <<<'
1495
-            write(debug_unit, '(A)') 'Filename: ' // trim(filename)
1496
-            close(debug_unit)
1497
-        end block
1498
-
1499
-        ! Convert filename to URI (simple file:// for now)
1500
         uri = filename_to_uri(filename)
1231
         uri = filename_to_uri(filename)
1501
-
1502
-        block
1503
-            integer :: debug_unit
1504
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1505
-            write(debug_unit, '(A)') '>>> request_definition: Creating request <<<'
1506
-            write(debug_unit, '(A)') 'URI: ' // trim(uri)
1507
-            write(debug_unit, '(A,I0,A,I0)') 'Position: line=', line, ' char=', character
1508
-            close(debug_unit)
1509
-        end block
1510
-
1511
         msg = create_definition_request(uri, line, character)
1232
         msg = create_definition_request(uri, line, character)
1512
         request_id = msg%id
1233
         request_id = msg%id
1513
-
1514
-        block
1515
-            integer :: debug_unit
1516
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1517
-            write(debug_unit, '(A)') '>>> request_definition: Calling send_request <<<'
1518
-            close(debug_unit)
1519
-        end block
1520
-
1521
         call send_request(manager, server_index, msg, callback)
1234
         call send_request(manager, server_index, msg, callback)
1522
-
1523
-        block
1524
-            integer :: debug_unit
1525
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
1526
-            write(debug_unit, '(A)') '>>> request_definition: DONE <<<'
1527
-            close(debug_unit)
1528
-        end block
1529
     end function request_definition
1235
     end function request_definition
1530
 
1236
 
1531
     ! Request references at cursor position
1237
     ! Request references at cursor position
@@ -1568,19 +1274,9 @@ contains
1568
         integer :: request_id
1274
         integer :: request_id
1569
         type(lsp_message_t) :: msg
1275
         type(lsp_message_t) :: msg
1570
         character(len=:), allocatable :: uri
1276
         character(len=:), allocatable :: uri
1571
-        integer :: dbg
1572
 
1277
 
1573
         request_id = -1
1278
         request_id = -1
1574
 
1279
 
1575
-        ! Debug logging
1576
-        open(newunit=dbg, file='/tmp/fac_code_actions.log', position='append', action='write')
1577
-        write(dbg, '(A,I0)') 'request_code_actions: server_index = ', server_index
1578
-        write(dbg, '(A,I0)') 'request_code_actions: num_servers = ', manager%num_servers
1579
-        if (server_index >= 1 .and. server_index <= manager%num_servers) then
1580
-            write(dbg, '(A,L1)') 'request_code_actions: initialized = ', manager%servers(server_index)%initialized
1581
-        end if
1582
-        close(dbg)
1583
-
1584
         if (server_index < 1 .or. server_index > manager%num_servers) return
1280
         if (server_index < 1 .or. server_index > manager%num_servers) return
1585
         if (.not. manager%servers(server_index)%initialized) return
1281
         if (.not. manager%servers(server_index)%initialized) return
1586
 
1282
 
src/terminal/input_handler_module.f90modified
@@ -105,14 +105,6 @@ contains
105
             end if
105
             end if
106
             ch2 = achar(char_code)
106
             ch2 = achar(char_code)
107
 
107
 
108
-            block
109
-                integer :: debug_unit, ch2_code
110
-                ch2_code = ichar(ch2)
111
-                open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
112
-                write(debug_unit, '(A,I0,A)') '>>> ESC[ RECEIVED, ch2=', ch2_code, ' (' // ch2 // ')'
113
-                close(debug_unit)
114
-            end block
115
-
116
             select case(ch2)
108
             select case(ch2)
117
             case('A')
109
             case('A')
118
                 key_str = 'up'
110
                 key_str = 'up'
@@ -187,22 +179,10 @@ contains
187
                 end if
179
                 end if
188
             case('1')
180
             case('1')
189
                 ! Could be function key (F1-F9) or modified arrow/home/end
181
                 ! Could be function key (F1-F9) or modified arrow/home/end
190
-                block
191
-                    integer :: debug_unit
192
-                    open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
193
-                    write(debug_unit, '(A)') '>>> ESC[1 SEQUENCE DETECTED <<<'
194
-                    close(debug_unit)
195
-                end block
196
                 ! Check next character
182
                 ! Check next character
197
                 char_code = terminal_read_char()
183
                 char_code = terminal_read_char()
198
                 if (char_code >= 0) then
184
                 if (char_code >= 0) then
199
                     ch3 = achar(char_code)
185
                     ch3 = achar(char_code)
200
-                    block
201
-                        integer :: debug_unit
202
-                        open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
203
-                        write(debug_unit, '(A)') 'ch3 = ' // ch3
204
-                        close(debug_unit)
205
-                    end block
206
                     if (ch3 == '~') then
186
                     if (ch3 == '~') then
207
                         ! F1: ESC [ 1 1 ~ (alternate format)
187
                         ! F1: ESC [ 1 1 ~ (alternate format)
208
                         key_str = 'f1'
188
                         key_str = 'f1'
@@ -250,21 +230,9 @@ contains
250
                 end if
230
                 end if
251
             case('2')
231
             case('2')
252
                 ! Could be F9-F12 or alternate modified keys
232
                 ! Could be F9-F12 or alternate modified keys
253
-                block
254
-                    integer :: debug_unit
255
-                    open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
256
-                    write(debug_unit, '(A)') '>>> ESC[2 SEQUENCE DETECTED <<<'
257
-                    close(debug_unit)
258
-                end block
259
                 char_code = terminal_read_char()
233
                 char_code = terminal_read_char()
260
                 if (char_code >= 0) then
234
                 if (char_code >= 0) then
261
                     ch3 = achar(char_code)
235
                     ch3 = achar(char_code)
262
-                    block
263
-                        integer :: debug_unit
264
-                        open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
265
-                        write(debug_unit, '(A)') 'ch3 = ' // ch3
266
-                        close(debug_unit)
267
-                    end block
268
                     if (ch3 == '0' .or. ch3 == '1' .or. ch3 == '3' .or. ch3 == '4') then
236
                     if (ch3 == '0' .or. ch3 == '1' .or. ch3 == '3' .or. ch3 == '4') then
269
                         ! Function keys F9-F12: ESC [ 2 X ~ or ESC [ 2 X ; modifier ~
237
                         ! Function keys F9-F12: ESC [ 2 X ~ or ESC [ 2 X ; modifier ~
270
                         char_code = terminal_read_char()
238
                         char_code = terminal_read_char()
@@ -281,13 +249,6 @@ contains
281
                                     key_str = 'f11'
249
                                     key_str = 'f11'
282
                                 case('4')
250
                                 case('4')
283
                                     key_str = 'f12'
251
                                     key_str = 'f12'
284
-                                    block
285
-                                        integer :: debug_unit
286
-                                        open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
287
-                                        write(debug_unit, '(A)') '>>> F12 KEY DETECTED IN INPUT HANDLER <<<'
288
-                                        write(debug_unit, '(A)') 'key_str set to: ' // trim(key_str)
289
-                                        close(debug_unit)
290
-                                    end block
291
                                 end select
252
                                 end select
292
                             else if (ch == ';') then
253
                             else if (ch == ';') then
293
                                 ! Modified F9-F12: ESC [ 2 X ; modifier ~
254
                                 ! Modified F9-F12: ESC [ 2 X ; modifier ~
@@ -465,64 +426,71 @@ contains
465
         if (terminator == '') return
426
         if (terminator == '') return
466
 
427
 
467
         ! Parse modifier
428
         ! Parse modifier
468
-        if (len_trim(modifier_seq) > 1 .and. modifier_seq(1:1) == ';') then
429
+        if (len_trim(modifier_seq) >= 1 .and. modifier_seq(1:1) == ';') then
469
-            ! Standard format: ";2" where 2 is the modifier
430
+            ! Standard format with leading ';': ";2" where 2 is the modifier
470
             if (len_trim(modifier_seq) >= 2) then
431
             if (len_trim(modifier_seq) >= 2) then
471
                 read(modifier_seq(2:len_trim(modifier_seq)), '(i10)', iostat=ios) modifier
432
                 read(modifier_seq(2:len_trim(modifier_seq)), '(i10)', iostat=ios) modifier
472
             else
433
             else
473
                 ios = -1
434
                 ios = -1
474
             end if
435
             end if
475
-            if (ios == 0) then
436
+        else if (len_trim(modifier_seq) >= 1 .and. &
476
-                select case(modifier)
437
+                 modifier_seq(1:1) >= '1' .and. modifier_seq(1:1) <= '9') then
477
-                case(2)  ! Shift
438
+            ! Format without leading ';' (already consumed by caller): "2" or "3" etc
478
-                    key_str = 'shift-'
439
+            read(modifier_seq(1:len_trim(modifier_seq)), '(i10)', iostat=ios) modifier
479
-                case(3)  ! Alt
440
+        else
480
-                    key_str = 'alt-'
441
+            ios = -1
481
-                case(4)  ! Alt+Shift
442
+        end if
482
-                    key_str = 'alt-shift-'
483
-                case(5)  ! Ctrl
484
-                    key_str = 'ctrl-'
485
-                case(6)  ! Ctrl+Shift
486
-                    key_str = 'ctrl-shift-'
487
-                case(7)  ! Alt+Ctrl
488
-                    key_str = 'alt-ctrl-'
489
-                case(8)  ! Alt+Shift (or Option+Shift)
490
-                    key_str = 'alt-shift-'
491
-                case(9)  ! Alt+Cmd (or Option+Cmd on macOS)
492
-                    key_str = 'opt-meta-'
493
-                case default
494
-                    key_str = ''
495
-                end select
496
 
443
 
497
-                ! Append the key type using the terminator character
444
+        if (ios == 0) then
498
-                select case(terminator)
445
+            select case(modifier)
499
-                case('A')
446
+            case(2)  ! Shift
500
-                    key_str = trim(key_str) // 'up'
447
+                key_str = 'shift-'
501
-                case('B')
448
+            case(3)  ! Alt
502
-                    key_str = trim(key_str) // 'down'
449
+                key_str = 'alt-'
503
-                case('C')
450
+            case(4)  ! Alt+Shift
504
-                    key_str = trim(key_str) // 'right'
451
+                key_str = 'alt-shift-'
505
-                case('D')
452
+            case(5)  ! Ctrl
506
-                    key_str = trim(key_str) // 'left'
453
+                key_str = 'ctrl-'
507
-                case('H')
454
+            case(6)  ! Ctrl+Shift
508
-                    key_str = trim(key_str) // 'home'
455
+                key_str = 'ctrl-shift-'
509
-                case('F')
456
+            case(7)  ! Alt+Ctrl
510
-                    key_str = trim(key_str) // 'end'
457
+                key_str = 'alt-ctrl-'
511
-                case('Z')
458
+            case(8)  ! Alt+Shift (or Option+Shift)
512
-                    ! Shift+Z could be ctrl-shift-z for redo
459
+                key_str = 'alt-shift-'
513
-                    if (index(key_str, 'ctrl-shift') == 1) then
460
+            case(9)  ! Alt+Cmd (or Option+Cmd on macOS)
514
-                        key_str = 'ctrl-shift-z'
461
+                key_str = 'opt-meta-'
515
-                    else
462
+            case default
516
-                        key_str = trim(key_str) // 'Z'
463
+                key_str = ''
517
-                    end if
464
+            end select
518
-                case('~')
465
+
519
-                    ! Check what special key it is based on the beginning of modifier_seq
466
+            ! Append the key type using the terminator character
520
-                    if (index(modifier_seq, ';') == 1 .and. len_trim(modifier_seq) > 1) then
467
+            select case(terminator)
521
-                        ! Already read the ;2 or ;5 etc, the key type should be before
468
+            case('A')
522
-                        key_str = trim(key_str) // 'unknown'
469
+                key_str = trim(key_str) // 'up'
523
-                    end if
470
+            case('B')
524
-                end select
471
+                key_str = trim(key_str) // 'down'
525
-            end if
472
+            case('C')
473
+                key_str = trim(key_str) // 'right'
474
+            case('D')
475
+                key_str = trim(key_str) // 'left'
476
+            case('H')
477
+                key_str = trim(key_str) // 'home'
478
+            case('F')
479
+                key_str = trim(key_str) // 'end'
480
+            case('Z')
481
+                ! Shift+Z could be ctrl-shift-z for redo
482
+                if (index(key_str, 'ctrl-shift') == 1) then
483
+                    key_str = 'ctrl-shift-z'
484
+                else
485
+                    key_str = trim(key_str) // 'Z'
486
+                end if
487
+            case('~')
488
+                ! Check what special key it is based on the beginning of modifier_seq
489
+                if (index(modifier_seq, ';') == 1 .and. len_trim(modifier_seq) > 1) then
490
+                    ! Already read the ;2 or ;5 etc, the key type should be before
491
+                    key_str = trim(key_str) // 'unknown'
492
+                end if
493
+            end select
526
         end if
494
         end if
527
     end subroutine handle_modified_key
495
     end subroutine handle_modified_key
528
 
496
 
src/ui/help_display_module.f90modified
@@ -114,7 +114,7 @@ contains
114
         n_lines = n_lines + 7 + 2   ! PANES
114
         n_lines = n_lines + 7 + 2   ! PANES
115
         n_lines = n_lines + 10 + 2  ! GIT
115
         n_lines = n_lines + 10 + 2  ! GIT
116
         n_lines = n_lines + 5 + 2   ! FILE
116
         n_lines = n_lines + 5 + 2   ! FILE
117
-        n_lines = n_lines + 6 + 2   ! LSP
117
+        n_lines = n_lines + 7 + 2   ! LSP (added code actions)
118
 
118
 
119
         allocate(lines(n_lines))
119
         allocate(lines(n_lines))
120
         i = 1
120
         i = 1
@@ -244,14 +244,14 @@ contains
244
         ! LSP (Language Server Protocol)
244
         ! LSP (Language Server Protocol)
245
         lines(i) = "LSP (Language Server Protocol)"; i = i + 1
245
         lines(i) = "LSP (Language Server Protocol)"; i = i + 1
246
         lines(i) = "  ctrl-space          code completion"; i = i + 1
246
         lines(i) = "  ctrl-space          code completion"; i = i + 1
247
-        lines(i) = "  ctrl-h              hover information"; i = i + 1
247
+        lines(i) = "  F12/alt-g           go to definition"; i = i + 1
248
-        lines(i) = "  F12                 go to definition"; i = i + 1
248
+        lines(i) = "  shift-F12/alt-r     find all references"; i = i + 1
249
-        lines(i) = "  shift-F12           find all references"; i = i + 1
250
         lines(i) = "  alt-, (alt-comma)   jump back (navigation history)"; i = i + 1
249
         lines(i) = "  alt-, (alt-comma)   jump back (navigation history)"; i = i + 1
251
         lines(i) = "  F2                  rename symbol"; i = i + 1
250
         lines(i) = "  F2                  rename symbol"; i = i + 1
252
-        lines(i) = "  F4                  document symbols (outline)"; i = i + 1
251
+        lines(i) = "  F10/alt-.           code actions (quick fixes)"; i = i + 1
253
-        lines(i) = "  F6                  workspace symbols (search project)"; i = i + 1
252
+        lines(i) = "  F4/alt-o            document symbols (outline)"; i = i + 1
254
-        lines(i) = "  F8                  toggle diagnostics panel (errors)"; 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
255
         lines(i) = "  ctrl-p              command palette"; i = i + 1
256
         lines(i) = ""; i = i + 1
256
         lines(i) = ""; i = i + 1
257
 
257
 
src/ui/rename_prompt_module.f90modified
@@ -23,18 +23,6 @@ contains
23
         ! Show the text prompt
23
         ! Show the text prompt
24
         call show_text_prompt(trim(prompt_text), input_text, cancelled, screen_rows)
24
         call show_text_prompt(trim(prompt_text), input_text, cancelled, screen_rows)
25
 
25
 
26
-        ! Debug logging
27
-        block
28
-            integer :: debug_unit
29
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
30
-            write(debug_unit, '(A)') '>>> RENAME PROMPT RETURNED <<<'
31
-            write(debug_unit, '(A,L1)') 'Cancelled: ', cancelled
32
-            write(debug_unit, '(A)') 'Input text: "' // trim(input_text) // '"'
33
-            write(debug_unit, '(A)') 'Old name: "' // trim(old_name) // '"'
34
-            write(debug_unit, '(A,I0)') 'Input length: ', len_trim(input_text)
35
-            close(debug_unit)
36
-        end block
37
-
38
         if (.not. cancelled) then
26
         if (.not. cancelled) then
39
             if (len_trim(input_text) > 0 .and. trim(input_text) /= trim(old_name)) then
27
             if (len_trim(input_text) > 0 .and. trim(input_text) /= trim(old_name)) then
40
                 allocate(character(len=len_trim(input_text)) :: new_name)
28
                 allocate(character(len=len_trim(input_text)) :: new_name)
@@ -43,19 +31,6 @@ contains
43
                 cancelled = .true.
31
                 cancelled = .true.
44
             end if
32
             end if
45
         end if
33
         end if
46
-
47
-        ! Debug logging after check
48
-        block
49
-            integer :: debug_unit
50
-            open(newunit=debug_unit, file='/tmp/fac_keys.log', position='append', action='write')
51
-            write(debug_unit, '(A,L1)') 'Final cancelled: ', cancelled
52
-            if (allocated(new_name)) then
53
-                write(debug_unit, '(A)') 'New name allocated: "' // trim(new_name) // '"'
54
-            else
55
-                write(debug_unit, '(A)') 'New name NOT allocated'
56
-            end if
57
-            close(debug_unit)
58
-        end block
59
     end subroutine show_rename_prompt
34
     end subroutine show_rename_prompt
60
 
35
 
61
 end module rename_prompt_module
36
 end module rename_prompt_module
src/workspace/workspace_module.f90modified
@@ -231,25 +231,9 @@ contains
231
         success = .false.
231
         success = .false.
232
         workspace_file = trim(dir_path) // "/.fac/workspace.json"
232
         workspace_file = trim(dir_path) // "/.fac/workspace.json"
233
 
233
 
234
-        ! DEBUG: Write to stderr (unit 0) so it doesn't interfere
235
-        write(0, '(A)') '[DEBUG SAVE] workspace_save_state called'
236
-        write(0, '(A)') '[DEBUG SAVE] Workspace file: ' // trim(workspace_file)
237
-        if (allocated(editor%tabs)) then
238
-            write(0, '(A,I0)') '[DEBUG SAVE] Tabs allocated, size: ', size(editor%tabs)
239
-            if (size(editor%tabs) > 0) then
240
-                write(0, '(A)') '[DEBUG SAVE] First tab filename: ' // trim(editor%tabs(1)%filename)
241
-            end if
242
-        else
243
-            write(0, '(A)') '[DEBUG SAVE] ERROR: Tabs not allocated!'
244
-        end if
245
-        write(0, '(A,I0)') '[DEBUG SAVE] Active tab index: ', editor%active_tab_index
246
-
247
         ! Open file for writing
234
         ! Open file for writing
248
         open(newunit=unit, file=workspace_file, status='replace', iostat=ios)
235
         open(newunit=unit, file=workspace_file, status='replace', iostat=ios)
249
-        if (ios /= 0) then
236
+        if (ios /= 0) return
250
-            write(0, '(A,I0)') '[DEBUG SAVE] ERROR: Failed to open file, ios=', ios
251
-            return
252
-        end if
253
 
237
 
254
         ! Get current timestamp (simplified)
238
         ! Get current timestamp (simplified)
255
         call date_and_time(timestamp)
239
         call date_and_time(timestamp)
@@ -263,7 +247,6 @@ contains
263
 
247
 
264
         ! Write tabs
248
         ! Write tabs
265
         if (allocated(editor%tabs)) then
249
         if (allocated(editor%tabs)) then
266
-            write(0, '(A,I0)') '[DEBUG SAVE] Writing ', size(editor%tabs), ' tabs'
267
             ws_len = len_trim(dir_path)
250
             ws_len = len_trim(dir_path)
268
             do i = 1, size(editor%tabs)
251
             do i = 1, size(editor%tabs)
269
                 ! Write tab start - must be on its own line for parser
252
                 ! Write tab start - must be on its own line for parser
@@ -426,33 +409,18 @@ contains
426
         logical :: file_exists
409
         logical :: file_exists
427
         integer :: load_status, tab_idx, pane_count, file_unit
410
         integer :: load_status, tab_idx, pane_count, file_unit
428
         character(len=20) :: value_str
411
         character(len=20) :: value_str
429
-        character(len=512) :: warning_msg
430
-
431
-        ! DEBUG: Start of restoration
432
-        write(0, '(A)') '[DEBUG RESTORE WS] workspace_restore_state called'
433
-        write(0, '(A)') '[DEBUG RESTORE WS] Dir path: ' // trim(dir_path)
434
 
412
 
435
         success = .false.
413
         success = .false.
436
         workspace_file = trim(dir_path) // "/.fac/workspace.json"
414
         workspace_file = trim(dir_path) // "/.fac/workspace.json"
437
 
415
 
438
-        write(0, '(A)') '[DEBUG RESTORE WS] Workspace file: ' // trim(workspace_file)
439
-
440
         ! Open workspace file
416
         ! Open workspace file
441
         open(newunit=unit, file=workspace_file, status='old', iostat=ios)
417
         open(newunit=unit, file=workspace_file, status='old', iostat=ios)
442
         if (ios /= 0) then
418
         if (ios /= 0) then
443
-            ! Workspace file doesn't exist or can't be read (Phase 7: error handling)
419
+            ! Workspace file doesn't exist or can't be read - initialize new workspace
444
-            write(0, '(A,I0)') '[DEBUG RESTORE WS] ERROR: Failed to open workspace.json, ios=', ios
445
-            warning_msg = "Warning: Could not open workspace.json - using empty workspace"
446
-            call terminal_write(trim(warning_msg))
447
-            ! Brief pause so user can see the warning
448
-            call execute_command_line("sleep 1.0", wait=.true.)
449
-            ! Initialize a new workspace instead
450
             call workspace_init(dir_path, success)
420
             call workspace_init(dir_path, success)
451
             return
421
             return
452
         end if
422
         end if
453
 
423
 
454
-        write(0, '(A)') '[DEBUG RESTORE WS] Workspace file opened successfully'
455
-
456
         ! Parse JSON line by line (simple parser for our specific format)
424
         ! Parse JSON line by line (simple parser for our specific format)
457
         in_tabs_array = .false.
425
         in_tabs_array = .false.
458
         reading_tab = .false.
426
         reading_tab = .false.
@@ -601,28 +569,19 @@ contains
601
                         end if
569
                         end if
602
 
570
 
603
                         if (.not. file_exists) then
571
                         if (.not. file_exists) then
604
-                            ! File doesn't exist - show warning and skip this tab
572
+                            ! File doesn't exist - skip this tab silently
605
-                            warning_msg = "Warning: File not found (skipping): " // trim(full_path)
606
-                            call terminal_write(trim(warning_msg))
607
-                            ! Brief pause so user can see the warning
608
-                            call execute_command_line("sleep 0.8", wait=.true.)
609
-                            ! Continue to next tab without creating this one
610
                             reading_pane = .false.
573
                             reading_pane = .false.
611
                             cycle
574
                             cycle
612
                         end if
575
                         end if
613
 
576
 
614
                         ! Create tab
577
                         ! Create tab
615
-                        write(0, '(A)') '[DEBUG RESTORE WS] Creating tab for file: ' // trim(full_path)
616
                         call create_tab(editor, trim(full_path))
578
                         call create_tab(editor, trim(full_path))
617
                         tab_idx = editor%active_tab_index
579
                         tab_idx = editor%active_tab_index
618
 
580
 
619
                         ! Set orphan flag and load file
581
                         ! Set orphan flag and load file
620
                         if (allocated(editor%tabs) .and. tab_idx > 0) then
582
                         if (allocated(editor%tabs) .and. tab_idx > 0) then
621
-                            write(0, '(A,I0)') '[DEBUG RESTORE WS] Tab created successfully, index: ', tab_idx
622
                             editor%tabs(tab_idx)%is_orphan = is_orphan
583
                             editor%tabs(tab_idx)%is_orphan = is_orphan
623
-
624
                             call buffer_load_file(editor%tabs(tab_idx)%buffer, trim(full_path), load_status)
584
                             call buffer_load_file(editor%tabs(tab_idx)%buffer, trim(full_path), load_status)
625
-                            write(0, '(A,I0)') '[DEBUG RESTORE WS] Buffer loaded, status: ', load_status
626
 
585
 
627
                             ! Send LSP didOpen notification for restored tabs
586
                             ! Send LSP didOpen notification for restored tabs
628
                             if (load_status == 0 .and. editor%tabs(tab_idx)%num_lsp_servers > 0) then
587
                             if (load_status == 0 .and. editor%tabs(tab_idx)%num_lsp_servers > 0) then
@@ -799,11 +758,8 @@ contains
799
 
758
 
800
         close(unit)
759
         close(unit)
801
 
760
 
802
-        write(0, '(A)') '[DEBUG RESTORE WS] Finished parsing JSON'
803
-
804
         ! Clamp active_tab_index to valid range
761
         ! Clamp active_tab_index to valid range
805
         if (allocated(editor%tabs)) then
762
         if (allocated(editor%tabs)) then
806
-            write(0, '(A,I0)') '[DEBUG RESTORE WS] Tabs allocated, count: ', size(editor%tabs)
807
             if (size(editor%tabs) > 0) then
763
             if (size(editor%tabs) > 0) then
808
                 if (editor%active_tab_index > size(editor%tabs)) then
764
                 if (editor%active_tab_index > size(editor%tabs)) then
809
                     editor%active_tab_index = size(editor%tabs)
765
                     editor%active_tab_index = size(editor%tabs)
@@ -812,16 +768,12 @@ contains
812
                     editor%active_tab_index = 1
768
                     editor%active_tab_index = 1
813
                 end if
769
                 end if
814
             else
770
             else
815
-                write(0, '(A)') '[DEBUG RESTORE WS] No tabs in array!'
816
                 editor%active_tab_index = 0  ! No tabs
771
                 editor%active_tab_index = 0  ! No tabs
817
             end if
772
             end if
818
         else
773
         else
819
-            write(0, '(A)') '[DEBUG RESTORE WS] Tabs NOT allocated!'
820
             editor%active_tab_index = 0  ! No tabs
774
             editor%active_tab_index = 0  ! No tabs
821
         end if
775
         end if
822
 
776
 
823
-        write(0, '(A,I0)') '[DEBUG RESTORE WS] Final active_tab_index: ', editor%active_tab_index
824
-
825
         ! Sync the active pane to editor state so status bar shows correct filename
777
         ! Sync the active pane to editor state so status bar shows correct filename
826
         if (allocated(editor%tabs) .and. editor%active_tab_index > 0) then
778
         if (allocated(editor%tabs) .and. editor%active_tab_index > 0) then
827
             if (editor%active_tab_index <= size(editor%tabs)) then
779
             if (editor%active_tab_index <= size(editor%tabs)) then
@@ -829,7 +781,6 @@ contains
829
                     if (editor%tabs(editor%active_tab_index)%active_pane_index > 0 .and. &
781
                     if (editor%tabs(editor%active_tab_index)%active_pane_index > 0 .and. &
830
                         editor%tabs(editor%active_tab_index)%active_pane_index <= &
782
                         editor%tabs(editor%active_tab_index)%active_pane_index <= &
831
                         size(editor%tabs(editor%active_tab_index)%panes)) then
783
                         size(editor%tabs(editor%active_tab_index)%panes)) then
832
-                        write(0, '(A)') '[DEBUG RESTORE WS] Syncing active pane to editor'
833
                         call sync_pane_to_editor(editor, editor%active_tab_index, &
784
                         call sync_pane_to_editor(editor, editor%active_tab_index, &
834
                                                 editor%tabs(editor%active_tab_index)%active_pane_index)
785
                                                 editor%tabs(editor%active_tab_index)%active_pane_index)
835
                     end if
786
                     end if
@@ -838,7 +789,6 @@ contains
838
         end if
789
         end if
839
 
790
 
840
         success = .true.
791
         success = .true.
841
-        write(0, '(A)') '[DEBUG RESTORE WS] workspace_restore_state completed successfully'
842
     end subroutine workspace_restore_state
792
     end subroutine workspace_restore_state
843
 
793
 
844
     !> Track workspace in recents (helper function)
794
     !> Track workspace in recents (helper function)
tests/scratch_files/calculator.pymodified
@@ -11,6 +11,7 @@ Test these features:
11
 - Formatting: Shift+Alt+F to format
11
 - Formatting: Shift+Alt+F to format
12
 """
12
 """
13
 
13
 
14
+
14
 def add(x, y):
15
 def add(x, y):
15
     """Add two numbers together."""
16
     """Add two numbers together."""
16
     return x + y
17
     return x + y
tests/scratch_files/long_errors.pymodified
@@ -1,6 +1,6 @@
1
 # Test file with errors that generate long diagnostic messages
1
 # Test file with errors that generate long diagnostic messages
2
 
2
 
3
-from typing import Dict, List, Optional, Union, Callable
3
+from typing import Callable, Dict, List, Optional, Union
4
 
4
 
5
 # Type mismatch with long type names
5
 # Type mismatch with long type names
6
 def process_data(
6
 def process_data(