···1+use std::path::PathBuf;
2+use std::{env::current_dir, io::Read};
3+4+//use smol;
5+//use iocraft::prelude::*;
6+use clap::{Args, Parser, Subcommand};
7+use edit::edit as open_editor;
8+9+fn default_dir() -> PathBuf {
10+ current_dir().unwrap()
11+}
12+13+#[derive(Parser)]
14+// TODO: add long_about
15+#[command(version, about, long_about = None)]
16+struct Cli {
17+ #[arg(short = 'C', env = "TSK_DIR", value_name = "DIR")]
18+ dir: Option<PathBuf>,
19+ // TODO: other global options
20+ #[command(subcommand)]
21+ command: Commands,
22+}
23+24+#[derive(Subcommand)]
25+enum Commands {
26+ /// Creates a new task, automatically assigning it a unique identifider and persisting
27+ Push {
28+ /// Whether to open $EDITOR to edit the content of the task. The first line if the
29+ /// resulting file will be the task's title. The body follows the title after two newlines,
30+ /// similr to the format of a commit message.
31+ #[arg(short = 'e', default_value_t = false)]
32+ edit: bool,
33+34+ /// The body of the task. It may be specified as either a string using quotes or the
35+ /// special character '-' to read from stdin.
36+ #[arg(short = 'b')]
37+ body: Option<String>,
38+39+ /// The title of the task as a raw string. It mus be proceeded by two dashes (--).
40+ #[command(flatten)]
41+ title: Title,
42+ },
43+}
44+45+#[derive(Args)]
46+#[group(required = true, multiple = false)]
47+struct Title {
48+ /// The title of the task. This is useful for when you also wish to specify the body of the
49+ /// task as an argument (ie. with -b).
50+ #[arg(short, value_name = "TITLE")]
51+ title: Option<String>,
52+53+ #[arg(value_name = "TITLE")]
54+ title_simple: Option<Vec<String>>,
55+}
56+57+fn main() {
58+ let cli = Cli::parse();
59+ if let Commands::Push { edit, body, title } = cli.command {
60+ let title = if let Some(title) = title.title {
61+ eprintln!("TITLE: {}", title);
62+ title
63+ } else if let Some(title) = title.title_simple {
64+ let joined = title.join(" ");
65+ eprintln!("TITLE simple: {}", joined);
66+ joined
67+ } else {
68+ "".to_string()
69+ };
70+ let mut body = body.unwrap_or_default();
71+ if body == "-" {
72+ // add newline so you can type directly in the shell
73+ eprintln!("");
74+ body.clear();
75+ std::io::stdin()
76+ .read_to_string(&mut body)
77+ .expect("Failed to read stdin");
78+ }
79+ if edit {
80+ body = open_editor(format!("{title}\n\n{body}")).expect("Failed to edit file");
81+ }
82+ eprintln!("BODY: {body}");
83+ }
84+}