Fortran · 4336 bytes Raw Blame History
1 module document_sync_module
2 use iso_fortran_env, only: int32, int64, real64
3 use lsp_server_manager_module, only: notify_file_changed
4 implicit none
5 private
6
7 public :: document_sync_t
8 public :: init_document_sync, cleanup_document_sync
9 public :: notify_document_change, flush_pending_changes
10 public :: set_sync_delay
11
12 ! Document synchronization manager with debouncing
13 type :: document_sync_t
14 integer :: version = 0 ! Current document version
15 character(len=:), allocatable :: uri ! File URI
16 character(len=:), allocatable :: pending_content ! Pending content to send
17 real(real64) :: last_change_time = 0.0 ! Time of last change (for debouncing)
18 real(real64) :: sync_delay = 0.5 ! Delay before sending (in seconds)
19 logical :: has_pending_changes = .false. ! Flag for pending changes
20 integer :: server_index = 0 ! LSP server handling this document
21 end type document_sync_t
22
23 contains
24
25 subroutine init_document_sync(sync, uri, server_index)
26 type(document_sync_t), intent(out) :: sync
27 character(len=*), intent(in) :: uri
28 integer, intent(in) :: server_index
29
30 sync%version = 0
31 sync%uri = uri
32 sync%server_index = server_index
33 sync%sync_delay = 0.5 ! 500ms default
34 sync%has_pending_changes = .false.
35 sync%last_change_time = 0.0
36 end subroutine init_document_sync
37
38 subroutine cleanup_document_sync(sync)
39 type(document_sync_t), intent(inout) :: sync
40
41 if (allocated(sync%uri)) deallocate(sync%uri)
42 if (allocated(sync%pending_content)) deallocate(sync%pending_content)
43 sync%has_pending_changes = .false.
44 end subroutine cleanup_document_sync
45
46 subroutine set_sync_delay(sync, delay_seconds)
47 type(document_sync_t), intent(inout) :: sync
48 real(real64), intent(in) :: delay_seconds
49
50 sync%sync_delay = max(0.1_real64, min(2.0_real64, delay_seconds)) ! Clamp between 100ms and 2s
51 end subroutine set_sync_delay
52
53 ! Notify that the document has changed (with debouncing)
54 subroutine notify_document_change(sync, content)
55 type(document_sync_t), intent(inout) :: sync
56 character(len=*), intent(in) :: content
57
58 ! Update pending content
59 if (allocated(sync%pending_content)) deallocate(sync%pending_content)
60 sync%pending_content = content
61
62 ! Mark that we have pending changes
63 sync%has_pending_changes = .true.
64
65 ! Update timestamp
66 sync%last_change_time = get_current_time()
67 end subroutine notify_document_change
68
69 ! Check if enough time has passed and flush pending changes
70 subroutine flush_pending_changes(sync, manager, force)
71 use lsp_server_manager_module, only: lsp_manager_t, notify_file_changed
72 type(document_sync_t), intent(inout) :: sync
73 type(lsp_manager_t), intent(inout) :: manager
74 logical, intent(in), optional :: force
75 real(real64) :: current_time, elapsed
76 logical :: should_flush
77
78 if (.not. sync%has_pending_changes) return
79
80 should_flush = .false.
81 if (present(force)) then
82 should_flush = force
83 else
84 ! Check if enough time has elapsed
85 current_time = get_current_time()
86 elapsed = current_time - sync%last_change_time
87 should_flush = (elapsed >= sync%sync_delay)
88 end if
89
90 if (should_flush .and. allocated(sync%pending_content)) then
91 ! Increment version
92 sync%version = sync%version + 1
93
94 ! Send the notification
95 call notify_file_changed(manager, sync%server_index, &
96 sync%uri, sync%pending_content)
97
98 ! Clear pending changes
99 sync%has_pending_changes = .false.
100 deallocate(sync%pending_content)
101 end if
102 end subroutine flush_pending_changes
103
104 ! Helper function to get current time in seconds
105 function get_current_time() result(time)
106 real(real64) :: time
107 integer(int64) :: count, count_rate
108
109 call system_clock(count, count_rate)
110 time = real(count, real64) / real(count_rate, real64)
111 end function get_current_time
112
113 end module document_sync_module