commit cce43ff18656b13c9b07bc797a790dccfa704639
Author: Raniconduh <clagv.randomgames@gmail.com>
Date: Thu Sep 30 21:55:05 2021 +0000
diff --git a/include/dir.h b/include/dir.h
new file mode 100644
index 0000000..878913c
--- /dev/null
+++ b/include/dir.h
@@ -00 +134 @@
+#ifndef DIR_H
+#define DIR_H
+#endif
+
+int list_dir(char *);
+void free_dir_entries(void);
+void cd_back(void);
+void enter_dir(char *);
+
+
+enum file_type_t {
+ FILE_REG,
+ FILE_DIR,
+ FILE_FIFO,
+ FILE_LINK,
+ FILE_BLK,
+ FILE_UNKNOWN
+};
+
+struct dir_entry_t {
+ char * name;
+ enum file_type_t file_type;
+} dir_entry_t;
+
+
+// number of directory entries
+extern size_t n_dir_entries;
+// actual directory entries
+extern struct dir_entry_t ** dir_entries;
+
+// current working directory
+extern char * cwd;
+
+
diff --git a/include/io.h b/include/io.h
new file mode 100644
index 0000000..685e75b
--- /dev/null
+++ b/include/io.h
@@ -00 +131 @@
+#ifndef IO_H
+#define IO_H
+#endif
+
+#include <stdbool.h>
+
+enum colors {
+ BLUE,
+ HBLUE,
+ CYAN,
+ HCYAN,
+ GREEN,
+ HGREEN,
+ MAGENTA,
+ HMAGENTA,
+ YELLOW,
+ HYELLOW,
+ RED,
+ HRED,
+ WHITE,
+ HWHITE,
+};
+
+enum keys {
+ ARROW_UP = 0,
+ ARROW_DOWN = 1,
+};
+
+void curses_init(void);
+void curses_write_file(struct dir_entry_t *, bool);
+char curses_getch(void);
diff --git a/src/dir.c b/src/dir.c
new file mode 100644
index 0000000..e4c0102
--- /dev/null
+++ b/src/dir.c
@@ -00 +168 @@
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#include "dir.h"
+
+char * cwd = NULL;
+
+size_t n_dir_entries = 0;
+struct dir_entry_t ** dir_entries = NULL;
+
+int list_dir(char * dir_path) {
+ struct dirent * d_entry;
+ DIR * dir = opendir(dir_path);
+
+ n_dir_entries = 0;
+
+ if (!dir)
+ return 1;
+
+ while ((d_entry = readdir(dir))) {
+ struct dir_entry_t * dir_entry = malloc(sizeof(struct dir_entry_t) + 12);
+
+ char * d_name = d_entry->d_name;
+ size_t d_name_len = strlen(d_name);
+
+ if (!strcmp(d_name, ".") || !strcmp(d_name, "..")) continue;
+
+ struct stat * buf = malloc(sizeof(struct stat));
+ char * tmp_path = malloc(d_name_len + strlen(dir_path) + 2);
+ sprintf(tmp_path, "%s/%s", dir_path, d_name);
+ stat(tmp_path, buf);
+ free(tmp_path);
+
+ dir_entries = realloc(dir_entries, sizeof(struct dir_entry_t) * (n_dir_entries + 1));
+ dir_entry->name = malloc(d_name_len + 1);
+
+ strcpy(dir_entry->name, d_name);
+
+ mode_t s = buf->st_mode;
+ if (S_ISBLK(s) || S_ISCHR(s)) dir_entry->file_type = FILE_BLK;
+ else if (S_ISDIR(s)) dir_entry->file_type = FILE_DIR;
+ else if (S_ISFIFO(s)) dir_entry->file_type = FILE_FIFO;
+ else if (S_ISLNK(s)) dir_entry->file_type = FILE_LINK;
+ else dir_entry->file_type = FILE_REG;
+ free(buf);
+
+ dir_entries[n_dir_entries] = dir_entry;
+
+ n_dir_entries++;
+ }
+
+ closedir(dir);
+
+ return 0;
+}
+
+
+void free_dir_entries(void) {
+ for (size_t i = 0; i < n_dir_entries; i++) {
+ free(dir_entries[i]->name);
+ free(dir_entries[i]);
+ }
+
+ n_dir_entries = 0;
+}
diff --git a/src/io.c b/src/io.c
new file mode 100644
index 0000000..4ce1fd0
--- /dev/null
+++ b/src/io.c
@@ -00 +1109 @@
+#include <ncurses.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "dir.h"
+#include "io.h"
+
+void curses_init(void) {
+ initscr();
+ curs_set(0);
+ start_color();
+
+ init_pair(BLUE, COLOR_BLUE, COLOR_BLACK);
+ init_pair(HBLUE, COLOR_BLACK, COLOR_BLUE);
+ init_pair(CYAN, COLOR_CYAN, COLOR_BLACK);
+ init_pair(HCYAN, COLOR_BLACK, COLOR_CYAN);
+ init_pair(GREEN, COLOR_GREEN, COLOR_BLACK);
+ init_pair(HGREEN, COLOR_BLACK, COLOR_GREEN);
+ init_pair(MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(HMAGENTA, COLOR_BLACK, COLOR_MAGENTA);
+ init_pair(YELLOW, COLOR_YELLOW, COLOR_BLACK);
+ init_pair(HYELLOW, COLOR_BLACK, COLOR_YELLOW);
+ init_pair(RED, COLOR_RED, COLOR_BLACK);
+ init_pair(HRED, COLOR_BLACK, COLOR_RED);
+ init_pair(WHITE, COLOR_WHITE, COLOR_BLACK);
+ init_pair(HWHITE, COLOR_BLACK, COLOR_WHITE);
+}
+
+
+void curses_write_file(struct dir_entry_t * dir_entry, bool highlight) {
+ int cp = -1;
+
+ char f_ident;
+ if (highlight) {
+ switch (dir_entry->file_type) {
+ case FILE_DIR:
+ cp = HBLUE;
+ f_ident = '/';
+ break;
+ case FILE_FIFO:
+ cp = HYELLOW;
+ f_ident = '|';
+ break;
+ case FILE_BLK:
+ cp = HYELLOW;
+ f_ident = '#';
+ break;
+ case FILE_LINK:
+ cp = HCYAN;
+ f_ident = '@';
+ break;
+ default: break;
+ }
+ if (cp == -1) {
+ cp = HWHITE;
+ f_ident = ' ';
+ }
+ } else {
+ switch (dir_entry->file_type) {
+ case FILE_DIR:
+ cp = BLUE;
+ f_ident = '/';
+ break;
+ case FILE_FIFO:
+ cp = YELLOW;
+ f_ident = '|';
+ break;
+ case FILE_BLK:
+ cp = YELLOW;
+ f_ident = '#';
+ break;
+ case FILE_LINK:
+ cp = CYAN;
+ f_ident = '@';
+ break;
+ default: break;
+ }
+ if (cp == -1) {
+ cp = WHITE;
+ f_ident = ' ';
+ }
+ }
+
+ attron(COLOR_PAIR((unsigned)cp));
+ printw("%s", dir_entry->name);
+ attroff(COLOR_PAIR((unsigned)cp));
+ printw("%c\n", f_ident);
+}
+
+
+char curses_getch(void) {
+ char c = getch();
+
+ char seq[5];
+ char * ptr = seq;
+
+ if (c == 27) {
+ *ptr++ = getch();
+ *ptr++ = getch();
+ *ptr++ = '\0';
+ }
+
+ if (!strcmp(seq, "[A"))
+ return ARROW_UP;
+ else if (!strcmp(seq, "[B"))
+ return ARROW_DOWN;
+ else
+ return c;
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..f2da568
--- /dev/null
+++ b/src/main.c
@@ -00 +151 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <ncurses.h>
+
+#include "dir.h"
+#include "io.h"
+
+int main(int argc, char ** argv) {
+ curses_init();
+
+ if (argc > 1)
+ cwd = argv[1];
+ else
+ cwd = getenv("PWD");
+
+ list_dir(cwd);
+
+ size_t cursor = 1;
+
+ while (true) {
+ erase();
+
+ printw("\n%s\n\n", cwd);
+
+ for (size_t i = 0; i < n_dir_entries; i++) {
+ if (cursor - 1 == i)
+ curses_write_file(dir_entries[i], true);
+ else
+ curses_write_file(dir_entries[i], false);
+ }
+
+ printw("\n%lu/%lu\n", cursor, n_dir_entries);
+
+ refresh();
+
+ char c = curses_getch();
+ if ((c == ARROW_UP || c == 'k') && cursor > 1)
+ cursor--;
+ else if ((c == ARROW_DOWN || c == 'j') && cursor < n_dir_entries)
+ cursor++;
+ else if (c == 'q')
+ goto done;
+ }
+
+done:
+ free_dir_entries();
+ free(dir_entries);
+ endwin();
+ return 0;
+}