aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2023-02-14 17:48:12 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2023-02-14 17:48:12 +0100
commit3a369468f7daae5b3a60feaa50c6050b240be6d4 (patch)
treeea3f5b1859c3cea91fb432c75c0920a0697347f3
parent7a98e998c5cda484611d19854649ab8535f503d4 (diff)
add colors to ls
-rw-r--r--core/ls.c43
-rw-r--r--lib/sys/getdents.h4
-rw-r--r--lib/sys/stat.h13
3 files changed, 54 insertions, 6 deletions
diff --git a/core/ls.c b/core/ls.c
index cd96ce7..c307ece 100644
--- a/core/ls.c
+++ b/core/ls.c
@@ -5,8 +5,11 @@
#include "../lib/arg/arg.h"
#include "../lib/tctl/tctl.h"
#include "../lib/cstr/cstr.h"
+#include "../lib/sys/errno.h"
+#include "../lib/aec/aec.h"
+#include "../lib/sys/stat.h"
-#define BUF_SIZE sizeof(struct dirent) * 32
+#define BUF_SIZE sizeof(dirent_t) * 32
enum {
FILTER_NONE = 0,
@@ -28,7 +31,7 @@ void add_dir(const char *path)
}
-u8 filter_entry(struct dirent *d)
+u8 filter_entry(dirent_t *d)
{
switch (filter) {
case FILTER_HIDDEN:
@@ -39,6 +42,29 @@ u8 filter_entry(struct dirent *d)
}
+void set_color(int fd, const char *name)
+{
+
+ stat_t st;
+ const char *color;
+
+ fstatat(fd, name, &st, 0);
+
+ switch (st.mode & S_IFMT) {
+ case S_IFREG: color = COLOR_WHITE; break;
+ case S_IFDIR: color = COLOR_BLUE; break;
+ case S_IFLNK: color = COLOR_CYAN; break;
+ case S_IFSOCK: color = COLOR_RED; break;
+ case S_IFBLK: color = COLOR_YELLOW; break;
+ case S_IFCHR: color = COLOR_PINK; break;
+ case S_IFIFO: color = COLOR_GREEN; break;
+ default: color = COLOR_RED; break;
+ }
+
+ foreground(color);
+}
+
+
int main(int argc, const char *argv[])
{
int fd;
@@ -49,7 +75,7 @@ int main(int argc, const char *argv[])
i64 maxwidth = istty ? tctl_get_window_size().width : -1;
i64 current_width = 0;
- struct dirent *d;
+ dirent_t *d;
dirs = new_list();
arg_register_flag("-a", &set_filter_none);
@@ -63,6 +89,11 @@ int main(int argc, const char *argv[])
for (list_node_t *node = dirs->first; node; node = node->next) {
fd = open(node->value, OPEN_READ_ONLY | OPEN_DIRECTORY, 0);
+ if (fd < 0) {
+ wff(STDERR_FD, "error: %s", errstr[-fd]);
+ continue;
+ }
+
while (1) {
nread = getdents(fd, buf, BUF_SIZE);
@@ -70,7 +101,7 @@ int main(int argc, const char *argv[])
break;
for (u64 bpos = 0; bpos < nread;) {
- d = (struct dirent*) (buf + bpos);
+ d = (dirent_t*) (buf + bpos);
if (filter_entry(d)) {
if (!istty) {
wstdf("%s\n", d->d_name);
@@ -78,11 +109,15 @@ int main(int argc, const char *argv[])
current_width += cstr_length(d->d_name) + 2;
if (current_width > maxwidth) {
wstd("\n");
+ set_color(fd, d->d_name);
wstd(d->d_name);
+ wstdf("%S", SGR_RESET)
wstd(" ");
current_width = cstr_length(d->d_name) + 2;
} else {
+ set_color(fd, d->d_name);
wstdf("%s ", d->d_name);
+ wstdf("%S", SGR_RESET)
}
}
}
diff --git a/lib/sys/getdents.h b/lib/sys/getdents.h
index b5a0c74..5efa3db 100644
--- a/lib/sys/getdents.h
+++ b/lib/sys/getdents.h
@@ -3,12 +3,12 @@
#include "syscalls.h"
-struct dirent {
+typedef struct {
unsigned long d_ino;
unsigned long d_off;
unsigned short d_reclen;
char d_name[];
-};
+} dirent_t;
static int getdents(unsigned int fd, char *buf, unsigned int count)
{
diff --git a/lib/sys/stat.h b/lib/sys/stat.h
index 0e02295..9fc5eda 100644
--- a/lib/sys/stat.h
+++ b/lib/sys/stat.h
@@ -60,4 +60,17 @@ static int stat(const char * filename, struct stat * statbuf)
return syscall(STAT, filename, statbuf);
}
+
+static int fstat(int fd, struct stat * statbuf)
+{
+ return syscall(FSTAT, fd, statbuf);
+}
+
+
+static int fstatat(int dirfd, const char *pathname, struct stat * statbuf, int flags)
+{
+ return syscall(NEWFSTATAT, dirfd, pathname, statbuf, flags);
+}
+
+
#endif