fortrangoingonforty/fgof-lineedit / b82afdd

Browse files

Add lineedit history

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
b82afdd890e44119383a1b9097f935c102056097
Parents
cfdf263
Tree
5596511

2 changed files

StatusFile+-
M src/fgof_lineedit.f90 132 10
M src/fgof_lineedit_types.f90 10 0
src/fgof_lineedit.f90modified
@@ -1,12 +1,16 @@
11
 module fgof_lineedit
2
-  use fgof_lineedit_types, only : lineedit_state, prompt_spec
2
+  use fgof_lineedit_types, only : history_entry, lineedit_state, prompt_spec
33
   implicit none
44
   private
55
 
6
+  public :: add_history_entry
67
   public :: buffer_length
78
   public :: delete_left
89
   public :: delete_right
910
   public :: default_prompt
11
+  public :: history_count
12
+  public :: history_next
13
+  public :: history_previous
1014
   public :: init_lineedit
1115
   public :: insert_text
1216
   public :: lineedit_state
@@ -40,6 +44,10 @@ contains
4044
     editor%buffer = ""
4145
     editor%cursor = 1
4246
     editor%active = .true.
47
+    editor%history_index = 0
48
+    editor%browsing_history = .false.
49
+    editor%stashed_buffer = ""
50
+    editor%stashed_cursor = 1
4351
     call normalize_lineedit(editor)
4452
   end subroutine init_lineedit
4553
 
@@ -50,6 +58,7 @@ contains
5058
     editor%buffer = ""
5159
     editor%cursor = 1
5260
     editor%active = .false.
61
+    call clear_history_navigation(editor)
5362
   end subroutine reset_lineedit
5463
 
5564
   integer function buffer_length(editor) result(length)
@@ -68,15 +77,7 @@ contains
6877
     integer, intent(in), optional :: cursor
6978
 
7079
     call normalize_lineedit(editor)
71
-
72
-    editor%buffer = text
73
-    if (present(cursor)) then
74
-      editor%cursor = cursor
75
-    else
76
-      editor%cursor = len(text) + 1
77
-    end if
78
-
79
-    call clamp_cursor(editor)
80
+    call assign_buffer(editor, text, cursor, clear_history=.true.)
8081
   end subroutine set_buffer
8182
 
8283
   subroutine insert_text(editor, text)
@@ -87,6 +88,7 @@ contains
8788
 
8889
     call normalize_lineedit(editor)
8990
     if (len(text) == 0) return
91
+    call clear_history_navigation(editor)
9092
 
9193
     insert_at = editor%cursor
9294
     old_length = len(editor%buffer)
@@ -117,6 +119,8 @@ contains
117119
       return
118120
     end if
119121
 
122
+    call clear_history_navigation(editor)
123
+
120124
     delete_at = editor%cursor - 1
121125
     if (old_length == 1) then
122126
       editor%buffer = ""
@@ -145,6 +149,8 @@ contains
145149
       return
146150
     end if
147151
 
152
+    call clear_history_navigation(editor)
153
+
148154
     delete_at = editor%cursor
149155
     if (old_length == 1) then
150156
       editor%buffer = ""
@@ -200,14 +206,130 @@ contains
200206
     editor%cursor = len(editor%buffer) + 1
201207
   end subroutine move_cursor_end
202208
 
