Skip to content

Commit 4d73eab

Browse files
committed
wc: add flags -l (lines), -w (words), -c (bytes) with multi-file totals
1 parent 6ac53b9 commit 4d73eab

File tree

1 file changed

+54
-14
lines changed
  • implement-shell-tools/wc

1 file changed

+54
-14
lines changed

implement-shell-tools/wc/wc.js

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,50 @@
11
#!/usr/bin/env node
2-
// wc.js — ESM: multiple files + total (no flags)
3-
// Prints per-file: lines words bytes filename
4-
// If given >1 files, also prints a "total" line.
2+
// wc.js — ESM: supports flags -l (lines), -w (words), -c (bytes)
3+
// Behaviors covered by the README:
4+
// - wc sample-files/*
5+
// - wc -l sample-files/3.txt
6+
// - wc -w sample-files/3.txt
7+
// - wc -c sample-files/3.txt
8+
// - wc -l sample-files/*
9+
// Also works with multiple flags (e.g., -lw), like GNU wc.
510

611
import fs from "node:fs";
712
import { pathToFileURL } from "node:url";
813

914
async function main() {
10-
const files = process.argv.slice(2);
15+
const argv = process.argv.slice(2);
16+
17+
let showLines = false;
18+
let showWords = false;
19+
let showBytes = false;
20+
const files = [];
21+
22+
// Parse flags + files. Support combined short flags like -lw, -cl, etc.
23+
for (const arg of argv) {
24+
if (arg.startsWith("-") && arg !== "-") {
25+
for (const ch of arg.slice(1)) {
26+
if (ch === "l") showLines = true;
27+
else if (ch === "w") showWords = true;
28+
else if (ch === "c") showBytes = true;
29+
else {
30+
// ignore unknown short options for this assignment
31+
}
32+
}
33+
} else {
34+
files.push(arg);
35+
}
36+
}
37+
1138
if (files.length === 0) {
12-
console.error("Usage (this commit): node wc.js <file...>");
39+
console.error("Usage: node wc.js [-l|-w|-c] <file...>");
1340
process.exit(1);
1441
}
1542

43+
// No flags → show all three like wc
44+
const showAll = !showLines && !showWords && !showBytes;
45+
1646
let hadError = false;
17-
let totalLines = 0, totalWords = 0, totalBytes = 0;
47+
let total = { lines: 0, words: 0, bytes: 0 };
1848
const results = [];
1949

2050
for (const file of files) {
@@ -25,9 +55,11 @@ async function main() {
2555
hadError = true;
2656
continue;
2757
}
28-
const { lines, words, bytes } = await countFile(file);
29-
results.push({ file, lines, words, bytes });
30-
totalLines += lines; totalWords += words; totalBytes += bytes;
58+
const counts = await countFile(file);
59+
results.push({ file, ...counts });
60+
total.lines += counts.lines;
61+
total.words += counts.words;
62+
total.bytes += counts.bytes;
3163
} catch (err) {
3264
if (err?.code === "ENOENT") {
3365
console.error(`wc: ${file}: No such file or directory`);
@@ -41,10 +73,10 @@ async function main() {
4173
}
4274

4375
for (const r of results) {
44-
console.log(`${pad(r.lines)} ${pad(r.words)} ${pad(r.bytes)} ${r.file}`);
76+
console.log(formatRow(r, { showAll, showLines, showWords, showBytes }));
4577
}
4678
if (results.length > 1) {
47-
console.log(`${pad(totalLines)} ${pad(totalWords)} ${pad(totalBytes)} total`);
79+
console.log(formatRow({ file: "total", ...total }, { showAll, showLines, showWords, showBytes }));
4880
}
4981

5082
if (hadError) process.exitCode = 1;
@@ -54,19 +86,27 @@ async function countFile(file) {
5486
const buf = await fs.promises.readFile(file); // Buffer
5587
const bytes = buf.length;
5688

57-
// lines: count '\n' bytes
89+
// Lines: count '\n' bytes
5890
let lines = 0;
5991
for (let i = 0; i < buf.length; i++) if (buf[i] === 0x0a) lines++;
6092

61-
// words: sequences of non-whitespace (on UTF-8 text)
93+
// Words: sequences of non-whitespace
6294
const text = buf.toString("utf8");
6395
const words = (text.match(/\S+/g) || []).length;
6496

6597
return { lines, words, bytes };
6698
}
6799

100+
function formatRow({ lines, words, bytes, file }, opts) {
101+
const cols = [];
102+
if (opts.showAll || opts.showLines) cols.push(pad(lines));
103+
if (opts.showAll || opts.showWords) cols.push(pad(words));
104+
if (opts.showAll || opts.showBytes) cols.push(pad(bytes));
105+
return `${cols.join(" ")} ${file}`;
106+
}
107+
68108
function pad(n) {
69-
// Right-align like `wc` (fixed width works well for visual parity)
109+
// Right-align like `wc`
70110
return String(n).padStart(7, " ");
71111
}
72112

0 commit comments

Comments
 (0)