1+ import { program } from 'commander' ;
2+ import { promises as fs } from 'node:fs' ;
3+ import process from 'node:process' ;
4+
5+ program
6+ . name ( 'cat' )
7+ . description ( 'Concatenates and prints the contents of files.' )
8+ . argument ( '<paths...>' , 'The paths to the files to concatenate' )
9+ . option ( '-n, --number' , 'Number all output lines' )
10+ . option ( '-b, --number-nonblank' , 'Number nonempty output lines' ) ;
11+
12+ program . parse ( ) ;
13+
14+ const argv = program . args ;
15+ const options = program . opts ( ) ;
16+
17+ if ( argv . length < 1 ) {
18+ console . error (
19+ `Expected at least 1 argument (a path) to be passed but got ${ argv . length } .` ,
20+ ) ;
21+ process . exit ( 1 ) ;
22+ }
23+
24+ let showLineNumbers = options . number || false ;
25+ let showNonEmptyLineNumbers = options . numberNonblank || false ;
26+
27+ if ( showLineNumbers && showNonEmptyLineNumbers ) {
28+ showLineNumbers = false ;
29+ }
30+
31+ let lineNumber = 1 ;
32+ const spacer = ' ' ;
33+
34+ for ( const path of argv ) {
35+ const content = await fs . readFile ( path , 'utf-8' ) ;
36+ const lines = content . split ( '\n' ) ;
37+ while ( lines . length > 0 && lines [ lines . length - 1 ] === '' ) {
38+ lines . pop ( ) ;
39+ }
40+ for ( const line of lines ) {
41+ if ( showLineNumbers ) {
42+ process . stdout . write ( `${ spacer } ${ lineNumber ++ } ${ line } \n` ) ;
43+ } else if ( showNonEmptyLineNumbers && line . trim ( ) !== '' ) {
44+ process . stdout . write ( `${ spacer } ${ lineNumber ++ } ${ line } \n` ) ;
45+ } else {
46+ process . stdout . write ( `${ line } \n` ) ;
47+ }
48+ }
49+ }
0 commit comments