182 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			V
		
	
	
| module cli
 | |
| 
 | |
| import time
 | |
| 
 | |
| fn man_flag() Flag {
 | |
| 	return Flag{
 | |
| 		flag: .bool
 | |
| 		name: 'man'
 | |
| 		description: 'Prints the auto-generated manpage.'
 | |
| 	}
 | |
| }
 | |
| 
 | |
| fn man_cmd() Command {
 | |
| 	return Command{
 | |
| 		name: 'man'
 | |
| 		usage: '<subcommand>'
 | |
| 		description: 'Prints the auto-generated manpage.'
 | |
| 		execute: print_manpage_for_command
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // print_manpage_for_command prints the manpage for the
 | |
| // command or subcommand in `man_cmd` to stdout
 | |
| pub fn print_manpage_for_command(man_cmd Command) ? {
 | |
| 	if man_cmd.args.len > 0 {
 | |
| 		mut cmd := man_cmd.parent
 | |
| 		for arg in man_cmd.args {
 | |
| 			mut found := false
 | |
| 			for sub_cmd in cmd.commands {
 | |
| 				if sub_cmd.name == arg {
 | |
| 					cmd = unsafe { &sub_cmd }
 | |
| 					found = true
 | |
| 					break
 | |
| 				}
 | |
| 			}
 | |
| 			if !found {
 | |
| 				args := man_cmd.args.join(' ')
 | |
| 				println('Invalid command: $args')
 | |
| 				return
 | |
| 			}
 | |
| 		}
 | |
| 		print(cmd.manpage())
 | |
| 	} else {
 | |
| 		if man_cmd.parent != 0 {
 | |
| 			print(man_cmd.parent.manpage())
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // manpage returns a `string` containing the mdoc(7) manpage for
 | |
| // this `Command`
 | |
| pub fn (cmd Command) manpage() string {
 | |
| 	mut mdoc := '.Dd ${time.now().strftime('%B %d, %Y')}\n'
 | |
| 	mdoc += '.Dt ${cmd.full_name().replace(' ', '-').to_upper()} 1\n'
 | |
| 	mdoc += '.Os\n.Sh NAME\n.Nm ${cmd.full_name().replace(' ', '-')}\n.Nd $cmd.description\n'
 | |
| 	mdoc += '.Sh SYNOPSIS\n'
 | |
| 	mdoc += '.Nm $cmd.root().name\n'
 | |
| 	if cmd.parent != 0 {
 | |
| 		mut parents := []Command{}
 | |
| 		if !cmd.parent.is_root() {
 | |
| 			parents.prepend(cmd.parent)
 | |
| 			for {
 | |
| 				p := parents[0]
 | |
| 				if p.parent.is_root() {
 | |
| 					break
 | |
| 				} else {
 | |
| 					parents.prepend(p.parent)
 | |
| 				}
 | |
| 			}
 | |
| 			for c in parents {
 | |
| 				mdoc += '.Ar $c.name\n'
 | |
| 			}
 | |
| 		}
 | |
| 		mdoc += '.Ar $cmd.name\n'
 | |
| 	}
 | |
| 	for flag in cmd.flags {
 | |
| 		mdoc += '.Op'
 | |
| 		if flag.abbrev != '' {
 | |
| 			mdoc += ' Fl $flag.abbrev'
 | |
| 		} else {
 | |
| 			if cmd.posix_mode {
 | |
| 				mdoc += ' Fl -$flag.name'
 | |
| 			} else {
 | |
| 				mdoc += ' Fl $flag.name'
 | |
| 			}
 | |
| 		}
 | |
| 		match flag.flag {
 | |
| 			.int, .float, .int_array, .float_array { mdoc += ' Ar num' }
 | |
| 			.string, .string_array { mdoc += ' Ar string' }
 | |
| 			else {}
 | |
| 		}
 | |
| 		mdoc += '\n'
 | |
| 	}
 | |
| 	for i in 0 .. cmd.required_args {
 | |
| 		mdoc += '.Ar arg$i\n'
 | |
| 	}
 | |
| 	if cmd.commands.len > 0 {
 | |
| 		mdoc += '.Nm $cmd.root().name\n'
 | |
| 		if cmd.parent != 0 {
 | |
| 			mut parents := []Command{}
 | |
| 			if !cmd.parent.is_root() {
 | |
| 				parents.prepend(cmd.parent)
 | |
| 				for {
 | |
| 					p := parents[0]
 | |
| 					if p.parent.is_root() {
 | |
| 						break
 | |
| 					} else {
 | |
| 						parents.prepend(p.parent)
 | |
| 					}
 | |
| 				}
 | |
| 				for c in parents {
 | |
| 					mdoc += '.Ar $c.name\n'
 | |
| 				}
 | |
| 			}
 | |
| 			mdoc += '.Ar $cmd.name\n'
 | |
| 		}
 | |
| 		mdoc += '.Ar subcommand\n'
 | |
| 	}
 | |
| 
 | |
| 	mdoc += '.Sh DESCRIPTION\n'
 | |
| 	if cmd.man_description != '' {
 | |
| 		mdoc += '$cmd.man_description\n'
 | |
| 	} else if cmd.description != '' {
 | |
| 		mdoc += '$cmd.description\n'
 | |
| 	}
 | |
| 	if cmd.flags.len > 0 {
 | |
| 		mdoc += '.Pp\nThe options are as follows:\n'
 | |
| 		mdoc += '.Bl -tag -width indent\n'
 | |
| 		for flag in cmd.flags {
 | |
| 			mdoc += '.It'
 | |
| 			if flag.abbrev != '' {
 | |
| 				mdoc += ' Fl $flag.abbrev'
 | |
| 			}
 | |
| 			if cmd.posix_mode {
 | |
| 				mdoc += ' Fl -$flag.name'
 | |
| 			} else {
 | |
| 				mdoc += ' Fl $flag.name'
 | |
| 			}
 | |
| 			mdoc += '\n'
 | |
| 			if flag.description != '' {
 | |
| 				mdoc += '$flag.description\n'
 | |
| 			}
 | |
| 		}
 | |
| 		mdoc += '.El\n'
 | |
| 	}
 | |
| 	if cmd.commands.len > 0 {
 | |
| 		mdoc += '.Pp\nThe subcommands are as follows:\n'
 | |
| 		mdoc += '.Bl -tag -width indent\n'
 | |
| 		for c in cmd.commands {
 | |
| 			mdoc += '.It Cm $c.name\n'
 | |
| 			if c.description != '' {
 | |
| 				mdoc += '$c.description\n'
 | |
| 			}
 | |
| 		}
 | |
| 		mdoc += '.El\n'
 | |
| 	}
 | |
| 
 | |
| 	if cmd.commands.len > 0 {
 | |
| 		mdoc += '.Sh SEE ALSO\n'
 | |
| 		mut cmds := []string{}
 | |
| 		if cmd.parent != 0 {
 | |
| 			cmds << cmd.parent.full_name().replace(' ', '-')
 | |
| 		}
 | |
| 		for c in cmd.commands {
 | |
| 			cmds << c.full_name().replace(' ', '-')
 | |
| 		}
 | |
| 		cmds.sort()
 | |
| 		mut i := 1
 | |
| 		for c in cmds {
 | |
| 			mdoc += '.Xr $c 1'
 | |
| 			if i == cmds.len {
 | |
| 				mdoc += '\n'
 | |
| 			} else {
 | |
| 				mdoc += ' ,\n'
 | |
| 			}
 | |
| 			i++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return mdoc
 | |
| }
 |