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
611import fs from "node:fs" ;
712import { pathToFileURL } from "node:url" ;
813
914async 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+
68108function 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