1+ import { program } from "commander" ;
2+ import { promises as fs } from "node:fs" ;
3+ import process from "node:process" ;
4+
5+ // configure the CLI program with its name, description, arguments, options, and actions (the help instructions)
6+ program
7+ . name ( "cat" )
8+ . description ( "An alternative to the 'cat' command" )
9+ . argument ( "<files...>" , "The file(s) to process" )
10+ . option ( "-n, --number" , "Number all output lines" )
11+ . option ( "-b, --number-nonblank" , "Number non-blank output lines" )
12+ // actions to process the provided files with the specified options (-n, -b)
13+ . action ( async ( files , options ) => {
14+ try {
15+ // call newCat for all files
16+ await newCat ( files , options . number , options . numberNonblank )
17+ } catch ( err ) {
18+ console . error ( `Error: ${ err . message } ` ) ;
19+ }
20+ } ) ;
21+
22+ // parse command-line file arguments using the process.argv array
23+ program . parse ( process . argv ) ;
24+
25+
26+ async function newCat ( files , numberLines , numberNonBlank ) {
27+ let lineNumber = 1 ;
28+
29+ for ( const file of files ) {
30+ // read each file into a single text string
31+ try {
32+ const data = await fs . readFile ( file , "utf8" ) ;
33+ // split that string into an array at \n where each element is a line from the file
34+ // e.g. lines = ["Line 1", "Line 2", "Line 3"]
35+ const lines = data . split ( "\n" )
36+
37+ // remove trailing blank line caused by a trailing newline
38+ if ( lines [ lines . length - 1 ] === "" ) {
39+ lines . pop ( ) ;
40+ }
41+
42+ for ( const line of lines ) {
43+ if ( numberNonBlank ) {
44+ // check what is left on the line after trimming (truthy = text, falsy = blank)
45+ if ( line . trim ( ) ) {
46+ console . log ( `${ lineNumber . toString ( ) . padStart ( 6 , ' ' ) } ${ line } ` ) ;
47+ lineNumber ++
48+ } else {
49+ console . log ( line )
50+ }
51+ } else if ( numberLines ) {
52+ // number all lines
53+ console . log ( `${ lineNumber . toString ( ) . padStart ( 6 , ' ' ) } ${ line } ` ) ;
54+ lineNumber ++
55+ } else {
56+ // if neither flag print normally
57+ console . log ( line )
58+ }
59+ }
60+ } catch ( err ) {
61+ console . error ( `Error reading file ${ file } : ${ err . message } ` ) ;
62+ }
63+ }
64+ }
0 commit comments