commit e760413675670103c599e9b6ba31368fadacd2b6
Author: rani <clagv.randomgames@gmail.com>
Date: Wed Dec 31 16:16:57 2025 +0000
diff --git a/include/dir.h b/include/dir.h
index 10c6d38..9551cb0 100644
--- a/include/dir.h
+++ b/include/dir.h
@@ -216 +219 @@
#define M_OTHW S_IWOTH
#define M_OTHX S_IXOTH
+#define REGSEARCH_BAD_REGEX 1
+#define REGSEARCH_NOT_FOUND 2
+
enum de_type {
DE_FILE,
DE_DIR,
@@ -617 +649 @@ const char * dir_get_cwd(void);
int dir_cd_back(const char * cwd);
int dir_cd(const char * cwd, const char * next);
int dir_search_name(const dir_t * dir, const char * name, size_t * idx);
+int dir_search_regex(const dir_t * dir, const char * regexstr, size_t * idx);
const char * dir_basename(const char * path);
+
char dirent_crepr(const dirent_t * de); // character representing dir entry
char dirent_creprl(const dirent_t * de); // like above, but for the link
char dirent_longcrepr(const dirent_t * de); // like above, but for long mode
diff --git a/include/ui.h b/include/ui.h
index facf0a5..a2e07c7 100644
--- a/include/ui.h
+++ b/include/ui.h
@@ -76 +79 @@
#include "dir.h"
+#define KEY_DEL 127
+#define KEY_ESC 27
+
enum ui_color {
COLOR_FILE = 1,
COLOR_DIR,
@@ -345 +377 @@ void ui_erase(void);
void ui_refresh(void);
void ui_print_dir(const dir_t * dir, size_t cursor, bool longmode);
void ui_print_cursor(size_t cursor, size_t total);
+void ui_resize(void);
+const char * ui_readline(const char * prompt);
#endif /* UI_H */
diff --git a/src/dir.c b/src/dir.c
index 8a63343..a480701 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -46 +47 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <regex.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
@@ -2893 +29022 @@ int dir_search_name(const dir_t * dir, const char * name, size_t * idx) {
return -1;
}
+
+int dir_search_regex(const dir_t * dir, const char * regexstr, size_t * idx) {
+ regex_t regex;
+ int ret = regcomp(®ex, regexstr, REG_EXTENDED);
+ if (!!ret) return -REGSEARCH_BAD_REGEX;
+
+ for (size_t i = 0; i < dir->len; i++) {
+ dirent_t * de = &dir->entries[i];
+ ret = regexec(®ex, de->name, 0, NULL, 0);
+ if (!ret) {
+ *idx = i;
+ regfree(®ex);
+ return 0;
+ }
+ }
+
+ regfree(®ex);
+ return -REGSEARCH_NOT_FOUND;
+}
diff --git a/src/main.c b/src/main.c
index 017c67d..58a169a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -627 +628 @@ int main(int argc, char ** argv) {
}
free(basename);
break;
- } case KEY_RIGHT:
+ }
+ case KEY_RIGHT:
if (cur_de && (cur_de->type == DE_DIR || (cur_de->type == DE_LINK
&& cur_de->linktype == DE_DIR))) {
int ret = dir_cd(cwd, cur_de->name);
@@ -898 +9032 @@ int main(int argc, char ** argv) {
cursor = dir.len - 1;
ui_status_info("");
break;
+ case '/': {
+ const char * input = ui_readline("/");
+ if (!input) break;
+ size_t idx;
+ int i = dir_search_regex(&dir, input, &idx);
+ if (i >= 0) {
+ cursor = idx;
+ ui_status_info("");
+ } else switch (-i) {
+ case REGSEARCH_BAD_REGEX:
+ ui_status_error("Bad RegEx");
+ break;
+ case REGSEARCH_NOT_FOUND:
+ ui_status_info("No Matches Found");
+ break;
+ default:
+ ui_status_error("Unhandled Case");
+ break;
+ }
+ break;
+ }
case 'q':
goto finished;
+ case KEY_RESIZE:
+ ui_resize();
+ break;
default: break;
}
}
diff --git a/src/ui.c b/src/ui.c
index ef060a5..1042da9 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -317 +338 @@
#include <stddef.h>
#include <string.h>
#include <locale.h>
+#include <ctype.h>
#include <time.h>
#include "ui.h"
#include "dir.h"
-static WINDOW * titlewin = NULL;
+#define TITLEWINSTARTY 0
+#define TITLEWINLINES 1
+#define TITLEWINCOLS COLS
+
+#define STATUSWINSTARTY 1
+#define STATUSWINLINES 1
+#define STATUSWINCOLS COLS
+
+#define FILEWINSTARTY 2
+#define FILEWINLINES (LINES - 3)
+#define FILEWINCOLS COLS
+
+#define INPUTWINSTARTY (LINES - 1)
+#define INPUTWINLINES 1
+#define INPUTWINCOLS COLS
+
+#define INPUTBUFSZ 2048
+
+static WINDOW * titlewin = NULL;
static WINDOW * statuswin = NULL;
-static WINDOW * filewin = NULL;
+static WINDOW * filewin = NULL;
+static WINDOW * inputwin = NULL;
static void win_set(WINDOW * win, const char * str, int attrs);
static int ui_dirent_color(const dirent_t * de);
+static int ui_link_color(const dirent_t * de);
static void ui_print_dirent(const dirent_t * de, size_t pos, bool selected, bool longmode, const dir_t * dir);
static void ui_wlpadstr(WINDOW * win, const char * s, size_t len);
static void ui_get_first_last(size_t n_dirents, size_t cursor, size_t * first, size_t * last);
@@ -269 +4710 @@ void ui_init(void) {
curs_set(0);
noecho();
- titlewin = newwin(1, COLS, 0, 0);
- statuswin = newwin(1, COLS, 1, 0);
- filewin = newwin(LINES - 2, COLS, 2, 0);
+ titlewin = newwin(TITLEWINLINES, TITLEWINCOLS, TITLEWINSTARTY, 0);
+ statuswin = newwin(STATUSWINLINES, STATUSWINCOLS, STATUSWINSTARTY, 0);
+ filewin = newwin(FILEWINLINES, FILEWINCOLS, FILEWINSTARTY, 0);
+ inputwin = newwin(INPUTWINLINES, INPUTWINCOLS, INPUTWINSTARTY, 0);
clear();
refresh();
@@ -7219 +9419 @@ void ui_status_info(const char * status) {
}
void ui_status_error(const char * status) {
- wattron(statuswin, COLOR_PAIR(RED));
- win_set(statuswin, status, 0);
- wattroff(statuswin, COLOR_PAIR(RED));
+ win_set(statuswin, status, COLOR_PAIR(RED));
}
void ui_erase(void) {
werase(filewin);
+ werase(inputwin);
}
void ui_refresh(void) {
wnoutrefresh(titlewin);
wnoutrefresh(statuswin);
wnoutrefresh(filewin);
+ wnoutrefresh(inputwin);
doupdate();
}
@@ -1446 +16617 @@ void ui_print_dirent(const dirent_t * de, size_t pos, bool selected, bool longmo
wattroff(filewin, color);
char c = dirent_crepr(de);
if (c) waddch(filewin, c);
+
+ if (de->type == DE_LINK) {
+ waddstr(filewin, " -> ");
+ color = COLOR_PAIR(ui_link_color(de));
+ if (selected) color |= A_REVERSE;
+ wattron(filewin, color);
+ waddstr(filewin, de->linkname);
+ wattroff(filewin, color);
+ char c = dirent_creprl(de);
+ if (c) waddch(filewin, c);
+ }
}
static int ui_dirent_color(const dirent_t * de) {
@@ -1676 +20020 @@ static int ui_dirent_color(const dirent_t * de) {
return color;
}
+static int ui_link_color(const dirent_t * de) {
+ switch (de->linktype) {
+ case DE_FILE: return COLOR_FILE;
+ case DE_DIR: return COLOR_DIR;
+ case DE_FIFO: return COLOR_FIFO;
+ case DE_LINK: return COLOR_LINK;
+ case DE_BLOCK: return COLOR_BLOCK;
+ case DE_CHAR: return COLOR_CHAR;
+ case DE_SOCKET: return COLOR_SOCKET;
+ case DE_UNKNOWN: return COLOR_UNKNOWN;
+ default: return WHITE;
+ }
+}
+
void ui_print_dir(const dir_t * dir, size_t cursor, bool longmode) {
size_t first;
size_t last;
@@ -20015 +24775 @@ static void ui_get_first_last(size_t dir_len, size_t cursor, size_t * first, siz
*first = 0;
*last = dir_len;
} else {
- size_t off = lines / 2;
- if (cursor < off) {
+ size_t off_lo = lines / 2;
+ size_t off_hi = lines - off_lo;
+ if (cursor < off_lo) {
*first = 0;
if (dir_len > lines) *last = lines;
else *last = dir_len;
} else {
- *first = cursor - off;
- if (dir_len > cursor + off) *last = cursor + off;
+ *first = cursor - off_lo;
+ if (dir_len > cursor + off_hi) *last = cursor + off_hi;
else *last = dir_len;
}
}
}
+
+void ui_resize(void) {
+ // unless a WINCH handler is specified, ncurses resizes the terminal
+ // automatically, so this function just resizes the windows
+ wresize(titlewin, TITLEWINLINES, TITLEWINCOLS);
+ wresize(statuswin, STATUSWINLINES, STATUSWINCOLS);
+ wresize(filewin, FILEWINLINES, FILEWINCOLS);
+ wresize(inputwin, INPUTWINLINES, INPUTWINCOLS);
+
+ mvwin(titlewin, TITLEWINSTARTY, 0);
+ mvwin(statuswin, STATUSWINSTARTY, 0);
+ mvwin(filewin, FILEWINSTARTY, 0);
+ mvwin(inputwin, INPUTWINSTARTY, 0);
+
+ ui_refresh();
+}
+
+const char * ui_readline(const char * prompt) {
+ static char inputbuf[INPUTBUFSZ];
+
+ char * p = inputbuf;
+ *p = 0;
+
+ werase(inputwin);
+ waddstr(inputwin, prompt);
+ wattron(inputwin, A_REVERSE);
+ waddch(inputwin, ' ');
+ wattroff(inputwin, A_REVERSE);
+ wrefresh(inputwin);
+
+ int c;
+ while ((c = wgetch(inputwin)) != '\n') {
+ if (c == KEY_ESC) {
+ curs_set(0);
+ return NULL;
+ }
+
+ if (c == KEY_DEL || c == KEY_BACKSPACE) {
+ if (p != inputbuf) *--p = 0;
+ else return NULL;
+ } else if (isprint(c)) {
+ if (p - inputbuf < INPUTBUFSZ - 1) {
+ *p++ = (char)c;
+ *p = 0;
+ }
+ }
+
+ werase(inputwin);
+ waddstr(inputwin, prompt);
+ waddstr(inputwin, inputbuf);
+ wattron(inputwin, A_REVERSE);
+ waddch(inputwin, ' ');
+ wattroff(inputwin, A_REVERSE);
+ wrefresh(inputwin);
+ }
+
+ if (p == inputbuf) return NULL;
+ return inputbuf;
+}