1+ const fs = require ( 'fs' ) ;
2+ const path = require ( 'path' ) ;
3+
4+ class MdTail {
5+ constructor ( ) {
6+ this . files = [ ] ;
7+ this . currentTabIndex = 0 ;
8+ }
9+
10+ parseArguments ( args ) {
11+ const helpFlags = [ '-h' , '--help' ] ;
12+
13+ if ( args . some ( arg => helpFlags . includes ( arg ) ) ) {
14+ return { showHelp : true } ;
15+ }
16+
17+ return { showHelp : false } ;
18+ }
19+
20+ expandFiles ( args , currentDir = process . cwd ( ) ) {
21+ const files = [ ] ;
22+
23+ if ( args . length === 0 ) {
24+ // Default to TODO.md in current directory
25+ const defaultFile = path . join ( currentDir , 'TODO.md' ) ;
26+ if ( fs . existsSync ( defaultFile ) ) {
27+ files . push ( defaultFile ) ;
28+ }
29+ } else {
30+ args . forEach ( arg => {
31+ if ( arg . includes ( '*' ) ) {
32+ // Handle wildcards
33+ const mdFiles = fs . readdirSync ( currentDir )
34+ . filter ( file => file . endsWith ( '.md' ) )
35+ . sort ( )
36+ . map ( f => path . resolve ( currentDir , f ) ) ;
37+ files . push ( ...mdFiles ) ;
38+ } else {
39+ // Resolve individual file paths
40+ const filePath = path . resolve ( currentDir , arg ) ;
41+ if ( fs . existsSync ( filePath ) && filePath . endsWith ( '.md' ) ) {
42+ files . push ( filePath ) ;
43+ }
44+ }
45+ } ) ;
46+ }
47+
48+ // Remove duplicates
49+ return [ ...new Set ( files ) ] ;
50+ }
51+
52+ validateFiles ( files ) {
53+ if ( ! Array . isArray ( files ) || files . length === 0 ) {
54+ throw new Error ( 'No markdown files found to watch' ) ;
55+ }
56+ return true ;
57+ }
58+
59+ renderTabs ( files , currentIndex , width = 80 ) {
60+ if ( files . length <= 1 ) return '' ;
61+
62+ const tabs = files . map ( ( file , index ) => {
63+ const filename = path . basename ( file ) ;
64+ const isActive = index === currentIndex ;
65+
66+ if ( isActive ) {
67+ return `[${ filename } ]` ;
68+ } else {
69+ return ` ${ filename } ` ;
70+ }
71+ } ) ;
72+
73+ const tabLine = tabs . join ( ' │ ' ) ;
74+ return `${ tabLine } \n${ '─' . repeat ( width ) } \n` ;
75+ }
76+
77+ formatContent ( content , filename , width = 80 ) {
78+ const lines = [ ] ;
79+ lines . push ( '\n' + '═' . repeat ( width ) ) ;
80+ lines . push ( filename . toUpperCase ( ) ) ;
81+ lines . push ( '═' . repeat ( width ) + '\n' ) ;
82+ lines . push ( content ) ;
83+ lines . push ( '\n' + '═' . repeat ( width ) ) ;
84+ return lines . join ( '\n' ) ;
85+ }
86+
87+ getHelpText ( ) {
88+ return `
89+ mdtail - Terminal markdown viewer with live refresh
90+
91+ Usage:
92+ mdtail [file1.md] [file2.md] ... Watch specific markdown files
93+ mdtail Watch TODO.md (default)
94+ mdtail -h, --help Show this help message
95+
96+ Navigation:
97+ ← / → Arrow Keys Switch between tabs
98+ Ctrl+C Exit
99+
100+ Examples:
101+ mdtail README.md Watch README.md
102+ mdtail todo.md notes.md Watch multiple files with tabs
103+ mdtail *.md Watch all markdown files in tabs
104+ ` ;
105+ }
106+
107+ navigateTab ( direction ) {
108+ if ( this . files . length <= 1 ) return false ;
109+
110+ if ( direction === 'left' ) {
111+ this . currentTabIndex = ( this . currentTabIndex - 1 + this . files . length ) % this . files . length ;
112+ } else if ( direction === 'right' ) {
113+ this . currentTabIndex = ( this . currentTabIndex + 1 ) % this . files . length ;
114+ } else {
115+ return false ;
116+ }
117+
118+ return true ;
119+ }
120+ }
121+
122+ module . exports = MdTail ;
0 commit comments