aboutsummaryrefslogtreecommitdiff
path: root/core/ls.c
blob: cd96ce78edfd77f14ab75fd58cb5f73cce691a6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "../lib/sys/sizes.h"
#include "../lib/sys/getdents.h"
#include "../lib/io/io.h"
#include "../lib/list/list.h"
#include "../lib/arg/arg.h"
#include "../lib/tctl/tctl.h"
#include "../lib/cstr/cstr.h"

#define BUF_SIZE sizeof(struct dirent) * 32

enum {
	FILTER_NONE   = 0,
	FILTER_HIDDEN = 1,
} filter = FILTER_HIDDEN;

list_t *dirs;


void set_filter_none()
{
	filter = FILTER_NONE;
}


void add_dir(const char *path)
{
	list_append(dirs, (void*)path);
}


u8 filter_entry(struct dirent *d)
{
	switch (filter) {
		case FILTER_HIDDEN:
			return d->d_name[0] != '.';
		case FILTER_NONE:
			return 1;
	}
}


int main(int argc, const char *argv[])
{
	int                  fd;
	char                 d_type;
	char                 buf[BUF_SIZE];
	long                 nread;
	u8 istty = isatty();
	i64 maxwidth = istty ? tctl_get_window_size().width : -1;
	i64 current_width = 0;

	struct dirent *d;
	dirs = new_list();

	arg_register_flag("-a", &set_filter_none);
	arg_register_default(&add_dir);
	arg_parse_arg(argc, argv);

	if (dirs->size == 0) {
		list_append(dirs, ".");
	}

	for (list_node_t *node = dirs->first; node; node = node->next) {
		fd = open(node->value, OPEN_READ_ONLY | OPEN_DIRECTORY, 0);

		while (1) {
			nread = getdents(fd, buf, BUF_SIZE);

			if (nread == 0)
				break;

			for (u64 bpos = 0; bpos < nread;) {
				d = (struct dirent*) (buf + bpos);
				if (filter_entry(d)) {
					if (!istty) {
						wstdf("%s\n", d->d_name);
					} else {
						current_width += cstr_length(d->d_name) + 2;
						if (current_width > maxwidth) {
							wstd("\n");
							wstd(d->d_name);
							wstd("  ");
							current_width = cstr_length(d->d_name) + 2;
						} else {
							wstdf("%s  ", d->d_name);
						}
					}
				}
				bpos += d->d_reclen;
			}
		}

		close(fd);
	}

	if (istty)
		wstd("\n");

	return 0;
}