clean this up jesus
- SHA
e7598ccb53918c03fd8a3d092ea8ec67d6e7c524- Parents
-
07219b0 - Tree
0b81b1c
e7598cc
e7598ccb53918c03fd8a3d092ea8ec67d6e7c52407219b0
0b81b1c| Status | File | + | - |
|---|---|---|---|
| A |
.gitignore
|
1 | 0 |
| A |
run.sh
|
34 | 0 |
| D |
src/fortress_clean.f90
|
0 | 278 |
| D |
src/fortress_v2.f90
|
0 | 289 |
| M |
src/main.f90
|
247 | 114 |
| D |
src/simple_main.f90
|
0 | 119 |
| D |
src/test_right_pane.f90
|
0 | 31 |
.gitignoreadded@@ -0,0 +1,1 @@ | ||
| 1 | +tests/ | |
run.shadded@@ -0,0 +1,34 @@ | ||
| 1 | +#!/bin/bash | |
| 2 | + | |
| 3 | +echo "========================================" | |
| 4 | +echo " FORTRESS File Manager " | |
| 5 | +echo " Written in Modern Fortran " | |
| 6 | +echo "========================================" | |
| 7 | +echo | |
| 8 | +echo "Features:" | |
| 9 | +echo " • Dual-pane interface (parent | current)" | |
| 10 | +echo " • Full keyboard navigation" | |
| 11 | +echo " • Directory traversal" | |
| 12 | +echo " • Clean, responsive display" | |
| 13 | +echo | |
| 14 | +echo "Controls:" | |
| 15 | +echo " ↑/↓ or j/k : Navigate files" | |
| 16 | +echo " → or l : Enter directory" | |
| 17 | +echo " ← or h : Go to parent" | |
| 18 | +echo " q : Quit" | |
| 19 | +echo | |
| 20 | +echo "Building FORTRESS..." | |
| 21 | +fpm build --flag "-O2" 2>&1 | grep -E "(done|error|Error|ERROR)" || true | |
| 22 | + | |
| 23 | +# Find the built executable | |
| 24 | +FORTRESS_BIN=$(find ./build -name fortress -type f -path "*/app/*" 2>/dev/null | head -1) | |
| 25 | + | |
| 26 | +if [ -n "$FORTRESS_BIN" ] && [ -f "$FORTRESS_BIN" ]; then | |
| 27 | + echo | |
| 28 | + echo "Starting FORTRESS..." | |
| 29 | + echo "====================" | |
| 30 | + $FORTRESS_BIN | |
| 31 | +else | |
| 32 | + echo "Build failed. Please run 'fpm build' to see full error messages." | |
| 33 | + exit 1 | |
| 34 | +fi | |
src/fortress_clean.f90deleted@@ -1,278 +0,0 @@ | ||
| 1 | -program fortress_clean | |
| 2 | - use iso_fortran_env, only: output_unit, error_unit | |
| 3 | - implicit none | |
| 4 | - | |
| 5 | - ! Constants | |
| 6 | - integer, parameter :: MAX_PATH = 512 | |
| 7 | - integer, parameter :: MAX_FILES = 500 | |
| 8 | - character(len=*), parameter :: ESC = char(27) | |
| 9 | - character(len=*), parameter :: CLEAR = ESC // "[2J" // ESC // "[H" | |
| 10 | - character(len=*), parameter :: BOLD = ESC // "[1m" | |
| 11 | - character(len=*), parameter :: DIM = ESC // "[2m" | |
| 12 | - character(len=*), parameter :: REVERSE = ESC // "[7m" | |
| 13 | - character(len=*), parameter :: RESET = ESC // "[0m" | |
| 14 | - | |
| 15 | - ! Variables | |
| 16 | - character(len=MAX_PATH) :: current_dir, parent_dir, temp_dir | |
| 17 | - character(len=MAX_PATH), dimension(MAX_FILES) :: current_files, parent_files | |
| 18 | - logical, dimension(MAX_FILES) :: current_is_dir, parent_is_dir | |
| 19 | - integer :: current_count, parent_count | |
| 20 | - integer :: selected = 1 | |
| 21 | - integer :: parent_selected = -1 | |
| 22 | - character(len=1) :: key | |
| 23 | - logical :: running = .true. | |
| 24 | - integer :: i, rows, cols | |
| 25 | - | |
| 26 | - ! Initialize | |
| 27 | - current_dir = get_pwd() | |
| 28 | - parent_dir = get_parent_path(current_dir) | |
| 29 | - | |
| 30 | - ! Setup terminal | |
| 31 | - call execute_command_line("stty -icanon -echo min 1 time 0 2>/dev/null") | |
| 32 | - | |
| 33 | - ! Main loop | |
| 34 | - do while (running) | |
| 35 | - ! Get files | |
| 36 | - call get_file_list(current_dir, current_files, current_is_dir, current_count) | |
| 37 | - call get_file_list(parent_dir, parent_files, parent_is_dir, parent_count) | |
| 38 | - | |
| 39 | - ! Find current dir in parent | |
| 40 | - parent_selected = find_in_parent(current_dir, parent_files, parent_count) | |
| 41 | - | |
| 42 | - ! Get terminal size | |
| 43 | - call get_term_size(rows, cols) | |
| 44 | - | |
| 45 | - ! Draw interface | |
| 46 | - write(output_unit, '(a)', advance='no') CLEAR | |
| 47 | - call draw_interface(rows, cols) | |
| 48 | - | |
| 49 | - ! Get input | |
| 50 | - read(*, '(a1)', advance='no') key | |
| 51 | - | |
| 52 | - ! Handle input | |
| 53 | - select case(ichar(key)) | |
| 54 | - case(27) ! ESC sequence | |
| 55 | - call read_arrow_key(key) | |
| 56 | - select case(key) | |
| 57 | - case('A') ! Up | |
| 58 | - if (selected > 1) selected = selected - 1 | |
| 59 | - case('B') ! Down | |
| 60 | - if (selected < current_count) selected = selected + 1 | |
| 61 | - case('C') ! Right - enter | |
| 62 | - if (current_is_dir(selected)) then | |
| 63 | - if (trim(current_files(selected)) == "..") then | |
| 64 | - temp_dir = current_dir | |
| 65 | - current_dir = parent_dir | |
| 66 | - parent_dir = get_parent_path(current_dir) | |
| 67 | - selected = max(1, find_in_parent(temp_dir, current_files, MAX_FILES)) | |
| 68 | - else if (trim(current_files(selected)) /= ".") then | |
| 69 | - parent_dir = current_dir | |
| 70 | - current_dir = join_path(current_dir, current_files(selected)) | |
| 71 | - selected = 1 | |
| 72 | - end if | |
| 73 | - end if | |
| 74 | - case('D') ! Left - back | |
| 75 | - if (current_dir /= "/") then | |
| 76 | - temp_dir = current_dir | |
| 77 | - current_dir = parent_dir | |
| 78 | - parent_dir = get_parent_path(current_dir) | |
| 79 | - selected = max(1, find_in_parent(temp_dir, current_files, MAX_FILES)) | |
| 80 | - end if | |
| 81 | - end select | |
| 82 | - case(113, 81) ! 'q' or 'Q' | |
| 83 | - running = .false. | |
| 84 | - end select | |
| 85 | - end do | |
| 86 | - | |
| 87 | - ! Cleanup | |
| 88 | - call execute_command_line("stty icanon echo 2>/dev/null") | |
| 89 | - write(output_unit, '(a)', advance='no') CLEAR | |
| 90 | - write(output_unit, '(a)') "Thanks for using FORTRESS!" | |
| 91 | - | |
| 92 | -contains | |
| 93 | - | |
| 94 | - function get_pwd() result(path) | |
| 95 | - character(len=MAX_PATH) :: path | |
| 96 | - integer :: unit, ios | |
| 97 | - | |
| 98 | - call execute_command_line("pwd > .fortress_pwd 2>/dev/null", wait=.true.) | |
| 99 | - open(newunit=unit, file=".fortress_pwd", status='old', iostat=ios) | |
| 100 | - if (ios == 0) then | |
| 101 | - read(unit, '(a)') path | |
| 102 | - close(unit) | |
| 103 | - else | |
| 104 | - path = "." | |
| 105 | - end if | |
| 106 | - call execute_command_line("rm -f .fortress_pwd 2>/dev/null") | |
| 107 | - end function get_pwd | |
| 108 | - | |
| 109 | - function get_parent_path(path) result(parent) | |
| 110 | - character(len=*), intent(in) :: path | |
| 111 | - character(len=MAX_PATH) :: parent | |
| 112 | - integer :: pos | |
| 113 | - | |
| 114 | - pos = index(path, "/", back=.true.) | |
| 115 | - if (pos > 1) then | |
| 116 | - parent = path(1:pos-1) | |
| 117 | - else if (pos == 1) then | |
| 118 | - parent = "/" | |
| 119 | - else | |
| 120 | - parent = "." | |
| 121 | - end if | |
| 122 | - end function get_parent_path | |
| 123 | - | |
| 124 | - function join_path(base, name) result(full) | |
| 125 | - character(len=*), intent(in) :: base, name | |
| 126 | - character(len=MAX_PATH) :: full | |
| 127 | - | |
| 128 | - if (base == "/") then | |
| 129 | - full = "/" // trim(name) | |
| 130 | - else | |
| 131 | - full = trim(base) // "/" // trim(name) | |
| 132 | - end if | |
| 133 | - end function join_path | |
| 134 | - | |
| 135 | - function find_in_parent(dir, files, count) result(idx) | |
| 136 | - character(len=*), intent(in) :: dir | |
| 137 | - character(len=*), dimension(*), intent(in) :: files | |
| 138 | - integer, intent(in) :: count | |
| 139 | - integer :: idx, pos | |
| 140 | - character(len=256) :: basename | |
| 141 | - | |
| 142 | - pos = index(dir, "/", back=.true.) | |
| 143 | - if (pos > 0) then | |
| 144 | - basename = dir(pos+1:) | |
| 145 | - else | |
| 146 | - basename = dir | |
| 147 | - end if | |
| 148 | - | |
| 149 | - do idx = 1, count | |
| 150 | - if (trim(files(idx)) == trim(basename)) return | |
| 151 | - end do | |
| 152 | - idx = 1 | |
| 153 | - end function find_in_parent | |
| 154 | - | |
| 155 | - subroutine get_file_list(dir, files, is_dir, count) | |
| 156 | - character(len=*), intent(in) :: dir | |
| 157 | - character(len=*), dimension(*), intent(out) :: files | |
| 158 | - logical, dimension(*), intent(out) :: is_dir | |
| 159 | - integer, intent(out) :: count | |
| 160 | - integer :: unit, ios, stat | |
| 161 | - character(len=MAX_PATH) :: fullpath | |
| 162 | - | |
| 163 | - call execute_command_line("ls -1a '" // trim(dir) // "' > .fortress_ls 2>/dev/null", wait=.true.) | |
| 164 | - | |
| 165 | - open(newunit=unit, file=".fortress_ls", status='old', iostat=ios) | |
| 166 | - if (ios /= 0) then | |
| 167 | - count = 0 | |
| 168 | - return | |
| 169 | - end if | |
| 170 | - | |
| 171 | - count = 0 | |
| 172 | - do | |
| 173 | - count = count + 1 | |
| 174 | - if (count > MAX_FILES) exit | |
| 175 | - read(unit, '(a)', iostat=ios) files(count) | |
| 176 | - if (ios /= 0) then | |
| 177 | - count = count - 1 | |
| 178 | - exit | |
| 179 | - end if | |
| 180 | - | |
| 181 | - fullpath = join_path(dir, files(count)) | |
| 182 | - call execute_command_line("test -d '" // trim(fullpath) // "'", exitstat=stat, wait=.true.) | |
| 183 | - is_dir(count) = (stat == 0) | |
| 184 | - end do | |
| 185 | - | |
| 186 | - close(unit) | |
| 187 | - call execute_command_line("rm -f .fortress_ls 2>/dev/null") | |
| 188 | - end subroutine get_file_list | |
| 189 | - | |
| 190 | - subroutine get_term_size(r, c) | |
| 191 | - integer, intent(out) :: r, c | |
| 192 | - integer :: unit, ios | |
| 193 | - | |
| 194 | - call execute_command_line("tput lines > .fortress_size 2>/dev/null", wait=.true.) | |
| 195 | - open(newunit=unit, file=".fortress_size", status='old', iostat=ios) | |
| 196 | - if (ios == 0) then | |
| 197 | - read(unit, *) r | |
| 198 | - close(unit) | |
| 199 | - else | |
| 200 | - r = 24 | |
| 201 | - end if | |
| 202 | - | |
| 203 | - call execute_command_line("tput cols > .fortress_size 2>/dev/null", wait=.true.) | |
| 204 | - open(newunit=unit, file=".fortress_size", status='old', iostat=ios) | |
| 205 | - if (ios == 0) then | |
| 206 | - read(unit, *) c | |
| 207 | - close(unit) | |
| 208 | - else | |
| 209 | - c = 80 | |
| 210 | - end if | |
| 211 | - | |
| 212 | - call execute_command_line("rm -f .fortress_size 2>/dev/null") | |
| 213 | - end subroutine get_term_size | |
| 214 | - | |
| 215 | - subroutine draw_interface(r, c) | |
| 216 | - integer, intent(in) :: r, c | |
| 217 | - integer :: left_w, i | |
| 218 | - character(len=256) :: fname | |
| 219 | - | |
| 220 | - left_w = c * 3 / 10 | |
| 221 | - | |
| 222 | - ! Header | |
| 223 | - write(output_unit, '(a)') BOLD // "FORTRESS" // RESET // " - " // trim(current_dir) | |
| 224 | - | |
| 225 | - ! Files | |
| 226 | - do i = 1, min(r-3, max(parent_count, current_count)) | |
| 227 | - ! Parent pane | |
| 228 | - if (i <= parent_count) then | |
| 229 | - fname = parent_files(i) | |
| 230 | - if (parent_is_dir(i) .and. fname /= "." .and. fname /= "..") then | |
| 231 | - fname = trim(fname) // "/" | |
| 232 | - end if | |
| 233 | - if (i == parent_selected) then | |
| 234 | - write(output_unit, '(a)', advance='no') DIM // BOLD // fname(1:min(len_trim(fname),left_w)) // RESET | |
| 235 | - else | |
| 236 | - write(output_unit, '(a)', advance='no') DIM // fname(1:min(len_trim(fname),left_w)) // RESET | |
| 237 | - end if | |
| 238 | - write(output_unit, '(a)', advance='no') repeat(" ", max(0, left_w - len_trim(fname))) | |
| 239 | - else | |
| 240 | - write(output_unit, '(a)', advance='no') repeat(" ", left_w) | |
| 241 | - end if | |
| 242 | - | |
| 243 | - ! Separator | |
| 244 | - write(output_unit, '(a)', advance='no') " │ " | |
| 245 | - | |
| 246 | - ! Current pane | |
| 247 | - if (i <= current_count) then | |
| 248 | - fname = current_files(i) | |
| 249 | - if (current_is_dir(i) .and. fname /= "." .and. fname /= "..") then | |
| 250 | - fname = trim(fname) // "/" | |
| 251 | - end if | |
| 252 | - if (i == selected) then | |
| 253 | - write(output_unit, '(a)') REVERSE // trim(fname) // RESET | |
| 254 | - else | |
| 255 | - write(output_unit, '(a)') trim(fname) | |
| 256 | - end if | |
| 257 | - else | |
| 258 | - write(output_unit, *) | |
| 259 | - end if | |
| 260 | - end do | |
| 261 | - | |
| 262 | - ! Footer | |
| 263 | - write(output_unit, '(a,i0,a)') DIM // "↑↓:nav →:enter ←:back q:quit [", selected, "/" // trim(adjustl(char(current_count))) // "]" // RESET | |
| 264 | - end subroutine draw_interface | |
| 265 | - | |
| 266 | - subroutine read_arrow_key(k) | |
| 267 | - character(len=1), intent(out) :: k | |
| 268 | - character(len=1) :: ch | |
| 269 | - | |
| 270 | - read(*, '(a1)', advance='no') ch | |
| 271 | - if (ch == '[') then | |
| 272 | - read(*, '(a1)', advance='no') k | |
| 273 | - else | |
| 274 | - k = ch | |
| 275 | - end if | |
| 276 | - end subroutine read_arrow_key | |
| 277 | - | |
| 278 | -end program fortress_clean | |
src/fortress_v2.f90deleted@@ -1,289 +0,0 @@ | ||
| 1 | -program fortress_v2 | |
| 2 | - use iso_fortran_env, only: output_unit | |
| 3 | - implicit none | |
| 4 | - | |
| 5 | - ! File entry type | |
| 6 | - type :: file_entry | |
| 7 | - character(len=256) :: name = "" | |
| 8 | - logical :: is_dir = .false. | |
| 9 | - end type file_entry | |
| 10 | - | |
| 11 | - ! Constants | |
| 12 | - integer, parameter :: MAX_FILES = 200 | |
| 13 | - character(len=*), parameter :: ESC = char(27) | |
| 14 | - | |
| 15 | - ! State variables | |
| 16 | - type(file_entry), dimension(MAX_FILES) :: current_files, parent_files | |
| 17 | - integer :: current_count, parent_count | |
| 18 | - integer :: selected = 1 | |
| 19 | - character(len=512) :: current_path, parent_path | |
| 20 | - logical :: running = .true. | |
| 21 | - character(len=10) :: key | |
| 22 | - integer :: rows, cols | |
| 23 | - integer :: i | |
| 24 | - | |
| 25 | - ! Initialize | |
| 26 | - call get_cwd(current_path) | |
| 27 | - call get_parent(current_path, parent_path) | |
| 28 | - | |
| 29 | - ! Setup terminal | |
| 30 | - call system("stty -icanon -echo min 1 time 0") | |
| 31 | - call get_terminal_size(rows, cols) | |
| 32 | - | |
| 33 | - ! Main loop | |
| 34 | - do while (running) | |
| 35 | - ! Get directory contents | |
| 36 | - call list_dir(current_path, current_files, current_count) | |
| 37 | - call list_dir(parent_path, parent_files, parent_count) | |
| 38 | - | |
| 39 | - ! Draw screen | |
| 40 | - call clear_screen() | |
| 41 | - call draw_header(current_path) | |
| 42 | - call draw_panes(parent_files, parent_count, current_files, current_count, selected, rows, cols) | |
| 43 | - call draw_footer() | |
| 44 | - | |
| 45 | - ! Get keyboard input | |
| 46 | - call get_key(key) | |
| 47 | - | |
| 48 | - ! Handle input | |
| 49 | - select case(trim(key)) | |
| 50 | - case('A') ! Up arrow | |
| 51 | - if (selected > 1) selected = selected - 1 | |
| 52 | - case('B') ! Down arrow | |
| 53 | - if (selected < current_count) selected = selected + 1 | |
| 54 | - case('C') ! Right arrow - enter directory | |
| 55 | - if (selected <= current_count .and. current_files(selected)%is_dir) then | |
| 56 | - if (trim(current_files(selected)%name) /= ".") then | |
| 57 | - call change_dir(current_path, current_files(selected)%name, parent_path) | |
| 58 | - selected = 1 | |
| 59 | - end if | |
| 60 | - end if | |
| 61 | - case('D') ! Left arrow - go to parent | |
| 62 | - if (trim(current_path) /= "/") then | |
| 63 | - current_path = parent_path | |
| 64 | - call get_parent(current_path, parent_path) | |
| 65 | - selected = 1 | |
| 66 | - end if | |
| 67 | - case('q', 'Q') | |
| 68 | - running = .false. | |
| 69 | - end select | |
| 70 | - end do | |
| 71 | - | |
| 72 | - ! Cleanup | |
| 73 | - call system("stty icanon echo") | |
| 74 | - call clear_screen() | |
| 75 | - write(output_unit, '(a)') "Thanks for using FORTRESS v2!" | |
| 76 | - | |
| 77 | -contains | |
| 78 | - | |
| 79 | - subroutine get_cwd(path) | |
| 80 | - character(len=*), intent(out) :: path | |
| 81 | - integer :: unit, ios | |
| 82 | - | |
| 83 | - call execute_command_line("pwd > pwd_temp.txt", wait=.true.) | |
| 84 | - open(newunit=unit, file="pwd_temp.txt", status='old', iostat=ios) | |
| 85 | - if (ios == 0) then | |
| 86 | - read(unit, '(a)') path | |
| 87 | - close(unit) | |
| 88 | - else | |
| 89 | - path = "." | |
| 90 | - end if | |
| 91 | - call execute_command_line("rm -f pwd_temp.txt", wait=.false.) | |
| 92 | - end subroutine get_cwd | |
| 93 | - | |
| 94 | - subroutine get_parent(path, parent) | |
| 95 | - character(len=*), intent(in) :: path | |
| 96 | - character(len=*), intent(out) :: parent | |
| 97 | - integer :: last_slash | |
| 98 | - | |
| 99 | - last_slash = index(path, '/', back=.true.) | |
| 100 | - if (last_slash > 1) then | |
| 101 | - parent = path(1:last_slash-1) | |
| 102 | - else | |
| 103 | - parent = "/" | |
| 104 | - end if | |
| 105 | - end subroutine get_parent | |
| 106 | - | |
| 107 | - subroutine change_dir(current, new_name, parent) | |
| 108 | - character(len=*), intent(inout) :: current | |
| 109 | - character(len=*), intent(in) :: new_name | |
| 110 | - character(len=*), intent(inout) :: parent | |
| 111 | - | |
| 112 | - if (trim(new_name) == "..") then | |
| 113 | - if (trim(current) /= "/") then | |
| 114 | - parent = current | |
| 115 | - call get_parent(current, parent) | |
| 116 | - current = parent | |
| 117 | - call get_parent(current, parent) | |
| 118 | - end if | |
| 119 | - else | |
| 120 | - parent = current | |
| 121 | - if (trim(current) == "/") then | |
| 122 | - current = "/" // trim(new_name) | |
| 123 | - else | |
| 124 | - current = trim(current) // "/" // trim(new_name) | |
| 125 | - end if | |
| 126 | - end if | |
| 127 | - end subroutine change_dir | |
| 128 | - | |
| 129 | - subroutine list_dir(path, files, count) | |
| 130 | - character(len=*), intent(in) :: path | |
| 131 | - type(file_entry), dimension(MAX_FILES), intent(out) :: files | |
| 132 | - integer, intent(out) :: count | |
| 133 | - integer :: unit, ios | |
| 134 | - character(len=512) :: cmd | |
| 135 | - | |
| 136 | - ! Initialize | |
| 137 | - files%name = "" | |
| 138 | - files%is_dir = .false. | |
| 139 | - | |
| 140 | - ! List files | |
| 141 | - write(cmd, '(a)') "ls -1a " // trim(path) // " 2>/dev/null > ls_temp.txt" | |
| 142 | - call execute_command_line(trim(cmd), wait=.true.) | |
| 143 | - | |
| 144 | - open(newunit=unit, file="ls_temp.txt", status='old', iostat=ios) | |
| 145 | - if (ios /= 0) then | |
| 146 | - count = 0 | |
| 147 | - return | |
| 148 | - end if | |
| 149 | - | |
| 150 | - count = 0 | |
| 151 | - do | |
| 152 | - count = count + 1 | |
| 153 | - if (count > MAX_FILES) exit | |
| 154 | - read(unit, '(a)', iostat=ios) files(count)%name | |
| 155 | - if (ios /= 0) then | |
| 156 | - count = count - 1 | |
| 157 | - exit | |
| 158 | - end if | |
| 159 | - ! Check if directory | |
| 160 | - call is_directory(path, files(count)%name, files(count)%is_dir) | |
| 161 | - end do | |
| 162 | - | |
| 163 | - close(unit) | |
| 164 | - call execute_command_line("rm -f ls_temp.txt", wait=.false.) | |
| 165 | - end subroutine list_dir | |
| 166 | - | |
| 167 | - subroutine is_directory(base_path, name, is_dir) | |
| 168 | - character(len=*), intent(in) :: base_path, name | |
| 169 | - logical, intent(out) :: is_dir | |
| 170 | - character(len=512) :: full_path | |
| 171 | - integer :: stat | |
| 172 | - | |
| 173 | - if (trim(base_path) == "/") then | |
| 174 | - full_path = "/" // trim(name) | |
| 175 | - else | |
| 176 | - full_path = trim(base_path) // "/" // trim(name) | |
| 177 | - end if | |
| 178 | - | |
| 179 | - call execute_command_line("test -d '" // trim(full_path) // "'", & | |
| 180 | - exitstat=stat, wait=.true.) | |
| 181 | - is_dir = (stat == 0) | |
| 182 | - end subroutine is_directory | |
| 183 | - | |
| 184 | - subroutine get_terminal_size(rows, cols) | |
| 185 | - integer, intent(out) :: rows, cols | |
| 186 | - integer :: unit, ios | |
| 187 | - | |
| 188 | - call execute_command_line("tput lines > size_temp.txt", wait=.true.) | |
| 189 | - open(newunit=unit, file="size_temp.txt", status='old', iostat=ios) | |
| 190 | - if (ios == 0) then | |
| 191 | - read(unit, *) rows | |
| 192 | - close(unit) | |
| 193 | - else | |
| 194 | - rows = 24 | |
| 195 | - end if | |
| 196 | - | |
| 197 | - call execute_command_line("tput cols > size_temp.txt", wait=.true.) | |
| 198 | - open(newunit=unit, file="size_temp.txt", status='old', iostat=ios) | |
| 199 | - if (ios == 0) then | |
| 200 | - read(unit, *) cols | |
| 201 | - close(unit) | |
| 202 | - else | |
| 203 | - cols = 80 | |
| 204 | - end if | |
| 205 | - | |
| 206 | - call execute_command_line("rm -f size_temp.txt", wait=.false.) | |
| 207 | - end subroutine get_terminal_size | |
| 208 | - | |
| 209 | - subroutine clear_screen() | |
| 210 | - write(output_unit, '(a)', advance='no') ESC // "[2J" // ESC // "[H" | |
| 211 | - end subroutine clear_screen | |
| 212 | - | |
| 213 | - subroutine draw_header(path) | |
| 214 | - character(len=*), intent(in) :: path | |
| 215 | - write(output_unit, '(a)') ESC // "[1m" // "FORTRESS v2" // ESC // "[0m - " // trim(path) | |
| 216 | - write(output_unit, '(a)') repeat("=", 70) | |
| 217 | - end subroutine draw_header | |
| 218 | - | |
| 219 | - subroutine draw_panes(p_files, p_count, c_files, c_count, sel, rows, cols) | |
| 220 | - type(file_entry), dimension(*), intent(in) :: p_files, c_files | |
| 221 | - integer, intent(in) :: p_count, c_count, sel, rows, cols | |
| 222 | - integer :: i | |
| 223 | - integer :: left_width, right_width | |
| 224 | - character(len=30) :: left_text | |
| 225 | - character(len=50) :: right_text | |
| 226 | - | |
| 227 | - left_width = cols * 3 / 10 | |
| 228 | - right_width = cols - left_width - 3 | |
| 229 | - | |
| 230 | - do i = 1, min(rows - 5, max(p_count, c_count)) | |
| 231 | - ! Left pane | |
| 232 | - if (i <= p_count) then | |
| 233 | - left_text = p_files(i)%name | |
| 234 | - if (p_files(i)%is_dir .and. trim(left_text) /= "." .and. trim(left_text) /= "..") then | |
| 235 | - left_text = trim(left_text) // "/" | |
| 236 | - end if | |
| 237 | - if (len_trim(left_text) > left_width) then | |
| 238 | - left_text = left_text(1:left_width-3) // "..." | |
| 239 | - end if | |
| 240 | - write(output_unit, '(a)', advance='no') ESC // "[2m" // left_text(1:left_width) // ESC // "[0m" | |
| 241 | - else | |
| 242 | - write(output_unit, '(a)', advance='no') repeat(" ", left_width) | |
| 243 | - end if | |
| 244 | - | |
| 245 | - ! Separator | |
| 246 | - write(output_unit, '(a)', advance='no') " | " | |
| 247 | - | |
| 248 | - ! Right pane | |
| 249 | - if (i <= c_count) then | |
| 250 | - right_text = c_files(i)%name | |
| 251 | - if (c_files(i)%is_dir .and. trim(right_text) /= "." .and. trim(right_text) /= "..") then | |
| 252 | - right_text = trim(right_text) // "/" | |
| 253 | - end if | |
| 254 | - | |
| 255 | - if (i == sel) then | |
| 256 | - write(output_unit, '(a)') ESC // "[7m" // trim(right_text) // ESC // "[0m" | |
| 257 | - else | |
| 258 | - write(output_unit, '(a)') trim(right_text) | |
| 259 | - end if | |
| 260 | - else | |
| 261 | - write(output_unit, *) | |
| 262 | - end if | |
| 263 | - end do | |
| 264 | - end subroutine draw_panes | |
| 265 | - | |
| 266 | - subroutine draw_footer() | |
| 267 | - write(output_unit, *) | |
| 268 | - write(output_unit, '(a)') ESC // "[2m" // "↑↓: navigate | →: enter | ←: back | q: quit" // ESC // "[0m" | |
| 269 | - end subroutine draw_footer | |
| 270 | - | |
| 271 | - subroutine get_key(key) | |
| 272 | - character(len=*), intent(out) :: key | |
| 273 | - character(len=1) :: ch | |
| 274 | - | |
| 275 | - key = "" | |
| 276 | - read(*, '(a1)', advance='no', iostat=i) ch | |
| 277 | - | |
| 278 | - if (ch == ESC) then | |
| 279 | - read(*, '(a1)', advance='no', iostat=i) ch | |
| 280 | - if (ch == '[') then | |
| 281 | - read(*, '(a1)', advance='no', iostat=i) ch | |
| 282 | - key = ch | |
| 283 | - end if | |
| 284 | - else | |
| 285 | - key = ch | |
| 286 | - end if | |
| 287 | - end subroutine get_key | |
| 288 | - | |
| 289 | -end program fortress_v2 | |
src/main.f90modified@@ -1,145 +1,278 @@ | ||
| 1 | -program fortress_main | |
| 1 | +program fortress_clean | |
| 2 | 2 | use iso_fortran_env, only: output_unit, error_unit |
| 3 | - use terminal_screen, only: init_screen, cleanup_screen, clear_screen | |
| 4 | - use terminal_input, only: get_key, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER, KEY_QUIT | |
| 5 | - use filesystem_ops, only: list_directory, get_parent_dir, get_current_dir, is_directory, & | |
| 6 | - file_entry, MAX_FILES | |
| 7 | - use ui_panes_buffered, only: draw_panes_buffered | |
| 8 | - | |
| 9 | 3 | implicit none |
| 10 | 4 | |
| 11 | - logical :: running | |
| 12 | - logical :: needs_full_redraw | |
| 13 | - integer :: key | |
| 14 | - character(len=256) :: current_dir | |
| 15 | - character(len=256) :: parent_dir | |
| 16 | - character(len=256) :: new_dir | |
| 17 | - integer :: selected_index | |
| 18 | - integer :: parent_selected_index | |
| 19 | - type(file_entry), dimension(MAX_FILES) :: current_files, parent_files | |
| 20 | - integer :: file_count, parent_file_count, i | |
| 21 | - character(len=256) :: base_name | |
| 5 | + ! Constants | |
| 6 | + integer, parameter :: MAX_PATH = 512 | |
| 7 | + integer, parameter :: MAX_FILES = 500 | |
| 8 | + character(len=*), parameter :: ESC = char(27) | |
| 9 | + character(len=*), parameter :: CLEAR = ESC // "[2J" // ESC // "[H" | |
| 10 | + character(len=*), parameter :: BOLD = ESC // "[1m" | |
| 11 | + character(len=*), parameter :: DIM = ESC // "[2m" | |
| 12 | + character(len=*), parameter :: REVERSE = ESC // "[7m" | |
| 13 | + character(len=*), parameter :: RESET = ESC // "[0m" | |
| 22 | 14 | |
| 23 | - ! Initialize | |
| 24 | - running = .true. | |
| 25 | - needs_full_redraw = .true. | |
| 26 | - selected_index = 1 | |
| 27 | - parent_selected_index = 1 | |
| 28 | - current_dir = get_current_dir() | |
| 29 | - parent_dir = get_parent_dir(current_dir) | |
| 15 | + ! Variables | |
| 16 | + character(len=MAX_PATH) :: current_dir, parent_dir, temp_dir | |
| 17 | + character(len=MAX_PATH), dimension(MAX_FILES) :: current_files, parent_files | |
| 18 | + logical, dimension(MAX_FILES) :: current_is_dir, parent_is_dir | |
| 19 | + integer :: current_count, parent_count | |
| 20 | + integer :: selected = 1 | |
| 21 | + integer :: parent_selected = -1 | |
| 22 | + character(len=1) :: key | |
| 23 | + logical :: running = .true. | |
| 24 | + integer :: i, rows, cols | |
| 30 | 25 | |
| 31 | - ! Set up terminal | |
| 32 | - call init_screen() | |
| 26 | + ! Initialize | |
| 27 | + current_dir = get_pwd() | |
| 28 | + parent_dir = get_parent_path(current_dir) | |
| 33 | 29 | |
| 34 | - ! Initial clear screen | |
| 35 | - call clear_screen() | |
| 30 | + ! Setup terminal | |
| 31 | + call execute_command_line("stty -icanon -echo min 1 time 0 2>/dev/null") | |
| 36 | 32 | |
| 37 | 33 | ! Main loop |
| 38 | 34 | do while (running) |
| 39 | - ! Get current directory contents | |
| 40 | - current_files = list_directory(current_dir) | |
| 41 | - parent_files = list_directory(parent_dir) | |
| 42 | - | |
| 43 | - ! Count actual files | |
| 44 | - file_count = 0 | |
| 45 | - do i = 1, MAX_FILES | |
| 46 | - if (len_trim(current_files(i)%name) == 0) exit | |
| 47 | - file_count = i | |
| 48 | - end do | |
| 35 | + ! Get files | |
| 36 | + call get_file_list(current_dir, current_files, current_is_dir, current_count) | |
| 37 | + call get_file_list(parent_dir, parent_files, parent_is_dir, parent_count) | |
| 38 | + | |
| 39 | + ! Find current dir in parent | |
| 40 | + parent_selected = find_in_parent(current_dir, parent_files, parent_count) | |
| 41 | + | |
| 42 | + ! Get terminal size | |
| 43 | + call get_term_size(rows, cols) | |
| 44 | + | |
| 45 | + ! Draw interface | |
| 46 | + write(output_unit, '(a)', advance='no') CLEAR | |
| 47 | + call draw_interface(rows, cols) | |
| 48 | + | |
| 49 | + ! Get input | |
| 50 | + read(*, '(a1)', advance='no') key | |
| 51 | + | |
| 52 | + ! Handle input | |
| 53 | + select case(ichar(key)) | |
| 54 | + case(27) ! ESC sequence | |
| 55 | + call read_arrow_key(key) | |
| 56 | + select case(key) | |
| 57 | + case('A') ! Up | |
| 58 | + if (selected > 1) selected = selected - 1 | |
| 59 | + case('B') ! Down | |
| 60 | + if (selected < current_count) selected = selected + 1 | |
| 61 | + case('C') ! Right - enter | |
| 62 | + if (current_is_dir(selected)) then | |
| 63 | + if (trim(current_files(selected)) == "..") then | |
| 64 | + temp_dir = current_dir | |
| 65 | + current_dir = parent_dir | |
| 66 | + parent_dir = get_parent_path(current_dir) | |
| 67 | + selected = max(1, find_in_parent(temp_dir, current_files, MAX_FILES)) | |
| 68 | + else if (trim(current_files(selected)) /= ".") then | |
| 69 | + parent_dir = current_dir | |
| 70 | + current_dir = join_path(current_dir, current_files(selected)) | |
| 71 | + selected = 1 | |
| 72 | + end if | |
| 73 | + end if | |
| 74 | + case('D') ! Left - back | |
| 75 | + if (current_dir /= "/") then | |
| 76 | + temp_dir = current_dir | |
| 77 | + current_dir = parent_dir | |
| 78 | + parent_dir = get_parent_path(current_dir) | |
| 79 | + selected = max(1, find_in_parent(temp_dir, current_files, MAX_FILES)) | |
| 80 | + end if | |
| 81 | + end select | |
| 82 | + case(113, 81) ! 'q' or 'Q' | |
| 83 | + running = .false. | |
| 84 | + end select | |
| 85 | + end do | |
| 86 | + | |
| 87 | + ! Cleanup | |
| 88 | + call execute_command_line("stty icanon echo 2>/dev/null") | |
| 89 | + write(output_unit, '(a)', advance='no') CLEAR | |
| 90 | + write(output_unit, '(a)') "Thanks for using FORTRESS!" | |
| 91 | + | |
| 92 | +contains | |
| 93 | + | |
| 94 | + function get_pwd() result(path) | |
| 95 | + character(len=MAX_PATH) :: path | |
| 96 | + integer :: unit, ios | |
| 97 | + | |
| 98 | + call execute_command_line("pwd > .fortress_pwd 2>/dev/null", wait=.true.) | |
| 99 | + open(newunit=unit, file=".fortress_pwd", status='old', iostat=ios) | |
| 100 | + if (ios == 0) then | |
| 101 | + read(unit, '(a)') path | |
| 102 | + close(unit) | |
| 103 | + else | |
| 104 | + path = "." | |
| 105 | + end if | |
| 106 | + call execute_command_line("rm -f .fortress_pwd 2>/dev/null") | |
| 107 | + end function get_pwd | |
| 108 | + | |
| 109 | + function get_parent_path(path) result(parent) | |
| 110 | + character(len=*), intent(in) :: path | |
| 111 | + character(len=MAX_PATH) :: parent | |
| 112 | + integer :: pos | |
| 113 | + | |
| 114 | + pos = index(path, "/", back=.true.) | |
| 115 | + if (pos > 1) then | |
| 116 | + parent = path(1:pos-1) | |
| 117 | + else if (pos == 1) then | |
| 118 | + parent = "/" | |
| 119 | + else | |
| 120 | + parent = "." | |
| 121 | + end if | |
| 122 | + end function get_parent_path | |
| 123 | + | |
| 124 | + function join_path(base, name) result(full) | |
| 125 | + character(len=*), intent(in) :: base, name | |
| 126 | + character(len=MAX_PATH) :: full | |
| 127 | + | |
| 128 | + if (base == "/") then | |
| 129 | + full = "/" // trim(name) | |
| 130 | + else | |
| 131 | + full = trim(base) // "/" // trim(name) | |
| 132 | + end if | |
| 133 | + end function join_path | |
| 134 | + | |
| 135 | + function find_in_parent(dir, files, count) result(idx) | |
| 136 | + character(len=*), intent(in) :: dir | |
| 137 | + character(len=*), dimension(*), intent(in) :: files | |
| 138 | + integer, intent(in) :: count | |
| 139 | + integer :: idx, pos | |
| 140 | + character(len=256) :: basename | |
| 49 | 141 | |
| 50 | - parent_file_count = 0 | |
| 51 | - do i = 1, MAX_FILES | |
| 52 | - if (len_trim(parent_files(i)%name) == 0) exit | |
| 53 | - parent_file_count = i | |
| 142 | + pos = index(dir, "/", back=.true.) | |
| 143 | + if (pos > 0) then | |
| 144 | + basename = dir(pos+1:) | |
| 145 | + else | |
| 146 | + basename = dir | |
| 147 | + end if | |
| 148 | + | |
| 149 | + do idx = 1, count | |
| 150 | + if (trim(files(idx)) == trim(basename)) return | |
| 54 | 151 | end do |
| 152 | + idx = 1 | |
| 153 | + end function find_in_parent | |
| 154 | + | |
| 155 | + subroutine get_file_list(dir, files, is_dir, count) | |
| 156 | + character(len=*), intent(in) :: dir | |
| 157 | + character(len=*), dimension(*), intent(out) :: files | |
| 158 | + logical, dimension(*), intent(out) :: is_dir | |
| 159 | + integer, intent(out) :: count | |
| 160 | + integer :: unit, ios, stat | |
| 161 | + character(len=MAX_PATH) :: fullpath | |
| 55 | 162 | |
| 56 | - ! Find current directory in parent listing for highlighting | |
| 57 | - call get_basename(current_dir, base_name) | |
| 58 | - parent_selected_index = 1 | |
| 59 | - do i = 1, parent_file_count | |
| 60 | - if (trim(parent_files(i)%name) == trim(base_name)) then | |
| 61 | - parent_selected_index = i | |
| 163 | + call execute_command_line("ls -1a '" // trim(dir) // "' > .fortress_ls 2>/dev/null", wait=.true.) | |
| 164 | + | |
| 165 | + open(newunit=unit, file=".fortress_ls", status='old', iostat=ios) | |
| 166 | + if (ios /= 0) then | |
| 167 | + count = 0 | |
| 168 | + return | |
| 169 | + end if | |
| 170 | + | |
| 171 | + count = 0 | |
| 172 | + do | |
| 173 | + count = count + 1 | |
| 174 | + if (count > MAX_FILES) exit | |
| 175 | + read(unit, '(a)', iostat=ios) files(count) | |
| 176 | + if (ios /= 0) then | |
| 177 | + count = count - 1 | |
| 62 | 178 | exit |
| 63 | 179 | end if |
| 180 | + | |
| 181 | + fullpath = join_path(dir, files(count)) | |
| 182 | + call execute_command_line("test -d '" // trim(fullpath) // "'", exitstat=stat, wait=.true.) | |
| 183 | + is_dir(count) = (stat == 0) | |
| 64 | 184 | end do |
| 65 | 185 | |
| 66 | - ! Only clear screen if needed (reduces flashing) | |
| 67 | - if (needs_full_redraw) then | |
| 68 | - call clear_screen() | |
| 69 | - needs_full_redraw = .false. | |
| 186 | + close(unit) | |
| 187 | + call execute_command_line("rm -f .fortress_ls 2>/dev/null") | |
| 188 | + end subroutine get_file_list | |
| 189 | + | |
| 190 | + subroutine get_term_size(r, c) | |
| 191 | + integer, intent(out) :: r, c | |
| 192 | + integer :: unit, ios | |
| 193 | + | |
| 194 | + call execute_command_line("tput lines > .fortress_size 2>/dev/null", wait=.true.) | |
| 195 | + open(newunit=unit, file=".fortress_size", status='old', iostat=ios) | |
| 196 | + if (ios == 0) then | |
| 197 | + read(unit, *) r | |
| 198 | + close(unit) | |
| 199 | + else | |
| 200 | + r = 24 | |
| 70 | 201 | end if |
| 71 | 202 | |
| 72 | - call draw_panes_buffered(parent_dir, current_dir, selected_index, parent_selected_index) | |
| 203 | + call execute_command_line("tput cols > .fortress_size 2>/dev/null", wait=.true.) | |
| 204 | + open(newunit=unit, file=".fortress_size", status='old', iostat=ios) | |
| 205 | + if (ios == 0) then | |
| 206 | + read(unit, *) c | |
| 207 | + close(unit) | |
| 208 | + else | |
| 209 | + c = 80 | |
| 210 | + end if | |
| 73 | 211 | |
| 74 | - key = get_key() | |
| 212 | + call execute_command_line("rm -f .fortress_size 2>/dev/null") | |
| 213 | + end subroutine get_term_size | |
| 75 | 214 | |
| 76 | - select case(key) | |
| 77 | - case(KEY_UP) | |
| 78 | - if (selected_index > 1) then | |
| 79 | - selected_index = selected_index - 1 | |
| 80 | - end if | |
| 81 | - case(KEY_DOWN) | |
| 82 | - if (selected_index < file_count) then | |
| 83 | - selected_index = selected_index + 1 | |
| 84 | - end if | |
| 85 | - case(KEY_LEFT) | |
| 86 | - ! Go to parent directory | |
| 87 | - if (trim(current_dir) /= "/") then | |
| 88 | - current_dir = parent_dir | |
| 89 | - parent_dir = get_parent_dir(current_dir) | |
| 90 | - selected_index = parent_selected_index | |
| 91 | - needs_full_redraw = .true. | |
| 92 | - end if | |
| 93 | - case(KEY_RIGHT, KEY_ENTER) | |
| 94 | - ! Enter directory or open file | |
| 95 | - if (selected_index <= file_count) then | |
| 96 | - if (current_files(selected_index)%is_dir) then | |
| 97 | - ! Navigate into directory | |
| 98 | - if (trim(current_files(selected_index)%name) == "..") then | |
| 99 | - ! Same as pressing left arrow | |
| 100 | - if (trim(current_dir) /= "/") then | |
| 101 | - current_dir = parent_dir | |
| 102 | - parent_dir = get_parent_dir(current_dir) | |
| 103 | - selected_index = parent_selected_index | |
| 104 | - needs_full_redraw = .true. | |
| 105 | - end if | |
| 106 | - else if (trim(current_files(selected_index)%name) /= ".") then | |
| 107 | - ! Enter subdirectory | |
| 108 | - new_dir = trim(current_dir) // "/" // trim(current_files(selected_index)%name) | |
| 109 | - if (is_directory(new_dir)) then | |
| 110 | - parent_dir = current_dir | |
| 111 | - current_dir = new_dir | |
| 112 | - selected_index = 1 | |
| 113 | - needs_full_redraw = .true. | |
| 114 | - end if | |
| 115 | - end if | |
| 215 | + subroutine draw_interface(r, c) | |
| 216 | + integer, intent(in) :: r, c | |
| 217 | + integer :: left_w, i | |
| 218 | + character(len=256) :: fname | |
| 219 | + | |
| 220 | + left_w = c * 3 / 10 | |
| 221 | + | |
| 222 | + ! Header | |
| 223 | + write(output_unit, '(a)') BOLD // "FORTRESS" // RESET // " - " // trim(current_dir) | |
| 224 | + | |
| 225 | + ! Files | |
| 226 | + do i = 1, min(r-3, max(parent_count, current_count)) | |
| 227 | + ! Parent pane | |
| 228 | + if (i <= parent_count) then | |
| 229 | + fname = parent_files(i) | |
| 230 | + if (parent_is_dir(i) .and. fname /= "." .and. fname /= "..") then | |
| 231 | + fname = trim(fname) // "/" | |
| 232 | + end if | |
| 233 | + if (i == parent_selected) then | |
| 234 | + write(output_unit, '(a)', advance='no') DIM // BOLD // fname(1:min(len_trim(fname),left_w)) // RESET | |
| 116 | 235 | else |
| 117 | - ! Open file - TODO: implement file opening with $EDITOR | |
| 236 | + write(output_unit, '(a)', advance='no') DIM // fname(1:min(len_trim(fname),left_w)) // RESET | |
| 118 | 237 | end if |
| 238 | + write(output_unit, '(a)', advance='no') repeat(" ", max(0, left_w - len_trim(fname))) | |
| 239 | + else | |
| 240 | + write(output_unit, '(a)', advance='no') repeat(" ", left_w) | |
| 119 | 241 | end if |
| 120 | - case(KEY_QUIT) | |
| 121 | - running = .false. | |
| 122 | - end select | |
| 123 | - end do | |
| 124 | 242 | |
| 125 | - ! Cleanup | |
| 126 | - call cleanup_screen() | |
| 243 | + ! Separator | |
| 244 | + write(output_unit, '(a)', advance='no') " │ " | |
| 127 | 245 | |
| 128 | - write(output_unit, *) "Thanks for using FORTRESS!" | |
| 246 | + ! Current pane | |
| 247 | + if (i <= current_count) then | |
| 248 | + fname = current_files(i) | |
| 249 | + if (current_is_dir(i) .and. fname /= "." .and. fname /= "..") then | |
| 250 | + fname = trim(fname) // "/" | |
| 251 | + end if | |
| 252 | + if (i == selected) then | |
| 253 | + write(output_unit, '(a)') REVERSE // trim(fname) // RESET | |
| 254 | + else | |
| 255 | + write(output_unit, '(a)') trim(fname) | |
| 256 | + end if | |
| 257 | + else | |
| 258 | + write(output_unit, *) | |
| 259 | + end if | |
| 260 | + end do | |
| 129 | 261 | |
| 130 | -contains | |
| 262 | + ! Footer | |
| 263 | + write(output_unit, '(a,i0,a)') DIM // "↑↓:nav →:enter ←:back q:quit [", selected, "/" // trim(adjustl(char(current_count))) // "]" // RESET | |
| 264 | + end subroutine draw_interface | |
| 131 | 265 | |
| 132 | - subroutine get_basename(path, basename) | |
| 133 | - character(len=*), intent(in) :: path | |
| 134 | - character(len=*), intent(out) :: basename | |
| 135 | - integer :: last_slash | |
| 266 | + subroutine read_arrow_key(k) | |
| 267 | + character(len=1), intent(out) :: k | |
| 268 | + character(len=1) :: ch | |
| 136 | 269 | |
| 137 | - last_slash = index(path, '/', back=.true.) | |
| 138 | - if (last_slash > 0 .and. last_slash < len_trim(path)) then | |
| 139 | - basename = path(last_slash+1:) | |
| 270 | + read(*, '(a1)', advance='no') ch | |
| 271 | + if (ch == '[') then | |
| 272 | + read(*, '(a1)', advance='no') k | |
| 140 | 273 | else |
| 141 | - basename = path | |
| 274 | + k = ch | |
| 142 | 275 | end if |
| 143 | - end subroutine get_basename | |
| 276 | + end subroutine read_arrow_key | |
| 144 | 277 | |
| 145 | -end program fortress_main | |
| 278 | +end program fortress_clean | |
src/simple_main.f90deleted@@ -1,119 +0,0 @@ | ||
| 1 | -program simple_fortress | |
| 2 | - use iso_fortran_env, only: output_unit, input_unit | |
| 3 | - implicit none | |
| 4 | - | |
| 5 | - character(len=256) :: current_path | |
| 6 | - character(len=256) :: parent_path | |
| 7 | - character(len=256), dimension(100) :: files | |
| 8 | - character(len=256), dimension(100) :: parent_files | |
| 9 | - integer :: num_files, num_parent_files | |
| 10 | - integer :: selected = 1 | |
| 11 | - integer :: i | |
| 12 | - character(len=1) :: key | |
| 13 | - logical :: running = .true. | |
| 14 | - | |
| 15 | - ! Start in current directory | |
| 16 | - current_path = "." | |
| 17 | - parent_path = ".." | |
| 18 | - | |
| 19 | - ! Main loop | |
| 20 | - do while (running) | |
| 21 | - ! Get file lists | |
| 22 | - call get_files(current_path, files, num_files) | |
| 23 | - call get_files(parent_path, parent_files, num_parent_files) | |
| 24 | - | |
| 25 | - ! Clear screen (simple way) | |
| 26 | - write(output_unit, '(a)') char(27) // "[2J" // char(27) // "[H" | |
| 27 | - | |
| 28 | - ! Draw header | |
| 29 | - write(output_unit, '(a)') "FORTRESS - Simple File Browser" | |
| 30 | - write(output_unit, '(a)') "==============================" | |
| 31 | - write(output_unit, *) | |
| 32 | - | |
| 33 | - ! Draw files in two columns | |
| 34 | - write(output_unit, '(a)') "Parent Directory | Current Directory" | |
| 35 | - write(output_unit, '(a)') "------------------------- | -------------------------" | |
| 36 | - | |
| 37 | - do i = 1, max(num_parent_files, num_files) | |
| 38 | - if (i <= num_parent_files) then | |
| 39 | - write(output_unit, '(a25)', advance='no') adjustl(parent_files(i)) | |
| 40 | - else | |
| 41 | - write(output_unit, '(a25)', advance='no') " " | |
| 42 | - end if | |
| 43 | - | |
| 44 | - write(output_unit, '(a)', advance='no') " | " | |
| 45 | - | |
| 46 | - if (i <= num_files) then | |
| 47 | - if (i == selected) then | |
| 48 | - write(output_unit, '(a)') "> " // trim(files(i)) | |
| 49 | - else | |
| 50 | - write(output_unit, '(a)') " " // trim(files(i)) | |
| 51 | - end if | |
| 52 | - else | |
| 53 | - write(output_unit, *) | |
| 54 | - end if | |
| 55 | - end do | |
| 56 | - | |
| 57 | - ! Show controls | |
| 58 | - write(output_unit, *) | |
| 59 | - write(output_unit, '(a)') "Controls: j=down, k=up, q=quit" | |
| 60 | - write(output_unit, '(a)', advance='no') "Command: " | |
| 61 | - | |
| 62 | - ! Get input | |
| 63 | - read(input_unit, '(a1)') key | |
| 64 | - | |
| 65 | - select case(key) | |
| 66 | - case('j', 'J') | |
| 67 | - if (selected < num_files) selected = selected + 1 | |
| 68 | - case('k', 'K') | |
| 69 | - if (selected > 1) selected = selected - 1 | |
| 70 | - case('q', 'Q') | |
| 71 | - running = .false. | |
| 72 | - end select | |
| 73 | - end do | |
| 74 | - | |
| 75 | - write(output_unit, '(a)') "Goodbye!" | |
| 76 | - | |
| 77 | -contains | |
| 78 | - | |
| 79 | - subroutine get_files(path, file_list, count) | |
| 80 | - character(len=*), intent(in) :: path | |
| 81 | - character(len=256), dimension(100), intent(out) :: file_list | |
| 82 | - integer, intent(out) :: count | |
| 83 | - | |
| 84 | - character(len=512) :: cmd | |
| 85 | - character(len=256) :: temp_file | |
| 86 | - integer :: unit, ios | |
| 87 | - | |
| 88 | - ! Create temp file name | |
| 89 | - temp_file = "temp_files.txt" | |
| 90 | - | |
| 91 | - ! List files to temp file | |
| 92 | - write(cmd, '(a)') "ls -1 " // trim(path) // " > " // trim(temp_file) // " 2>/dev/null" | |
| 93 | - call execute_command_line(cmd, wait=.true.) | |
| 94 | - | |
| 95 | - ! Read files | |
| 96 | - open(newunit=unit, file=temp_file, status='old', iostat=ios) | |
| 97 | - if (ios /= 0) then | |
| 98 | - count = 0 | |
| 99 | - return | |
| 100 | - end if | |
| 101 | - | |
| 102 | - count = 0 | |
| 103 | - do | |
| 104 | - count = count + 1 | |
| 105 | - if (count > 100) exit | |
| 106 | - read(unit, '(a)', iostat=ios) file_list(count) | |
| 107 | - if (ios /= 0) then | |
| 108 | - count = count - 1 | |
| 109 | - exit | |
| 110 | - end if | |
| 111 | - end do | |
| 112 | - | |
| 113 | - close(unit) | |
| 114 | - | |
| 115 | - ! Clean up | |
| 116 | - call execute_command_line("rm -f " // trim(temp_file), wait=.false.) | |
| 117 | - end subroutine get_files | |
| 118 | - | |
| 119 | -end program simple_fortress | |
src/test_right_pane.f90deleted@@ -1,31 +0,0 @@ | ||
| 1 | -program test_right_pane | |
| 2 | - use terminal_screen, only: init_screen, cleanup_screen, clear_screen | |
| 3 | - use ui_panes_buffered, only: draw_panes_buffered | |
| 4 | - | |
| 5 | - implicit none | |
| 6 | - character(len=256) :: current_dir, parent_dir | |
| 7 | - | |
| 8 | - ! Set test directories | |
| 9 | - current_dir = "." | |
| 10 | - parent_dir = ".." | |
| 11 | - | |
| 12 | - ! Initialize screen | |
| 13 | - call init_screen() | |
| 14 | - call clear_screen() | |
| 15 | - | |
| 16 | - ! Draw the panes with buffered rendering | |
| 17 | - write(*, '(a)') "Testing buffered rendering - both panes should show files:" | |
| 18 | - write(*, *) | |
| 19 | - | |
| 20 | - call draw_panes_buffered(parent_dir, current_dir, 2, 1) | |
| 21 | - | |
| 22 | - ! Wait for user input | |
| 23 | - write(*, *) | |
| 24 | - write(*, '(a)') "Press Enter to exit test..." | |
| 25 | - read(*, *) | |
| 26 | - | |
| 27 | - ! Cleanup | |
| 28 | - call cleanup_screen() | |
| 29 | - write(*, '(a)') "Test complete - if you saw files in both panes, buffered rendering works!" | |
| 30 | - | |
| 31 | -end program test_right_pane | |