summaryrefslogtreecommitdiff
path: root/src/user/fileman
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/fileman')
-rw-r--r--src/user/fileman/fileman.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/user/fileman/fileman.c b/src/user/fileman/fileman.c
new file mode 100644
index 0000000..0b28d1d
--- /dev/null
+++ b/src/user/fileman/fileman.c
@@ -0,0 +1,130 @@
+#include <pland/syscall.h>
+#include <knob/block.h>
+#include <knob/file.h>
+#include <knob/heap.h>
+#include <knob/task.h>
+
+char path_sz[1024] = "";
+uint32_t path_len = 0;
+
+_dir_info_entry_t *dir_info;
+uint32_t dir_info_len;
+
+uint32_t scroll;
+uint32_t selected;
+#define MAX_PER_SCREEN 18
+
+void paint_screen() {
+ _clear_screen();
+
+ _set_color(0x70);
+ _print_at(0, 0, path_sz);
+ _log_string("/");
+ _set_color(0x07);
+
+ for (uint32_t i = scroll, row = 2; (i < dir_info_len) && (row < MAX_PER_SCREEN + 2); ++i, ++row) {
+ if (i == selected)
+ _set_color(0x17);
+ _print_at(row, 0, dir_info[i].name);
+ if (dir_info[i].is_dir)
+ _log_string("/");
+ if (i == selected)
+ _set_color(0x07);
+ }
+
+ _print_at(21, 0, "keybindings:\n"
+ "UP, DOWN, PAGE UP, PAGE DOWN, HOME, END: move selection\n"
+ "ENTER: enter selected directory, run selected program\n"
+ "ESC: go up a directory Q: quit");
+}
+
+void load_dir() {
+ free_block(dir_info);
+ dir_info = get_directory_info(path_sz, &dir_info_len);
+ scroll = 0;
+ selected = 0;
+}
+
+void main(const char *sz) {
+ path_len = strcpy(path_sz, sz);
+ dir_info = get_directory_info(sz, &dir_info_len);
+
+ paint_screen();
+
+ while (true) {
+ _key_code_t key;
+ switch (key = _get_key()) {
+ case 0:
+ _yield_task();
+ continue;
+ case '\n':
+ {
+ uint32_t old_len = path_len;
+ if (path_len)
+ path_sz[path_len++] = '/';
+ path_len += strcpy(path_sz + path_len, dir_info[selected].name);
+ if (dir_info[selected].is_dir)
+ load_dir();
+ else {
+ try_run_command_blocking(path_sz);
+ //TODO: handle error
+ path_sz[old_len] = '\0';
+ path_len = old_len;
+ }
+ }
+ break;
+ case _KEY_ESC:
+ {
+ char *cutoff = path_sz;
+ for (char *i = path_sz + path_len - 1; i >= path_sz; --i)
+ if (*i == '/') {
+ cutoff = i;
+ break;
+ }
+ *cutoff = '\0';
+ path_len = cutoff - path_sz;
+ load_dir();
+ }
+ break;
+ case _KEY_HOME:
+ scroll = 0;
+ selected = 0;
+ break;
+ case _KEY_END:
+ selected = dir_info_len - 1;
+ scroll = dir_info_len >= MAX_PER_SCREEN
+ ? dir_info_len - MAX_PER_SCREEN : 0;
+ break;
+ case _KEY_UP:
+ if (!selected)
+ continue;
+ if (--selected < scroll)
+ scroll = selected;
+ break;
+ case _KEY_DOWN:
+ if (selected == dir_info_len - 1)
+ continue;
+ if (++selected >= scroll + MAX_PER_SCREEN)
+ ++scroll;
+ break;
+ case _KEY_PUP:
+ selected = selected >= MAX_PER_SCREEN
+ ? selected - MAX_PER_SCREEN : 0;
+ scroll = scroll >= MAX_PER_SCREEN
+ ? scroll - MAX_PER_SCREEN : 0;
+ break;
+ case _KEY_PDOWN:
+ if ((selected += MAX_PER_SCREEN) >= dir_info_len)
+ selected = dir_info_len - 1;
+ if ((scroll += MAX_PER_SCREEN) > selected)
+ scroll = selected;
+ break;
+ case 'q':
+ _clear_screen();
+ return;
+ default:
+ continue;
+ }
+ paint_screen();
+ }
+} \ No newline at end of file