@@ -14,6 +14,7 @@ mod psmacos;
1414mod pslinux;
1515
1616use clap:: Parser ;
17+ use std:: collections:: HashMap ;
1718
1819#[ cfg( target_os = "macos" ) ]
1920mod platform {
@@ -44,6 +45,57 @@ struct Args {
4445 /// Exclude session leaders
4546 #[ arg( short = 'd' , long) ]
4647 exclude_session_leaders : bool ,
48+
49+ /// Full output format (-f)
50+ #[ arg( short = 'f' , long) ]
51+ full_format : bool ,
52+
53+ /// Long output format (-l)
54+ #[ arg( short = 'l' , long) ]
55+ long_format : bool ,
56+
57+ /// Custom output format (-o)
58+ #[ arg( short = 'o' , long, value_parser = clap:: builder:: NonEmptyStringValueParser :: new( ) ) ]
59+ output_format : Option < String > ,
60+ }
61+
62+ // Parse the -o format option into a list of fields
63+ fn parse_output_format < ' a > (
64+ format : & ' a str ,
65+ posix_fields : & ' a HashMap < & ' a str , ( & ' a str , & ' a str ) > ,
66+ ) -> Vec < & ' a str > {
67+ format
68+ . split ( |c| c == ' ' || c == ',' )
69+ . map ( |s| {
70+ let field = s. split ( '=' ) . next ( ) . unwrap_or ( "" ) . trim ( ) ;
71+ if posix_fields. contains_key ( field) {
72+ field
73+ } else {
74+ panic ! ( "Invalid field specified in -o option: {}" , field) ;
75+ }
76+ } )
77+ . collect ( )
78+ }
79+
80+ // Lookup table for POSIX-compliant output fields
81+ fn posix_field_map ( ) -> HashMap < & ' static str , ( & ' static str , & ' static str ) > {
82+ HashMap :: from ( [
83+ ( "ruser" , ( "uid" , "RUSER" ) ) ,
84+ ( "user" , ( "uid" , "USER" ) ) ,
85+ ( "rgroup" , ( "gid" , "RGROUP" ) ) ,
86+ ( "group" , ( "gid" , "GROUP" ) ) ,
87+ ( "pid" , ( "pid" , "PID" ) ) ,
88+ ( "ppid" , ( "ppid" , "PPID" ) ) ,
89+ ( "pgid" , ( "pgid" , "PGID" ) ) ,
90+ ( "pcpu" , ( "pcpu" , "%CPU" ) ) ,
91+ ( "vsz" , ( "vsz" , "VSZ" ) ) ,
92+ ( "nice" , ( "nice" , "NI" ) ) ,
93+ ( "etime" , ( "etime" , "ELAPSED" ) ) ,
94+ ( "time" , ( "time" , "TIME" ) ) ,
95+ ( "tty" , ( "tty" , "TTY" ) ) ,
96+ ( "comm" , ( "comm" , "COMMAND" ) ) ,
97+ ( "args" , ( "args" , "COMMAND" ) ) ,
98+ ] )
4799}
48100
49101fn main ( ) {
@@ -80,14 +132,42 @@ fn main() {
80132 processes
81133 } ;
82134
83- println ! (
84- "{:<5} {:<5} {:<5} {:<5} {}" ,
85- "PID" , "PPID" , "UID" , "GID" , "COMMAND"
86- ) ;
135+ // Define a lookup table for POSIX-compliant fields
136+ let posix_fields = posix_field_map ( ) ;
137+
138+ // Build output based on -o, -f, -l, or default
139+ let output_fields = if let Some ( ref format) = args. output_format {
140+ parse_output_format ( format, & posix_fields)
141+ } else if args. full_format {
142+ vec ! [ "uid" , "pid" , "ppid" , "C" , "time" , "comm" ]
143+ } else if args. long_format {
144+ vec ! [ "nice" , "vsz" , "WCHAN" , "tty" , "comm" ]
145+ } else {
146+ vec ! [ "pid" , "ppid" , "tty" , "time" , "comm" ] // Default format
147+ } ;
148+
149+ // Print the header
150+ for field in & output_fields {
151+ let header = posix_fields. get ( * field) . unwrap_or ( & ( & field, & field) ) . 1 ;
152+ print ! ( "{:<10} " , header) ;
153+ }
154+ println ! ( ) ;
155+
156+ // Print each process
87157 for proc in filtered_processes {
88- println ! (
89- "{:<5} {:<5} {:<5} {:<5} {}" ,
90- proc. pid, proc. ppid, proc. uid, proc. gid, proc. path
91- ) ;
158+ for field in & output_fields {
159+ match * field {
160+ "pid" => print ! ( "{:<10} " , proc. pid) ,
161+ "ppid" => print ! ( "{:<10} " , proc. ppid) ,
162+ "group" => print ! ( "{:<10} " , proc. gid) ,
163+ "tty" => print ! ( "{:<10} " , proc. tty. as_deref( ) . unwrap_or( "-" ) ) ,
164+ // "time" => print!("{:<10} ", proc.time),
165+ "comm" => print ! ( "{:<10} " , proc. path) ,
166+ "user" => print ! ( "{:<10} " , proc. uid) , // Example for user field, would need to resolve UID -> username
167+ // Add cases for more fields as needed...
168+ _ => print ! ( "{:<10} " , "-" ) ,
169+ }
170+ }
171+ println ! ( ) ;
92172 }
93173}
0 commit comments