Fortran · 4925 bytes Raw Blame History
1 module goto_prompt_module
2 use iso_fortran_env, only: input_unit, output_unit
3 use terminal_io_module
4 use editor_state_module, only: editor_state_t, cursor_t
5 use text_buffer_module
6 implicit none
7 private
8
9 public :: show_goto_prompt
10
11 contains
12
13 subroutine show_goto_prompt(editor, buffer)
14 type(editor_state_t), intent(inout) :: editor
15 type(buffer_t), intent(inout) :: buffer
16 character(len=256) :: input_buffer
17 character(len=32) :: prompt
18 integer :: input_pos, ch
19 integer :: target_line, target_col
20 integer :: line_count
21
22 ! Initialize
23 input_buffer = ''
24 input_pos = 0
25 prompt = 'Go to (line:col): '
26
27 ! Get current position for default
28 target_line = editor%cursors(editor%active_cursor)%line
29 target_col = editor%cursors(editor%active_cursor)%column
30 line_count = buffer_get_line_count(buffer)
31
32 ! Display prompt at bottom of screen
33 call terminal_move_cursor(editor%screen_rows, 1)
34 call terminal_write(prompt)
35 call terminal_show_cursor()
36
37 ! Input loop
38 do
39 ch = terminal_read_char()
40
41 if (ch == -1) then
42 ! No input, continue
43 cycle
44 else if (ch == 27) then ! ESC - cancel
45 exit
46 else if (ch == 10 .or. ch == 13) then ! Enter - accept
47 if (input_pos > 0) then
48 call parse_goto_input(input_buffer(1:input_pos), target_line, target_col)
49 end if
50
51 ! Validate and apply
52 if (target_line >= 1 .and. target_line <= line_count) then
53 editor%cursors(editor%active_cursor)%line = target_line
54 editor%cursors(editor%active_cursor)%column = max(1, target_col)
55 editor%cursors(editor%active_cursor)%desired_column = &
56 editor%cursors(editor%active_cursor)%column
57
58 ! Clear any selection
59 editor%cursors(editor%active_cursor)%has_selection = .false.
60
61 ! Update viewport to center on target
62 call center_viewport_on_cursor(editor)
63 end if
64 exit
65 else if (ch == 127 .or. ch == 8) then ! Backspace
66 if (input_pos > 0) then
67 input_pos = input_pos - 1
68 ! Redraw prompt and input
69 call terminal_move_cursor(editor%screen_rows, 1)
70 call terminal_write(prompt // input_buffer(1:input_pos) // ' ')
71 call terminal_move_cursor(editor%screen_rows, len(prompt) + input_pos + 1)
72 end if
73 else if (ch >= 32 .and. ch <= 126) then ! Printable characters
74 if (input_pos < 256) then
75 input_pos = input_pos + 1
76 input_buffer(input_pos:input_pos) = char(ch)
77 call terminal_write(char(ch))
78 end if
79 end if
80 end do
81
82 ! Clean up - hide cursor and clear prompt line
83 call terminal_hide_cursor()
84 call terminal_move_cursor(editor%screen_rows, 1)
85 call terminal_write(repeat(' ', editor%screen_cols))
86 end subroutine show_goto_prompt
87
88 subroutine parse_goto_input(input, line, col)
89 character(len=*), intent(in) :: input
90 integer, intent(out) :: line, col
91 integer :: colon_pos, ios
92 character(len=:), allocatable :: line_str, col_str
93
94 ! Default to column 1
95 col = 1
96
97 ! Find colon separator
98 colon_pos = index(input, ':')
99
100 if (colon_pos > 0) then
101 ! Parse line:column format
102 line_str = input(1:colon_pos-1)
103 col_str = input(colon_pos+1:)
104
105 ! Parse line number
106 read(line_str, '(i10)', iostat=ios) line
107 if (ios /= 0) line = 1
108
109 ! Parse column number if present
110 if (len_trim(col_str) > 0) then
111 read(col_str, '(i10)', iostat=ios) col
112 if (ios /= 0) col = 1
113 end if
114 else
115 ! Just a line number
116 read(input, '(i10)', iostat=ios) line
117 if (ios /= 0) line = 1
118 end if
119
120 ! Ensure positive values
121 line = max(1, line)
122 col = max(1, col)
123 end subroutine parse_goto_input
124
125 subroutine center_viewport_on_cursor(editor)
126 type(editor_state_t), intent(inout) :: editor
127 integer :: cursor_line
128 integer :: viewport_height
129
130 cursor_line = editor%cursors(editor%active_cursor)%line
131 viewport_height = editor%screen_rows - 2 ! Account for status bar
132
133 ! Center the cursor in the viewport
134 editor%viewport_line = max(1, cursor_line - viewport_height / 2)
135 end subroutine center_viewport_on_cursor
136
137 end module goto_prompt_module