Skip to content

Commit 8ab9ff3

Browse files
committed
task: complete implementation of ls functionality in javascript
1 parent a51051b commit 8ab9ff3

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

  • implement-shell-tools/ls

implement-shell-tools/ls/ls.mjs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import process from "node:process";
2+
import fs, { truncate } from "node:fs";
3+
4+
const argv = process.argv.slice(2);
5+
6+
const options = {
7+
onePerLine: false,
8+
all: false,
9+
help: false,
10+
};
11+
12+
const validFlags = {
13+
onePerLine: {
14+
short: "-1",
15+
long: "--one-per-line",
16+
description: "Lists one file per line",
17+
},
18+
all: {
19+
short: "-a",
20+
long: "--all",
21+
description: "Include entries whose names begin with a dot",
22+
},
23+
help: {
24+
short: "-h",
25+
long: "--help",
26+
description: "Display help information",
27+
},
28+
};
29+
30+
const paths = [];
31+
let parsingFlags = true;
32+
33+
for (const arg of argv) {
34+
if (arg === "--") {
35+
parsingFlags = false;
36+
} else if (parsingFlags && arg.startsWith("--")) {
37+
const matchedFlag = Object.entries(validFlags).find(
38+
([, definition]) => arg === definition.long,
39+
);
40+
41+
if (matchedFlag) {
42+
const [optionName] = matchedFlag;
43+
options[optionName] = true;
44+
} else {
45+
process.stderr.write(`Invalid option -- '${arg}'\n`);
46+
process.exit(1);
47+
}
48+
} else if (parsingFlags && arg.startsWith("-")) {
49+
const shortFlags = arg.slice(1);
50+
51+
for (const shortFlag of shortFlags) {
52+
const matchedFlag = Object.entries(validFlags).find(
53+
([, definition]) => definition.short === `-${shortFlag}`,
54+
);
55+
56+
if (matchedFlag) {
57+
const [optionName] = matchedFlag;
58+
options[optionName] = true;
59+
} else {
60+
process.stderr.write(`Invalid option -- '${arg}\n'`);
61+
process.exit(1);
62+
}
63+
}
64+
} else {
65+
paths.push(arg);
66+
}
67+
}
68+
69+
if (paths.length === 0) {
70+
paths.push(".");
71+
}
72+
73+
const multiplePaths = paths.length > 1;
74+
const filePaths = [];
75+
const directoryPaths = [];
76+
77+
for (const path of paths) {
78+
const stats = fs.statSync(path);
79+
80+
if (stats.isDirectory()) {
81+
directoryPaths.push(path);
82+
} else {
83+
filePaths.push(path);
84+
}
85+
}
86+
87+
if (filePaths.length > 0) {
88+
const separator = options.onePerLine ? "\n" : " ";
89+
process.stdout.write(`${filePaths.join(separator)}\n`);
90+
}
91+
92+
for (const path of directoryPaths) {
93+
if (multiplePaths) {
94+
process.stdout.write(`\n${path}: \n`);
95+
}
96+
let content = fs.readdirSync(path);
97+
98+
if (options.all) {
99+
content.unshift(".", "..");
100+
} else {
101+
content = content.filter((entry) => !entry.startsWith("."));
102+
}
103+
104+
content.sort();
105+
106+
const separator = options.onePerLine ? "\n" : " ";
107+
const output = content.join(separator);
108+
109+
process.stdout.write(`${output}\n`);
110+
}

0 commit comments

Comments
 (0)