tiempo-rs/src/cli.rs

307 lines
12 KiB
Rust

use clap::{
Command, Arg, SubCommand, command, value_parser,
};
pub fn make_cli() -> Command<'static> {
// Let's first declare some args that repeat here and there
let start_arg = Arg::with_name("start")
.long("start").short('s')
.takes_value(true).value_name("TIME")
.help("Include entries that start on this date or later");
let end_arg = Arg::with_name("end")
.long("end").short('e')
.takes_value(true).value_name("TIME")
.help("Include entries that start on this date or earlier");
let ids_arg = Arg::with_name("ids")
.short('v').long("ids")
.help("Print database ids (for use with edit)");
let grep_arg = Arg::with_name("grep")
.long("grep").short('g')
.takes_value(true).value_name("REGEXP")
.help("Only include entries whose note matches this regular expression");
let format_arg = Arg::with_name("format")
.short('f').long("format")
.takes_value(true).value_name("FORMAT")
.help(
"The output format. Valid built-in formats are chart, text, ical, \
csv, json and ids. Documentation on defining custom formats can be \
found at https://tiempo.categulario.xyz or the man page included \
with the installation."
);
let sheet_arg = Arg::with_name("sheet")
.takes_value(true).value_name("SHEET")
.help(
"The sheet to display. Pass 'all' to see entries from all sheets \
or 'full' to see hidden entries"
);
let at_arg = Arg::with_name("at")
.long("at")
.takes_value(true).value_name("TIME")
.help("Use this time instead of now");
let id_arg = Arg::with_name("id")
.long("id")
.takes_value(true).value_name("ID")
.value_parser(value_parser!(u64));
let interactive_arg = Arg::with_name("interactive")
.short('i')
.long("interactive")
.takes_value(false)
.conflicts_with("id")
.help("Choose an entry of the (unique) last N interactively");
// Now declar this app's cli
let cli = command!()
.subcommand_required(true)
.subcommand(SubCommand::with_name("archive")
.visible_alias("a")
.about("Move entries to a hidden sheet (by default named '_[SHEET]') so they're out of the way.")
.arg(start_arg.clone())
.arg(end_arg.clone())
.arg(grep_arg.clone())
.arg(sheet_arg.clone().help("Archive entries from this sheet instead of the current one"))
.arg(Arg::with_name("fake")
.short('f').long("fake")
.help("Don't actually archive the entries, just display them")
)
.arg(Arg::with_name("time")
.short('t').long("time")
.takes_value(true).value_name("HOURS")
.help("Time in hours to archive. Archived time will be equal or less than this.")
)
)
.subcommand(SubCommand::with_name("backend")
.visible_alias("b")
.about("Open an sqlite shell to the database.")
)
.subcommand(SubCommand::with_name("configure")
.visible_alias("c")
.about("Configure tiempo in-place. If no arguments are given it just prints the path to the config file in use.")
.arg(Arg::with_name("round_in_seconds")
.long("round-in-seconds")
.takes_value(true)
.value_name("SECONDS")
.value_parser(value_parser!(u64))
.help("The duration of time to use for rounding with the -r flag. Default: 900 (15 m)"))
.arg(Arg::with_name("database_file")
.long("database-file")
.takes_value(true)
.value_name("PATH")
.help("The file path of the sqlite database"))
.arg(Arg::with_name("append_notes_delimiter")
.long("append-notes-delimiter")
.takes_value(true)
.value_name("DELIMITER")
.help("delimiter used when appending notes via t edit --append. Default: ' ' (space)"))
.arg(Arg::with_name("formatter_search_paths")
.long("formatter-search-paths")
.takes_value(true)
.multiple(true)
.value_name("PATHS")
.help("comma separated directories to search for user defined fomatter classes"))
.arg(Arg::with_name("default_formatter")
.long("default-formatter")
.takes_value(true)
.value_name("FORMATTER")
.help("The format to use when display is invoked without a `--format` option. Default 'text'"))
.arg(Arg::with_name("require_note")
.long("require-note")
.help("Prompt for a note if one isn't provided when checking in (default)"))
.arg(Arg::with_name("no_require_note")
.long("no-require-note")
.help("Entries can be created without notes"))
.arg(Arg::with_name("auto_checkout")
.long("auto-checkout")
.help("Checkout of current running entry when starting a new one"))
.arg(Arg::with_name("no_auto_checkout")
.long("no-auto-checkout")
.help("Starting a new entry fails if one is running (default)"))
.arg(Arg::with_name("note_editor")
.long("note-editor")
.takes_value(true)
.value_name("EDITOR")
.help("Command to launch notes editor. Default: $EDITOR"))
.arg(Arg::with_name("week_start")
.long("week-start")
.takes_value(true)
.value_name("DAY")
.possible_values(["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"])
.help("The day of the week to use as the start of the week for t week. Default: monday"))
.arg(Arg::with_name("interactive_entries")
.long("interactive-entries")
.takes_value(true)
.value_name("N")
.value_parser(value_parser!(u64))
.help("How many unique previous notes to show when selecting interactively"))
)
.subcommand(SubCommand::with_name("display")
.visible_alias("d")
.about(
"Display the current timesheet or a specific. Pass `all' as \
SHEET to display all unarchived sheets or `full' to display \
archived and unarchived sheets.")
.arg(ids_arg.clone())
.arg(start_arg.clone())
.arg(end_arg.clone())
.arg(format_arg.clone())
.arg(grep_arg.clone())
.arg(sheet_arg.clone())
)
.subcommand(SubCommand::with_name("today")
.visible_alias("t")
.about("Display entries that started today")
.arg(ids_arg.clone())
.arg(end_arg.clone())
.arg(format_arg.clone())
.arg(grep_arg.clone())
.arg(sheet_arg.clone())
)
.subcommand(SubCommand::with_name("yesterday")
.visible_alias("y")
.about("Display entries that started yesterday")
.arg(ids_arg.clone())
.arg(format_arg.clone())
.arg(grep_arg.clone())
.arg(sheet_arg.clone())
)
.subcommand(SubCommand::with_name("week")
.visible_alias("w")
.about("Display entries starting last monday or later")
.arg(ids_arg.clone())
.arg(end_arg.clone())
.arg(format_arg.clone())
.arg(grep_arg.clone())
.arg(sheet_arg.clone())
)
.subcommand(SubCommand::with_name("month")
.visible_alias("m")
.about("Display entries starting this month")
.arg(ids_arg.clone())
.arg(format_arg.clone())
.arg(grep_arg.clone())
.arg(sheet_arg.clone())
.arg(Arg::with_name("month")
.long("month").short('m')
.takes_value(true).value_name("TIME")
.aliases(&["s", "start"])
.possible_values([
"this", "current", "last", "jan", "january", "feb",
"february", "mar", "march", "apr", "april", "may", "jun",
"june", "jul", "july", "aug", "august", "sep", "september",
"oct", "october", "nov", "november", "dic", "december",
])
.hide_possible_values(true)
.help(
"Include entries of the specified month instead of the \
current month"
)
)
)
.subcommand(SubCommand::with_name("in")
.visible_alias("i")
.about("Start an activity in the current timesheet")
.arg(at_arg.clone())
.arg(Arg::with_name("note")
.takes_value(true)
.value_name("NOTE")
.help("Text describing the activity to start"))
)
.subcommand(SubCommand::with_name("resume")
.visible_alias("r")
.about("Restart the timer for an entry. Defaults to the last active entry")
.arg(at_arg.clone())
.arg(id_arg.clone().help("Use entry with ID instead of the last entry"))
.arg(interactive_arg.clone())
)
.subcommand(SubCommand::with_name("out")
.visible_alias("o")
.about("end the active entry in the current timesheet")
.arg(at_arg.clone())
)
.subcommand(SubCommand::with_name("sheet")
.visible_alias("s")
.about("Change active timesheet or list existing timesheets")
.arg(sheet_arg.clone().help("The sheet to switch to. Use - to quickly switch to the previous sheet"))
)
.subcommand(SubCommand::with_name("list")
.visible_alias("l")
.about("List existing sheets")
.arg(Arg::with_name("all")
.short('a').long("all")
.help("List archive sheets also"))
.arg(Arg::with_name("flat")
.short('f').long("flat")
.help("show only the sheet names"))
)
.subcommand(SubCommand::with_name("kill")
.visible_alias("k")
.about("Delete an entry or an entire sheet")
.arg(id_arg.clone().help("Delete entry with this ID instead of sheet"))
.arg(Arg::with_name("sheet")
.takes_value(true).value_name("SHEET")
.conflicts_with_all(&["id", "last"])
.required_unless_one(["id", "last"])
.help(
"Delete an entire sheet by its name"
))
.arg(Arg::with_name("last")
.short('l').long("last")
.takes_value(false)
.help("Delete the last entry of the current sheet"))
)
.subcommand(SubCommand::with_name("now")
.visible_alias("n")
.about("Show all running entries")
)
.subcommand(SubCommand::with_name("edit")
.visible_alias("e")
.about("Edit an entry")
.arg(id_arg.clone().help("Edit entry with this ID instead of the last one in the current sheet"))
.arg(start_arg.clone().help("Set this as the start time"))
.arg(end_arg.clone().help("Set this as the end time"))
.arg(
Arg::with_name("append")
.long("append").short('z')
.help("Append to the current note instead of replacing it. The delimiter between appended notes is configurable (see configure)")
)
.arg(
Arg::with_name("move")
.short('m').long("move")
.takes_value(true)
.value_name("SHEET")
.help("Move entry to another sheet")
)
.arg(
Arg::with_name("note")
.takes_value(true)
.value_name("NOTE")
.help("The note text. It will replace the previous one unless --append is given")
)
);
cli
}