Skip to content

Commit 523342a

Browse files
committed
wc command implementation.
1 parent 4179068 commit 523342a

3 files changed

Lines changed: 113 additions & 0 deletions

File tree

implement-shell-tools/wc/package-lock.json

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "module",
3+
"dependencies": {
4+
"commander": "^14.0.0"
5+
}
6+
}

implement-shell-tools/wc/wc.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { program } from "commander";
2+
import { promises as fs } from "node:fs";
3+
import path from "node:path";
4+
import { stat } from "node:fs/promises";
5+
6+
program
7+
.name("my-wc")
8+
.description("simplified implementation of wc")
9+
.argument("[paths...]", "One or more file or directory paths")
10+
.option("-l, --line", "count lines")
11+
.option("-w, --word", "count words")
12+
.option("-c, --character", "count characters");
13+
14+
program.parse();
15+
16+
const filePaths = program.args.length > 0 ? program.args : ['.'];
17+
const options = program.opts();
18+
19+
const countContent = (content) => {
20+
const lines = content.split('\n').length;
21+
const words = content.trim().split(/\s+/).filter(Boolean).length;
22+
const characters = content.length;
23+
return { lines, words, characters };
24+
};
25+
26+
const total = {
27+
lines: 0,
28+
words: 0,
29+
characters: 0
30+
};
31+
32+
(async () => {
33+
let fileCount = 0;
34+
35+
for (const inputPath of filePaths) {
36+
try {
37+
const stats = await stat(inputPath);
38+
if (stats.isDirectory()) {
39+
console.log(`${inputPath} is a directory. Skipping.`);
40+
continue;
41+
}
42+
43+
const content = await fs.readFile(inputPath, "utf-8");
44+
const { lines, words, characters } = countContent(content);
45+
46+
total.lines += lines;
47+
total.words += words;
48+
total.characters += characters;
49+
fileCount++;
50+
51+
let output = "";
52+
if (options.line) output += `${lines.toString().padStart(8)} `;
53+
if (options.word) output += `${words.toString().padStart(8)} `;
54+
if (options.character) output += `${characters.toString().padStart(8)} `;
55+
56+
// If no options given, show all
57+
if (!options.line && !options.word && !options.character) {
58+
output += `${lines.toString().padStart(8)} `;
59+
output += `${words.toString().padStart(8)} `;
60+
output += `${characters.toString().padStart(8)} `;
61+
}
62+
63+
output += inputPath;
64+
console.log(output);
65+
} catch (err) {
66+
console.error(`Error reading "${inputPath}": ${err.message}`);
67+
}
68+
}
69+
70+
// Print total only if multiple files were processed
71+
if (fileCount > 1) {
72+
let output = "";
73+
if (options.line) output += `${total.lines.toString().padStart(8)} `;
74+
if (options.word) output += `${total.words.toString().padStart(8)} `;
75+
if (options.character) output += `${total.characters.toString().padStart(8)} `;
76+
77+
if (!options.line && !options.word && !options.character) {
78+
output += `${total.lines.toString().padStart(8)} `;
79+
output += `${total.words.toString().padStart(8)} `;
80+
output += `${total.characters.toString().padStart(8)} `;
81+
}
82+
83+
output += "total";
84+
console.log(output);
85+
}
86+
})();

0 commit comments

Comments
 (0)