Fortran · 4853 bytes Raw Blame History
1 module app_state_module
2 use config_module, only: get_config_dir, ensure_config_dir
3 implicit none
4 private
5
6 public :: app_state_t
7 public :: app_state_load, app_state_save
8 public :: is_first_run, mark_first_run_complete
9
10 type :: app_state_t
11 logical :: first_run_completed = .false.
12 logical :: lsp_installer_seen = .false.
13 character(len=16) :: version = '1.0'
14 end type app_state_t
15
16 contains
17
18 subroutine app_state_load(state)
19 type(app_state_t), intent(out) :: state
20 character(len=:), allocatable :: config_dir
21 character(len=512) :: state_file
22 character(len=1024) :: line
23 integer :: unit_num, ios
24 logical :: file_exists
25
26 ! Initialize defaults
27 state%first_run_completed = .false.
28 state%lsp_installer_seen = .false.
29 state%version = '1.0'
30
31 ! Get config directory
32 call get_config_dir(config_dir)
33 if (.not. allocated(config_dir)) return
34 state_file = trim(config_dir) // '/state.json'
35
36 ! Check if file exists
37 inquire(file=trim(state_file), exist=file_exists)
38 if (.not. file_exists) return
39
40 ! Read and parse JSON
41 open(newunit=unit_num, file=trim(state_file), status='old', &
42 action='read', iostat=ios)
43 if (ios /= 0) return
44
45 do
46 read(unit_num, '(A)', iostat=ios) line
47 if (ios /= 0) exit
48
49 ! Parse simple JSON fields
50 if (index(line, '"first_run_completed"') > 0) then
51 if (index(line, 'true') > 0) then
52 state%first_run_completed = .true.
53 else
54 state%first_run_completed = .false.
55 end if
56 else if (index(line, '"lsp_installer_seen"') > 0) then
57 if (index(line, 'true') > 0) then
58 state%lsp_installer_seen = .true.
59 else
60 state%lsp_installer_seen = .false.
61 end if
62 else if (index(line, '"version"') > 0) then
63 call extract_json_string(line, 'version', state%version)
64 end if
65 end do
66
67 close(unit_num)
68 end subroutine app_state_load
69
70 subroutine app_state_save(state)
71 type(app_state_t), intent(in) :: state
72 character(len=:), allocatable :: config_dir
73 character(len=512) :: state_file
74 integer :: unit_num, ios
75 logical :: dir_success
76
77 ! Ensure config directory exists
78 call ensure_config_dir(dir_success)
79 if (.not. dir_success) return
80
81 ! Get config directory
82 call get_config_dir(config_dir)
83 if (.not. allocated(config_dir)) return
84 state_file = trim(config_dir) // '/state.json'
85
86 ! Write JSON
87 open(newunit=unit_num, file=trim(state_file), status='replace', &
88 action='write', iostat=ios)
89 if (ios /= 0) return
90
91 write(unit_num, '(A)') '{'
92 if (state%first_run_completed) then
93 write(unit_num, '(A)') ' "first_run_completed": true,'
94 else
95 write(unit_num, '(A)') ' "first_run_completed": false,'
96 end if
97 if (state%lsp_installer_seen) then
98 write(unit_num, '(A)') ' "lsp_installer_seen": true,'
99 else
100 write(unit_num, '(A)') ' "lsp_installer_seen": false,'
101 end if
102 write(unit_num, '(A)') ' "version": "' // trim(state%version) // '"'
103 write(unit_num, '(A)') '}'
104
105 close(unit_num)
106 end subroutine app_state_save
107
108 function is_first_run() result(first_run)
109 logical :: first_run
110 type(app_state_t) :: state
111
112 call app_state_load(state)
113 first_run = .not. state%first_run_completed
114 end function is_first_run
115
116 subroutine mark_first_run_complete()
117 type(app_state_t) :: state
118
119 call app_state_load(state)
120 state%first_run_completed = .true.
121 call app_state_save(state)
122 end subroutine mark_first_run_complete
123
124 subroutine extract_json_string(line, key, value)
125 character(len=*), intent(in) :: line, key
126 character(len=*), intent(out) :: value
127 integer :: key_pos, colon_pos, quote1, quote2
128
129 value = ''
130 key_pos = index(line, '"' // trim(key) // '"')
131 if (key_pos == 0) return
132
133 colon_pos = index(line(key_pos:), ':')
134 if (colon_pos == 0) return
135 colon_pos = key_pos + colon_pos
136
137 quote1 = index(line(colon_pos:), '"')
138 if (quote1 == 0) return
139 quote1 = colon_pos + quote1
140
141 quote2 = index(line(quote1:), '"')
142 if (quote2 == 0) return
143 quote2 = quote1 + quote2 - 2
144
145 if (quote2 >= quote1) then
146 value = line(quote1:quote2)
147 end if
148 end subroutine extract_json_string
149
150 end module app_state_module
151