bug fixes with tabs and f6 menu
- SHA
098cb2b7b6f04c4b57ab14e284973a763d2a52ca- Parents
-
b845f07 - Tree
878a44f
098cb2b
098cb2b7b6f04c4b57ab14e284973a763d2a52cab845f07
878a44f| Status | File | + | - |
|---|---|---|---|
| M |
app/main.f90
|
47 | 6 |
| M |
src/commands/command_handler_module.f90
|
105 | 10 |
| M |
src/lsp/lsp_server_manager_module.f90
|
31 | 25 |
app/main.f90modified@@ -18,18 +18,19 @@ program facsimile | |||
| 18 | use binary_prompt_module, only: binary_file_prompt | 18 | use binary_prompt_module, only: binary_file_prompt |
| 19 | use lsp_server_manager_module, only: notify_file_opened, notify_file_changed, & | 19 | use lsp_server_manager_module, only: notify_file_opened, notify_file_changed, & |
| 20 | notify_file_closed, process_server_messages, & | 20 | notify_file_closed, process_server_messages, & |
| 21 | - set_diagnostics_handler | 21 | + set_diagnostics_handler, set_lsp_workspace_root |
| 22 | use lsp_protocol_module, only: lsp_message_t | 22 | use lsp_protocol_module, only: lsp_message_t |
| 23 | implicit none | 23 | implicit none |
| 24 | 24 | ||
| 25 | type(editor_state_t) :: editor | 25 | type(editor_state_t) :: editor |
| 26 | type(buffer_t) :: buffer | 26 | type(buffer_t) :: buffer |
| 27 | character(len=32) :: key_input | 27 | character(len=32) :: key_input |
| 28 | - character(len=512) :: filename, arg, workspace_dir | 28 | + character(len=512) :: filename, arg, workspace_dir, lsp_workspace |
| 29 | logical :: running, should_quit, is_workspace_mode, workspace_success | 29 | logical :: running, should_quit, is_workspace_mode, workspace_success |
| 30 | logical :: welcome_cancelled, is_browse, nav_cancelled, is_directory | 30 | logical :: welcome_cancelled, is_browse, nav_cancelled, is_directory |
| 31 | + logical :: explicit_lsp_workspace | ||
| 31 | character(len=:), allocatable :: selected_path | 32 | character(len=:), allocatable :: selected_path |
| 32 | - integer :: status, argc, rows, cols | 33 | + integer :: status, argc, rows, cols, i |
| 33 | 34 | ||
| 34 | 35 | ||
| 35 | ! Get command line arguments | 36 | ! Get command line arguments |
@@ -37,9 +38,37 @@ program facsimile | |||
| 37 | is_workspace_mode = .false. | 38 | is_workspace_mode = .false. |
| 38 | workspace_dir = "" | 39 | workspace_dir = "" |
| 39 | filename = "" | 40 | filename = "" |
| 41 | + lsp_workspace = "" | ||
| 42 | + explicit_lsp_workspace = .false. | ||
| 43 | + | ||
| 44 | + ! First pass: look for -w/--workspace flag | ||
| 45 | + i = 1 | ||
| 46 | + do while (i <= argc) | ||
| 47 | + call get_command_argument(i, arg) | ||
| 48 | + if (trim(arg) == '-w' .or. trim(arg) == '--workspace') then | ||
| 49 | + if (i < argc) then | ||
| 50 | + call get_command_argument(i + 1, lsp_workspace) | ||
| 51 | + explicit_lsp_workspace = .true. | ||
| 52 | + i = i + 2 | ||
| 53 | + else | ||
| 54 | + write(error_unit, '(A)') 'Error: -w/--workspace requires a directory argument' | ||
| 55 | + stop 1 | ||
| 56 | + end if | ||
| 57 | + else | ||
| 58 | + i = i + 1 | ||
| 59 | + end if | ||
| 60 | + end do | ||
| 40 | 61 | ||
| 41 | - if (argc > 0) then | 62 | + ! Second pass: handle other arguments |
| 42 | - call get_command_argument(1, arg) | 63 | + i = 1 |
| 64 | + do while (i <= argc) | ||
| 65 | + call get_command_argument(i, arg) | ||
| 66 | + | ||
| 67 | + ! Skip -w and its argument (already processed) | ||
| 68 | + if (trim(arg) == '-w' .or. trim(arg) == '--workspace') then | ||
| 69 | + i = i + 2 | ||
| 70 | + cycle | ||
| 71 | + end if | ||
| 43 | 72 | ||
| 44 | ! Handle version flags | 73 | ! Handle version flags |
| 45 | if (trim(arg) == '--version' .or. trim(arg) == '-v') then | 74 | if (trim(arg) == '--version' .or. trim(arg) == '-v') then |
@@ -53,6 +82,7 @@ program facsimile | |||
| 53 | stop | 82 | stop |
| 54 | end if | 83 | end if |
| 55 | 84 | ||
| 85 | + ! This must be the file/directory argument | ||
| 56 | ! Check if argument is a directory (workspace mode) | 86 | ! Check if argument is a directory (workspace mode) |
| 57 | ! Use test -d which is POSIX compliant (works on Linux, macOS, BSD) | 87 | ! Use test -d which is POSIX compliant (works on Linux, macOS, BSD) |
| 58 | call execute_command_line("test -d '" // trim(arg) // & | 88 | call execute_command_line("test -d '" // trim(arg) // & |
@@ -71,7 +101,10 @@ program facsimile | |||
| 71 | end if | 101 | end if |
| 72 | filename = arg | 102 | filename = arg |
| 73 | end if | 103 | end if |
| 74 | - else | 104 | + i = i + 1 |
| 105 | + end do | ||
| 106 | + | ||
| 107 | + if (argc == 0) then | ||
| 75 | ! No arguments - launch Fortress welcome menu (Phase 5) | 108 | ! No arguments - launch Fortress welcome menu (Phase 5) |
| 76 | call terminal_init() | 109 | call terminal_init() |
| 77 | call show_welcome_menu(selected_path, welcome_cancelled) | 110 | call show_welcome_menu(selected_path, welcome_cancelled) |
@@ -168,6 +201,11 @@ program facsimile | |||
| 168 | call init_editor(editor) | 201 | call init_editor(editor) |
| 169 | running = .true. | 202 | running = .true. |
| 170 | 203 | ||
| 204 | + ! Set LSP workspace root if explicit -w flag was provided | ||
| 205 | + if (explicit_lsp_workspace) then | ||
| 206 | + call set_lsp_workspace_root(editor%lsp_manager, trim(lsp_workspace)) | ||
| 207 | + end if | ||
| 208 | + | ||
| 171 | ! Set up diagnostics handler for LSP | 209 | ! Set up diagnostics handler for LSP |
| 172 | call set_diagnostics_handler(editor%lsp_manager, handle_diagnostics) | 210 | call set_diagnostics_handler(editor%lsp_manager, handle_diagnostics) |
| 173 | 211 | ||
@@ -541,9 +579,12 @@ contains | |||
| 541 | write(output_unit, '(A)') '' | 579 | write(output_unit, '(A)') '' |
| 542 | write(output_unit, '(A)') 'Usage:' | 580 | write(output_unit, '(A)') 'Usage:' |
| 543 | write(output_unit, '(A)') ' fac [filename] Open a file for editing' | 581 | write(output_unit, '(A)') ' fac [filename] Open a file for editing' |
| 582 | + write(output_unit, '(A)') ' fac [directory] Open directory in workspace mode' | ||
| 544 | write(output_unit, '(A)') ' fac Start with empty buffer' | 583 | write(output_unit, '(A)') ' fac Start with empty buffer' |
| 545 | write(output_unit, '(A)') ' fac --version, -v Show version information' | 584 | write(output_unit, '(A)') ' fac --version, -v Show version information' |
| 546 | write(output_unit, '(A)') ' fac --help, -h Show this help message' | 585 | write(output_unit, '(A)') ' fac --help, -h Show this help message' |
| 586 | + write(output_unit, '(A)') ' fac -w <dir> [file] Set LSP workspace root to <dir>' | ||
| 587 | + write(output_unit, '(A)') ' fac --workspace <dir> Same as -w' | ||
| 547 | write(output_unit, '(A)') '' | 588 | write(output_unit, '(A)') '' |
| 548 | write(output_unit, '(A)') 'Key Bindings:' | 589 | write(output_unit, '(A)') 'Key Bindings:' |
| 549 | write(output_unit, '(A)') ' Ctrl-Q Quit' | 590 | write(output_unit, '(A)') ' Ctrl-Q Quit' |
src/commands/command_handler_module.f90modified@@ -6644,7 +6644,7 @@ contains | |||
| 6644 | subroutine navigate_to_workspace_symbol(editor, buffer, symbol, should_quit) | 6644 | subroutine navigate_to_workspace_symbol(editor, buffer, symbol, should_quit) |
| 6645 | use workspace_symbols_panel_module, only: workspace_symbol_t | 6645 | use workspace_symbols_panel_module, only: workspace_symbol_t |
| 6646 | use jump_stack_module, only: push_jump_location | 6646 | use jump_stack_module, only: push_jump_location |
| 6647 | - use editor_state_module, only: switch_to_tab, create_tab, sync_pane_to_editor, sync_editor_to_pane | 6647 | + use editor_state_module, only: switch_to_tab_with_buffer, create_tab, sync_pane_to_editor, sync_editor_to_pane |
| 6648 | use text_buffer_module, only: buffer_load_file, copy_buffer | 6648 | use text_buffer_module, only: buffer_load_file, copy_buffer |
| 6649 | type(editor_state_t), intent(inout) :: editor | 6649 | type(editor_state_t), intent(inout) :: editor |
| 6650 | type(buffer_t), intent(inout) :: buffer | 6650 | type(buffer_t), intent(inout) :: buffer |
@@ -6669,27 +6669,55 @@ contains | |||
| 6669 | editor%cursors(editor%active_cursor)%column) | 6669 | editor%cursors(editor%active_cursor)%column) |
| 6670 | end if | 6670 | end if |
| 6671 | 6671 | ||
| 6672 | - ! Check if file is already open in a tab | 6672 | + ! FIRST: Check if symbol is in the currently active tab (just jump, no tab switch) |
| 6673 | + if (editor%active_tab_index > 0 .and. editor%active_tab_index <= size(editor%tabs)) then | ||
| 6674 | + if (allocated(editor%tabs(editor%active_tab_index)%filename)) then | ||
| 6675 | + if (paths_match(editor%tabs(editor%active_tab_index)%filename, filepath)) then | ||
| 6676 | + ! Same file - just jump to the position | ||
| 6677 | + editor%cursors(editor%active_cursor)%line = symbol%line + 1 ! LSP is 0-based | ||
| 6678 | + editor%cursors(editor%active_cursor)%column = symbol%column + 1 | ||
| 6679 | + editor%cursors(editor%active_cursor)%desired_column = symbol%column + 1 | ||
| 6680 | + editor%viewport_line = max(1, symbol%line + 1 - editor%screen_rows / 2) | ||
| 6681 | + call sync_editor_to_pane(editor) | ||
| 6682 | + return | ||
| 6683 | + end if | ||
| 6684 | + end if | ||
| 6685 | + end if | ||
| 6686 | + | ||
| 6687 | + ! SECOND: Check if file is open in another (inactive) tab | ||
| 6673 | do i = 1, size(editor%tabs) | 6688 | do i = 1, size(editor%tabs) |
| 6689 | + if (i == editor%active_tab_index) cycle ! Skip active tab, already checked | ||
| 6674 | if (allocated(editor%tabs(i)%filename)) then | 6690 | if (allocated(editor%tabs(i)%filename)) then |
| 6675 | - if (trim(editor%tabs(i)%filename) == trim(filepath)) then | 6691 | + if (paths_match(editor%tabs(i)%filename, filepath)) then |
| 6676 | - call switch_to_tab(editor, i) | 6692 | + ! Save current buffer and switch to existing tab |
| 6693 | + call switch_to_tab_with_buffer(editor, i, buffer) | ||
| 6677 | ! Jump to the symbol's position | 6694 | ! Jump to the symbol's position |
| 6678 | editor%cursors(editor%active_cursor)%line = symbol%line + 1 ! LSP is 0-based | 6695 | editor%cursors(editor%active_cursor)%line = symbol%line + 1 ! LSP is 0-based |
| 6679 | editor%cursors(editor%active_cursor)%column = symbol%column + 1 | 6696 | editor%cursors(editor%active_cursor)%column = symbol%column + 1 |
| 6680 | editor%cursors(editor%active_cursor)%desired_column = symbol%column + 1 | 6697 | editor%cursors(editor%active_cursor)%desired_column = symbol%column + 1 |
| 6681 | editor%viewport_line = max(1, symbol%line + 1 - editor%screen_rows / 2) | 6698 | editor%viewport_line = max(1, symbol%line + 1 - editor%screen_rows / 2) |
| 6699 | + call sync_editor_to_pane(editor) | ||
| 6682 | return | 6700 | return |
| 6683 | end if | 6701 | end if |
| 6684 | end if | 6702 | end if |
| 6685 | end do | 6703 | end do |
| 6686 | 6704 | ||
| 6687 | ! File not open - create a new tab and load the file | 6705 | ! File not open - create a new tab and load the file |
| 6688 | - call create_tab(editor, filepath) | ||
| 6689 | - | ||
| 6690 | - ! Load file content into the new tab's buffer | ||
| 6691 | block | 6706 | block |
| 6692 | - integer :: status, new_tab_idx | 6707 | + integer :: status, new_tab_idx, old_tab_idx, old_pane_idx |
| 6708 | + | ||
| 6709 | + ! CRITICAL: Save current buffer to old tab BEFORE create_tab changes active_tab_index | ||
| 6710 | + old_tab_idx = editor%active_tab_index | ||
| 6711 | + if (old_tab_idx > 0 .and. old_tab_idx <= size(editor%tabs)) then | ||
| 6712 | + old_pane_idx = editor%tabs(old_tab_idx)%active_pane_index | ||
| 6713 | + if (allocated(editor%tabs(old_tab_idx)%panes) .and. & | ||
| 6714 | + old_pane_idx > 0 .and. old_pane_idx <= size(editor%tabs(old_tab_idx)%panes)) then | ||
| 6715 | + call copy_buffer(editor%tabs(old_tab_idx)%panes(old_pane_idx)%buffer, buffer) | ||
| 6716 | + end if | ||
| 6717 | + call copy_buffer(editor%tabs(old_tab_idx)%buffer, buffer) | ||
| 6718 | + end if | ||
| 6719 | + | ||
| 6720 | + call create_tab(editor, filepath) | ||
| 6693 | 6721 | ||
| 6694 | new_tab_idx = size(editor%tabs) ! The tab we just created | 6722 | new_tab_idx = size(editor%tabs) ! The tab we just created |
| 6695 | 6723 | ||
@@ -6702,8 +6730,14 @@ contains | |||
| 6702 | call copy_buffer(editor%tabs(new_tab_idx)%panes(1)%buffer, editor%tabs(new_tab_idx)%buffer) | 6730 | call copy_buffer(editor%tabs(new_tab_idx)%panes(1)%buffer, editor%tabs(new_tab_idx)%buffer) |
| 6703 | end if | 6731 | end if |
| 6704 | 6732 | ||
| 6705 | - ! Switch to the new tab | 6733 | + ! Load the new tab's buffer into working buffer (create_tab already switched active_tab_index) |
| 6706 | - call switch_to_tab(editor, new_tab_idx) | 6734 | + call copy_buffer(buffer, editor%tabs(new_tab_idx)%buffer) |
| 6735 | + | ||
| 6736 | + ! Update editor%filename to the new tab's filename | ||
| 6737 | + if (allocated(editor%filename)) deallocate(editor%filename) | ||
| 6738 | + allocate(character(len=len(editor%tabs(new_tab_idx)%filename)) :: editor%filename) | ||
| 6739 | + editor%filename = editor%tabs(new_tab_idx)%filename | ||
| 6740 | + editor%modified = editor%tabs(new_tab_idx)%modified | ||
| 6707 | 6741 | ||
| 6708 | ! Sync the pane to editor state (this updates editor%cursors, etc.) | 6742 | ! Sync the pane to editor state (this updates editor%cursors, etc.) |
| 6709 | call sync_pane_to_editor(editor, new_tab_idx, 1) | 6743 | call sync_pane_to_editor(editor, new_tab_idx, 1) |
@@ -6724,6 +6758,67 @@ contains | |||
| 6724 | end block | 6758 | end block |
| 6725 | end subroutine navigate_to_workspace_symbol | 6759 | end subroutine navigate_to_workspace_symbol |
| 6726 | 6760 | ||
| 6761 | + ! Helper function to compare file paths (handles relative vs absolute) | ||
| 6762 | + function paths_match(path1, path2) result(match) | ||
| 6763 | + character(len=*), intent(in) :: path1, path2 | ||
| 6764 | + logical :: match | ||
| 6765 | + character(len=:), allocatable :: p1, p2 | ||
| 6766 | + | ||
| 6767 | + match = .false. | ||
| 6768 | + | ||
| 6769 | + ! Direct comparison first | ||
| 6770 | + if (trim(path1) == trim(path2)) then | ||
| 6771 | + match = .true. | ||
| 6772 | + return | ||
| 6773 | + end if | ||
| 6774 | + | ||
| 6775 | + ! Try comparing just the filenames (basename) if one is relative | ||
| 6776 | + p1 = get_path_basename(path1) | ||
| 6777 | + p2 = get_path_basename(path2) | ||
| 6778 | + | ||
| 6779 | + ! If basenames match and one path ends with the other, consider it a match | ||
| 6780 | + if (trim(p1) == trim(p2)) then | ||
| 6781 | + ! Check if one path is a suffix of the other | ||
| 6782 | + if (index(path1, trim(path2)) > 0 .or. index(path2, trim(path1)) > 0) then | ||
| 6783 | + match = .true. | ||
| 6784 | + return | ||
| 6785 | + end if | ||
| 6786 | + ! Also match if the absolute path ends with the relative path | ||
| 6787 | + if (len_trim(path1) > len_trim(path2)) then | ||
| 6788 | + if (path1(len_trim(path1)-len_trim(path2)+1:) == trim(path2)) then | ||
| 6789 | + match = .true. | ||
| 6790 | + return | ||
| 6791 | + end if | ||
| 6792 | + else if (len_trim(path2) > len_trim(path1)) then | ||
| 6793 | + if (path2(len_trim(path2)-len_trim(path1)+1:) == trim(path1)) then | ||
| 6794 | + match = .true. | ||
| 6795 | + return | ||
| 6796 | + end if | ||
| 6797 | + end if | ||
| 6798 | + end if | ||
| 6799 | + end function paths_match | ||
| 6800 | + | ||
| 6801 | + ! Get basename from a path | ||
| 6802 | + function get_path_basename(path) result(basename) | ||
| 6803 | + character(len=*), intent(in) :: path | ||
| 6804 | + character(len=:), allocatable :: basename | ||
| 6805 | + integer :: i, last_slash | ||
| 6806 | + | ||
| 6807 | + last_slash = 0 | ||
| 6808 | + do i = len_trim(path), 1, -1 | ||
| 6809 | + if (path(i:i) == '/') then | ||
| 6810 | + last_slash = i | ||
| 6811 | + exit | ||
| 6812 | + end if | ||
| 6813 | + end do | ||
| 6814 | + | ||
| 6815 | + if (last_slash > 0 .and. last_slash < len_trim(path)) then | ||
| 6816 | + basename = path(last_slash+1:len_trim(path)) | ||
| 6817 | + else | ||
| 6818 | + basename = trim(path) | ||
| 6819 | + end if | ||
| 6820 | + end function get_path_basename | ||
| 6821 | + | ||
| 6727 | ! ================================================== | 6822 | ! ================================================== |
| 6728 | ! LSP Definition Response Handler | 6823 | ! LSP Definition Response Handler |
| 6729 | ! ================================================== | 6824 | ! ================================================== |
src/lsp/lsp_server_manager_module.f90modified@@ -9,7 +9,7 @@ module lsp_server_manager_module | |||
| 9 | 9 | ||
| 10 | public :: lsp_server_t | 10 | public :: lsp_server_t |
| 11 | public :: lsp_manager_t | 11 | public :: lsp_manager_t |
| 12 | - public :: init_lsp_manager, cleanup_lsp_manager | 12 | + public :: init_lsp_manager, cleanup_lsp_manager, set_lsp_workspace_root |
| 13 | public :: get_or_start_server, stop_server | 13 | public :: get_or_start_server, stop_server |
| 14 | public :: send_request, send_notification | 14 | public :: send_request, send_notification |
| 15 | public :: process_server_messages | 15 | public :: process_server_messages |
@@ -121,6 +121,7 @@ module lsp_server_manager_module | |||
| 121 | type(callback_entry_t), allocatable :: callbacks(:) | 121 | type(callback_entry_t), allocatable :: callbacks(:) |
| 122 | integer :: num_callbacks = 0 | 122 | integer :: num_callbacks = 0 |
| 123 | procedure(diagnostics_callback), pointer, nopass :: diagnostics_handler => null() | 123 | procedure(diagnostics_callback), pointer, nopass :: diagnostics_handler => null() |
| 124 | + character(len=512) :: workspace_root = '.' ! LSP workspace root (cwd by default) | ||
| 124 | end type lsp_manager_t | 125 | end type lsp_manager_t |
| 125 | 126 | ||
| 126 | ! C interfaces | 127 | ! C interfaces |
@@ -168,17 +169,40 @@ module lsp_server_manager_module | |||
| 168 | 169 | ||
| 169 | contains | 170 | contains |
| 170 | 171 | ||
| 171 | - subroutine init_lsp_manager(manager) | 172 | + subroutine init_lsp_manager(manager, workspace_root) |
| 172 | type(lsp_manager_t), intent(out) :: manager | 173 | type(lsp_manager_t), intent(out) :: manager |
| 174 | + character(len=*), intent(in), optional :: workspace_root | ||
| 175 | + character(len=512) :: cwd | ||
| 176 | + integer :: status | ||
| 173 | 177 | ||
| 174 | allocate(manager%servers(0)) | 178 | allocate(manager%servers(0)) |
| 175 | allocate(manager%configs(0)) | 179 | allocate(manager%configs(0)) |
| 176 | allocate(manager%callbacks(0)) | 180 | allocate(manager%callbacks(0)) |
| 177 | 181 | ||
| 182 | + ! Set workspace root (default to cwd if not provided) | ||
| 183 | + if (present(workspace_root) .and. len_trim(workspace_root) > 0) then | ||
| 184 | + manager%workspace_root = trim(workspace_root) | ||
| 185 | + else | ||
| 186 | + call getcwd(cwd, status) | ||
| 187 | + if (status == 0) then | ||
| 188 | + manager%workspace_root = trim(cwd) | ||
| 189 | + else | ||
| 190 | + manager%workspace_root = '.' | ||
| 191 | + end if | ||
| 192 | + end if | ||
| 193 | + | ||
| 178 | ! Load default server configurations | 194 | ! Load default server configurations |
| 179 | call load_default_configs(manager) | 195 | call load_default_configs(manager) |
| 180 | end subroutine init_lsp_manager | 196 | end subroutine init_lsp_manager |
| 181 | 197 | ||
| 198 | + ! Set the workspace root for LSP servers (call before opening files) | ||
| 199 | + subroutine set_lsp_workspace_root(manager, workspace_root) | ||
| 200 | + type(lsp_manager_t), intent(inout) :: manager | ||
| 201 | + character(len=*), intent(in) :: workspace_root | ||
| 202 | + | ||
| 203 | + manager%workspace_root = trim(workspace_root) | ||
| 204 | + end subroutine set_lsp_workspace_root | ||
| 205 | + | ||
| 182 | subroutine cleanup_lsp_manager(manager) | 206 | subroutine cleanup_lsp_manager(manager) |
| 183 | type(lsp_manager_t), intent(inout) :: manager | 207 | type(lsp_manager_t), intent(inout) :: manager |
| 184 | integer :: i | 208 | integer :: i |
@@ -861,8 +885,6 @@ contains | |||
| 861 | character(len=*), intent(in) :: filename | 885 | character(len=*), intent(in) :: filename |
| 862 | integer :: server_index | 886 | integer :: server_index |
| 863 | character(len=:), allocatable :: language | 887 | character(len=:), allocatable :: language |
| 864 | - character(len=256) :: workspace_path | ||
| 865 | - integer :: slash_pos | ||
| 866 | 888 | ||
| 867 | server_index = 0 | 889 | server_index = 0 |
| 868 | 890 | ||
@@ -870,16 +892,8 @@ contains | |||
| 870 | language = get_language_for_file(filename) | 892 | language = get_language_for_file(filename) |
| 871 | if (language == "") return | 893 | if (language == "") return |
| 872 | 894 | ||
| 873 | - ! Extract workspace path from filename (directory containing file) | 895 | + ! Use manager's workspace_root (set during init, defaults to cwd) |
| 874 | - slash_pos = index(filename, '/', back=.true.) | 896 | + server_index = get_or_start_server(manager, language, trim(manager%workspace_root)) |
| 875 | - if (slash_pos > 0) then | ||
| 876 | - workspace_path = filename(1:slash_pos-1) | ||
| 877 | - else | ||
| 878 | - workspace_path = "." | ||
| 879 | - end if | ||
| 880 | - | ||
| 881 | - ! Get or start server for this language | ||
| 882 | - server_index = get_or_start_server(manager, language, trim(workspace_path)) | ||
| 883 | end function start_lsp_for_file | 897 | end function start_lsp_for_file |
| 884 | 898 | ||
| 885 | ! Start ALL LSP servers that match a file (multi-server support) | 899 | ! Start ALL LSP servers that match a file (multi-server support) |
@@ -889,8 +903,7 @@ contains | |||
| 889 | integer, allocatable, intent(out) :: server_indices(:) | 903 | integer, allocatable, intent(out) :: server_indices(:) |
| 890 | integer, intent(out) :: num_servers | 904 | integer, intent(out) :: num_servers |
| 891 | character(len=:), allocatable :: language | 905 | character(len=:), allocatable :: language |
| 892 | - character(len=256) :: workspace_path | 906 | + integer :: i, idx |
| 893 | - integer :: slash_pos, i, idx | ||
| 894 | integer :: temp_indices(20) ! Max 20 servers per file | 907 | integer :: temp_indices(20) ! Max 20 servers per file |
| 895 | 908 | ||
| 896 | num_servers = 0 | 909 | num_servers = 0 |
@@ -900,19 +913,12 @@ contains | |||
| 900 | language = get_language_for_file(filename) | 913 | language = get_language_for_file(filename) |
| 901 | if (language == "") return | 914 | if (language == "") return |
| 902 | 915 | ||
| 903 | - ! Extract workspace path from filename | 916 | + ! Use manager's workspace_root (set during init, defaults to cwd) |
| 904 | - slash_pos = index(filename, '/', back=.true.) | ||
| 905 | - if (slash_pos > 0) then | ||
| 906 | - workspace_path = filename(1:slash_pos-1) | ||
| 907 | - else | ||
| 908 | - workspace_path = "." | ||
| 909 | - end if | ||
| 910 | - | ||
| 911 | ! Find ALL configs that match this language and start servers | 917 | ! Find ALL configs that match this language and start servers |
| 912 | do i = 1, manager%num_configs | 918 | do i = 1, manager%num_configs |
| 913 | if (manager%configs(i)%language == language) then | 919 | if (manager%configs(i)%language == language) then |
| 914 | ! Start or get server for this config | 920 | ! Start or get server for this config |
| 915 | - idx = get_or_start_server_by_config(manager, i, trim(workspace_path)) | 921 | + idx = get_or_start_server_by_config(manager, i, trim(manager%workspace_root)) |
| 916 | if (idx > 0 .and. num_servers < 20) then | 922 | if (idx > 0 .and. num_servers < 20) then |
| 917 | num_servers = num_servers + 1 | 923 | num_servers = num_servers + 1 |
| 918 | temp_indices(num_servers) = idx | 924 | temp_indices(num_servers) = idx |