@@ -4,6 +4,8 @@ module terminal_control |
| 4 | private | 4 | private |
| 5 | | 5 | |
| 6 | public :: get_term_size, setup_raw_mode, restore_terminal, read_arrow_key, read_arrow_key_with_shift | 6 | public :: get_term_size, setup_raw_mode, restore_terminal, read_arrow_key, read_arrow_key_with_shift |
| | 7 | + public :: enable_read_timeout, disable_read_timeout |
| | 8 | + public :: needs_extra_spacing |
| 7 | public :: ESC, CLEAR, BOLD, DIM, REVERSE, RESET | 9 | public :: ESC, CLEAR, BOLD, DIM, REVERSE, RESET |
| 8 | public :: BLUE, GREEN, RED, GREY, WHITE, YELLOW | 10 | public :: BLUE, GREEN, RED, GREY, WHITE, YELLOW |
| 9 | public :: invalidate_term_cache | 11 | public :: invalidate_term_cache |
@@ -84,13 +86,53 @@ contains |
| 84 | end subroutine get_term_size | 86 | end subroutine get_term_size |
| 85 | | 87 | |
| 86 | subroutine setup_raw_mode() | 88 | subroutine setup_raw_mode() |
| 87 | - call execute_command_line("stty -icanon -echo min 1 time 0 2>/dev/null") | 89 | + ! Blocking mode for stable operation |
| | 90 | + call execute_command_line("stty -icanon -echo min 1 time 0 2>/dev/null", wait=.true.) |
| 88 | end subroutine setup_raw_mode | 91 | end subroutine setup_raw_mode |
| 89 | | 92 | |
| | 93 | + subroutine enable_read_timeout() |
| | 94 | + ! No-op for now |
| | 95 | + end subroutine enable_read_timeout |
| | 96 | + |
| | 97 | + subroutine disable_read_timeout() |
| | 98 | + ! No-op for now |
| | 99 | + end subroutine disable_read_timeout |
| | 100 | + |
| 90 | subroutine restore_terminal() | 101 | subroutine restore_terminal() |
| 91 | call execute_command_line("stty icanon echo 2>/dev/null") | 102 | call execute_command_line("stty icanon echo 2>/dev/null") |
| 92 | end subroutine restore_terminal | 103 | end subroutine restore_terminal |
| 93 | | 104 | |
| | 105 | + function needs_extra_spacing() result(needs_spacing) |
| | 106 | + logical :: needs_spacing |
| | 107 | + character(len=256) :: term_var, alacritty_var |
| | 108 | + integer :: stat |
| | 109 | + |
| | 110 | + needs_spacing = .false. |
| | 111 | + |
| | 112 | + ! Check TERM environment variable |
| | 113 | + call get_environment_variable("TERM", term_var, status=stat) |
| | 114 | + if (stat == 0) then |
| | 115 | + ! Check if TERM contains "alacritty" or other terminals that need spacing |
| | 116 | + if (index(term_var, "alacritty") > 0) then |
| | 117 | + needs_spacing = .true. |
| | 118 | + return |
| | 119 | + end if |
| | 120 | + end if |
| | 121 | + |
| | 122 | + ! Also check for ALACRITTY_SOCKET or ALACRITTY_LOG to detect alacritty |
| | 123 | + call get_environment_variable("ALACRITTY_SOCKET", alacritty_var, status=stat) |
| | 124 | + if (stat == 0 .and. len_trim(alacritty_var) > 0) then |
| | 125 | + needs_spacing = .true. |
| | 126 | + return |
| | 127 | + end if |
| | 128 | + |
| | 129 | + call get_environment_variable("ALACRITTY_LOG", alacritty_var, status=stat) |
| | 130 | + if (stat == 0 .and. len_trim(alacritty_var) > 0) then |
| | 131 | + needs_spacing = .true. |
| | 132 | + return |
| | 133 | + end if |
| | 134 | + end function needs_extra_spacing |
| | 135 | + |
| 94 | subroutine read_arrow_key(k) | 136 | subroutine read_arrow_key(k) |
| 95 | character(len=1), intent(out) :: k | 137 | character(len=1), intent(out) :: k |
| 96 | character(len=1) :: ch | 138 | character(len=1) :: ch |