1- import packageJson from '../../package.json' ;
2- import themes from '../../themes.json' ;
3- import { history } from '../stores/history' ;
4- import { theme } from '../stores/theme' ;
1+ import packageJson from "../../package.json" ;
2+ import themes from "../../themes.json" ;
3+ import { history } from "../stores/history" ;
4+ import { theme } from "../stores/theme" ;
5+ import { todoManager } from "./todo" ;
56
67const hostname = window . location . hostname ;
78
89export const commands : Record < string , ( args : string [ ] ) => Promise < string > | string > = {
9- help : ( ) => 'Available commands: ' + Object . keys ( commands ) . join ( ', ' ) ,
10+ help : ( ) => {
11+ const categories = {
12+ System : [ "help" , "clear" , "date" , "exit" ] ,
13+ Productivity : [ "todo" , "weather" ] ,
14+ Customization : [ "theme" , "banner" ] ,
15+ Network : [ "curl" , "hostname" , "whoami" ] ,
16+ Contact : [ "email" , "repo" , "donate" ] ,
17+ Fun : [ "echo" , "sudo" , "vi" , "vim" , "emacs" ] ,
18+ } ;
19+
20+ let output = "Available commands:\n\n" ;
21+
22+ for ( const [ category , cmds ] of Object . entries ( categories ) ) {
23+ output += `${ category } :\n` ;
24+ output += cmds . map ( ( cmd ) => ` ${ cmd } ` ) . join ( "\n" ) ;
25+ output += "\n\n" ;
26+ }
27+
28+ output +=
29+ 'Type "[command] help" or "[command]" without args for more info.' ;
30+
31+ return output ;
32+ } ,
1033 hostname : ( ) => hostname ,
11- whoami : ( ) => ' guest' ,
34+ whoami : ( ) => " guest" ,
1235 date : ( ) => new Date ( ) . toLocaleString ( ) ,
1336 vi : ( ) => `why use vi? try 'emacs'` ,
1437 vim : ( ) => `why use vim? try 'emacs'` ,
1538 emacs : ( ) => `why use emacs? try 'vim'` ,
16- echo : ( args : string [ ] ) => args . join ( ' ' ) ,
39+ echo : ( args : string [ ] ) => args . join ( " " ) ,
1740 sudo : ( args : string [ ] ) => {
18- window . open ( ' https://www.youtube.com/watch?v=dQw4w9WgXcQ' ) ;
41+ window . open ( " https://www.youtube.com/watch?v=dQw4w9WgXcQ" ) ;
1942
2043 return `Permission denied: unable to run the command '${ args [ 0 ] } ' as root.` ;
2144 } ,
@@ -34,14 +57,14 @@ export const commands: Record<string, (args: string[]) => Promise<string> | stri
3457 }
3558
3659 switch ( args [ 0 ] ) {
37- case 'ls' : {
38- let result = themes . map ( ( t ) => t . name . toLowerCase ( ) ) . join ( ', ' ) ;
60+ case "ls" : {
61+ let result = themes . map ( ( t ) => t . name . toLowerCase ( ) ) . join ( ", " ) ;
3962 result += `You can preview all these themes here: ${ packageJson . repository . url } /tree/master/docs/themes` ;
4063
4164 return result ;
4265 }
4366
44- case ' set' : {
67+ case " set" : {
4568 if ( args . length !== 2 ) {
4669 return usage ;
4770 }
@@ -64,42 +87,42 @@ export const commands: Record<string, (args: string[]) => Promise<string> | stri
6487 }
6588 } ,
6689 repo : ( ) => {
67- window . open ( packageJson . repository . url , ' _blank' ) ;
90+ window . open ( packageJson . repository . url , " _blank" ) ;
6891
69- return ' Opening repository...' ;
92+ return " Opening repository..." ;
7093 } ,
7194 clear : ( ) => {
7295 history . set ( [ ] ) ;
7396
74- return '' ;
97+ return "" ;
7598 } ,
7699 email : ( ) => {
77100 window . open ( `mailto:${ packageJson . author . email } ` ) ;
78101
79102 return `Opening mailto:${ packageJson . author . email } ...` ;
80103 } ,
81104 donate : ( ) => {
82- window . open ( packageJson . funding . url , ' _blank' ) ;
105+ window . open ( packageJson . funding . url , " _blank" ) ;
83106
84- return ' Opening donation url...' ;
107+ return " Opening donation url..." ;
85108 } ,
86109 weather : async ( args : string [ ] ) => {
87- const city = args . join ( '+' ) ;
110+ const city = args . join ( "+" ) ;
88111
89112 if ( ! city ) {
90- return ' Usage: weather [city]. Example: weather Brussels' ;
113+ return " Usage: weather [city]. Example: weather Brussels" ;
91114 }
92115
93116 const weather = await fetch ( `https://wttr.in/${ city } ?ATm` ) ;
94117
95118 return weather . text ( ) ;
96119 } ,
97120 exit : ( ) => {
98- return ' Please close the tab to exit.' ;
121+ return " Please close the tab to exit." ;
99122 } ,
100123 curl : async ( args : string [ ] ) => {
101124 if ( args . length === 0 ) {
102- return ' curl: no URL provided' ;
125+ return " curl: no URL provided" ;
103126 }
104127
105128 const url = args [ 0 ] ;
@@ -123,4 +146,76 @@ export const commands: Record<string, (args: string[]) => Promise<string> | stri
123146
124147Type 'help' to see list of available commands.
125148` ,
149+ todo : ( args : string [ ] ) => {
150+ const usage = `Usage: todo [command] [args]
151+
152+ Commands:
153+ add <text> Add a new todo
154+ ls [filter] List todos (filter: all, completed, pending)
155+ done <id> Mark todo as completed
156+ rm <id> Remove a todo
157+ clear [completed] Clear todos (add 'completed' to clear only completed)
158+ stats Show todo statistics
159+
160+ Examples:
161+ todo add Buy groceries
162+ todo ls
163+ todo ls pending
164+ todo done 1
165+ todo rm 2
166+ todo clear completed` ;
167+
168+ if ( args . length === 0 ) {
169+ return usage ;
170+ }
171+
172+ const [ subCommand , ...subArgs ] = args ;
173+
174+ switch ( subCommand ) {
175+ case "add" :
176+ if ( subArgs . length === 0 ) {
177+ return "Error: Please provide todo text. Example: todo add Buy milk" ;
178+ }
179+ return todoManager . add ( subArgs . join ( " " ) ) ;
180+
181+ case "ls" :
182+ case "list" :
183+ const filter = subArgs [ 0 ] as
184+ | "all"
185+ | "completed"
186+ | "pending"
187+ | undefined ;
188+ if ( filter && ! [ "all" , "completed" , "pending" ] . includes ( filter ) ) {
189+ return "Error: Invalid filter. Use: all, completed, or pending" ;
190+ }
191+ return todoManager . list ( filter ) ;
192+
193+ case "done" :
194+ case "complete" :
195+ const completeId = parseInt ( subArgs [ 0 ] ) ;
196+ if ( isNaN ( completeId ) ) {
197+ return "Error: Please provide a valid todo ID number" ;
198+ }
199+ return todoManager . complete ( completeId ) ;
200+
201+ case "rm" :
202+ case "remove" :
203+ case "delete" :
204+ const removeId = parseInt ( subArgs [ 0 ] ) ;
205+ if ( isNaN ( removeId ) ) {
206+ return "Error: Please provide a valid todo ID number" ;
207+ }
208+ return todoManager . remove ( removeId ) ;
209+
210+ case "clear" :
211+ const onlyCompleted = subArgs [ 0 ] === "completed" ;
212+ return todoManager . clear ( onlyCompleted ) ;
213+
214+ case "stats" :
215+ return todoManager . stats ( ) ;
216+
217+ default :
218+ return `Unknown todo command: ${ subCommand } \n\n${ usage } ` ;
219+ }
220+ } ,
126221} ;
0 commit comments