209
+  integer function history_count(editor) result(count)
210
+    type(lineedit_state), intent(in) :: editor
211
+
212
+    if (allocated(editor%history)) then
213
+      count = size(editor%history)
214
+    else
215
+      count = 0
216
+    end if
217
+  end function history_count
218
+
219
+  subroutine add_history_entry(editor, text)
220
+    type(lineedit_state), intent(inout) :: editor
221
+    character(len=*), intent(in) :: text
222
+    type(history_entry), allocatable :: new_history(:)
223
+    integer :: count
224
+    integer :: i
225
+
226
+    call normalize_lineedit(editor)
227
+    if (len_trim(text) == 0) return
228
+
229
+    count = history_count(editor)
230
+    allocate(new_history(count + 1))
231
+    do i = 1, count
232
+      new_history(i)%text = editor%history(i)%text
233
+    end do
234
+    new_history(count + 1)%text = text
235
+
236
+    call move_alloc(new_history, editor%history)
237
+    call clear_history_navigation(editor)
238
+  end subroutine add_history_entry
239
+
240
+  logical function history_previous(editor) result(changed)
241
+    type(lineedit_state), intent(inout) :: editor
242
+    integer :: count
243
+
244
+    call normalize_lineedit(editor)
245
+    count = history_count(editor)
246
+    if (count == 0) then
247
+      changed = .false.
248
+      return
249
+    end if
250
+
251
+    if (.not. editor%browsing_history) then
252
+      editor%stashed_buffer = editor%buffer
253
+      editor%stashed_cursor = editor%cursor
254
+      editor%browsing_history = .true.
255
+      editor%history_index = count
256
+    else if (editor%history_index > 1) then
257
+      editor%history_index = editor%history_index - 1
258
+    else
259
+      changed = .false.
260
+      return
261
+    end if
262
+
263
+    call assign_buffer(editor, editor%history(editor%history_index)%text, len(editor%history(editor%history_index)%text) + 1, &
264
+      clear_history=.false.)
265
+    changed = .true.
266
+  end function history_previous
267
+
268
+  logical function history_next(editor) result(changed)
269
+    type(lineedit_state), intent(inout) :: editor
270
+    integer :: count
271
+
272
+    call normalize_lineedit(editor)
273
+    if (.not. editor%browsing_history) then
274
+      changed = .false.
275
+      return
276
+    end if
277
+
278
+    count = history_count(editor)
279
+    if (count == 0) then
280
+      call clear_history_navigation(editor)
281
+      changed = .false.
282
+      return
283
+    end if
284
+
285
+    if (editor%history_index < count) then
286
+      editor%history_index = editor%history_index + 1
287
+      call assign_buffer(editor, editor%history(editor%history_index)%text, len(editor%history(editor%history_index)%text) + 1, &
288
+        clear_history=.false.)
289
+      changed = .true.
290
+      return
291
+    end if
292
+
293
+    call assign_buffer(editor, editor%stashed_buffer, editor%stashed_cursor, clear_history=.false.)
294
+    call clear_history_navigation(editor)
295
+    changed = .true.
296
+  end function history_next
297
+
203298
   subroutine normalize_lineedit(editor)
204299
     type(lineedit_state), intent(inout) :: editor
205300
 
206301
     if (.not. allocated(editor%prompt%text)) editor%prompt%text = ""
207302
     if (.not. allocated(editor%buffer)) editor%buffer = ""
303
+    if (.not. allocated(editor%stashed_buffer)) editor%stashed_buffer = ""
208304
     call clamp_cursor(editor)
209305
   end subroutine normalize_lineedit
210306
 
307
+  subroutine assign_buffer(editor, text, cursor, clear_history)
308
+    type(lineedit_state), intent(inout) :: editor
309
+    character(len=*), intent(in) :: text
310
+    integer, intent(in), optional :: cursor
311
+    logical, intent(in) :: clear_history
312
+
313
+    editor%buffer = text
314
+    if (present(cursor)) then
315
+      editor%cursor = cursor
316
+    else
317
+      editor%cursor = len(text) + 1
318
+    end if
319
+
320
+    call clamp_cursor(editor)
321
+    if (clear_history) call clear_history_navigation(editor)
322
+  end subroutine assign_buffer
323
+
324
+  subroutine clear_history_navigation(editor)
325
+    type(lineedit_state), intent(inout) :: editor
326
+
327
+    editor%browsing_history = .false.
328
+    editor%history_index = 0
329
+    editor%stashed_buffer = ""
330
+    editor%stashed_cursor = 1
331
+  end subroutine clear_history_navigation
332
+
211333
   subroutine clamp_cursor(editor)
212334
     type(lineedit_state), intent(inout) :: editor
213335
     integer :: max_cursor
src/fgof_lineedit_types.f90modified
@@ -2,6 +2,7 @@ module fgof_lineedit_types
22
   implicit none
33
   private
44
 
5
+  public :: history_entry
56
   public :: lineedit_state
67
   public :: prompt_spec
78
 
@@ -9,11 +10,20 @@ module fgof_lineedit_types
910
     character(len=:), allocatable :: text
1011
   end type prompt_spec
1112
 
13
+  type :: history_entry
14
+    character(len=:), allocatable :: text
15
+  end type history_entry
16
+
1217
   type :: lineedit_state
1318
     type(prompt_spec) :: prompt
1419
     character(len=:), allocatable :: buffer
1520
     integer :: cursor = 1
1621
     logical :: active = .false.
22
+    type(history_entry), allocatable :: history(:)
23
+    integer :: history_index = 0
24
+    logical :: browsing_history = .false.
25
+    character(len=:), allocatable :: stashed_buffer
26
+    integer :: stashed_cursor = 1
1727
   end type lineedit_state
1828
 
1929
 end module fgof_lineedit_types