1use clap::{Parser, Subcommand};
2use tracing_subscriber::EnvFilter;
3
4pub mod commands;
5
6#[derive(Parser)]
8#[command(name = "git-notes", version, about, long_about = None)]
9pub struct Cli {
10 #[command(subcommand)]
11 pub command: Commands,
12}
13
14#[derive(Subcommand)]
15pub enum Commands {
16 #[command(alias = "a")]
18 Add(commands::add::AddArgs),
19
20 #[command(alias = "r")]
22 Reply(commands::reply::ReplyArgs),
23
24 #[command(alias = "l", alias = "ls")]
26 List(commands::list::ListArgs),
27
28 #[command(alias = "s")]
30 Show(commands::show::ShowArgs),
31
32 #[command(alias = "push", alias = "pull", alias = "p2p")]
34 Sync(commands::sync::SyncArgs),
35
36 #[command(alias = "ok", alias = "close")]
38 Resolve(commands::resolve::ResolveArgs),
39
40 #[command(alias = "exp")]
42 Export(commands::export::ExportArgs),
43
44 #[command(alias = "doc")]
46 Doctor,
47
48 #[command(alias = "b")]
50 Blame(commands::blame::BlameArgs),
51
52 #[command(alias = "pr")]
54 ImportPr(commands::import_pr::ImportPrArgs),
55
56 #[command(alias = "imp")]
58 Import(commands::import::ImportArgs),
59
60 #[command(alias = "sum")]
62 Summarize(commands::summarize::SummarizeArgs),
63
64 #[command(alias = "i")]
66 Init,
67
68 Hook(commands::hook::HookArgs),
70
71 #[command(alias = "d")]
73 Diff(commands::diff::DiffArgs),
74
75 #[command(alias = "shortcut", alias = "keys", alias = "quickies")]
77 Shortcuts(commands::shortcuts::ShortcutsArgs),
78
79 Completions(commands::completions::CompletionsArgs),
81
82 #[command(alias = "heal")]
84 RebaseHeal(commands::rebase_heal::RebaseHealArgs),
85
86 #[command(alias = "gate")]
88 Check(commands::check::CheckArgs),
89
90 #[command(alias = "sig")]
92 Verify(commands::verify::VerifyArgs),
93}
94
95pub fn run_cli() -> anyhow::Result<()> {
96 tracing_subscriber::fmt()
97 .with_env_filter(EnvFilter::from_default_env())
98 .init();
99
100 let mut profile = commands::learning::UserBehaviorProfile::load();
101 let cli = Cli::parse();
102
103 let result = match &cli.command {
104 Commands::Add(args) => {
105 profile.record_interaction("add", Some(&args.file), Some(&args.namespace));
106 commands::add::run(args)
107 }
108 Commands::Reply(args) => {
109 profile.record_interaction("reply", None, None);
110 commands::reply::run(args)
111 }
112 Commands::List(args) => {
113 profile.record_interaction("list", args.file.as_deref(), args.namespace.as_deref());
114 commands::list::run(args)
115 }
116 Commands::Show(args) => {
117 profile.record_interaction("show", None, None);
118 commands::show::run(args)
119 }
120 Commands::Sync(args) => {
121 profile.record_interaction("sync", None, None);
122 commands::sync::run(args)
123 }
124 Commands::Resolve(args) => {
125 profile.record_interaction("resolve", None, None);
126 commands::resolve::run(args)
127 }
128 Commands::Export(args) => {
129 profile.record_interaction("export", None, None);
130 commands::export::run(args)
131 }
132 Commands::Doctor => {
133 profile.record_interaction("doctor", None, None);
134 commands::doctor::run()
135 }
136 Commands::Blame(args) => {
137 profile.record_interaction("blame", Some(&args.file), Some(&args.namespace));
138 commands::blame::run(args)
139 }
140 Commands::ImportPr(args) => {
141 profile.record_interaction("import-pr", None, Some(&args.namespace));
142 commands::import_pr::run(args)
143 }
144 Commands::Import(args) => {
145 profile.record_interaction("import", None, None);
146 commands::import::run(args)
147 }
148 Commands::Summarize(args) => {
149 profile.record_interaction("summarize", None, Some(&args.namespace));
150 commands::summarize::run(args)
151 }
152 Commands::Init => {
153 profile.record_interaction("init", None, None);
154 commands::init::run()
155 }
156 Commands::Hook(args) => {
157 profile.record_interaction("hook", None, None);
158 commands::hook::run(args)
159 }
160 Commands::Diff(args) => {
161 profile.record_interaction("diff", None, Some(&args.namespace));
162 commands::diff::run(args)
163 }
164 Commands::Shortcuts(args) => {
165 profile.record_interaction("shortcuts", None, None);
166 commands::shortcuts::run(args)
167 }
168 Commands::RebaseHeal(args) => {
169 profile.record_interaction("rebase-heal", None, args.namespace.as_deref());
170 commands::rebase_heal::run(args)
171 }
172 Commands::Check(args) => {
173 profile.record_interaction("check", None, args.namespace.as_deref());
174 commands::check::run(args)
175 }
176 Commands::Verify(args) => {
177 profile.record_interaction("verify", None, args.namespace.as_deref());
178 commands::verify::run(args)
179 }
180 Commands::Completions(args) => commands::completions::run(args),
181 };
182
183 let is_json = match &cli.command {
184 Commands::List(a) => a.json,
185 Commands::Check(a) => a.json,
186 Commands::Show(a) => a.json,
187 _ => false,
188 };
189
190 if !is_json {
191 if let Some(tip) = profile.suggest_next_action(None) {
192 println!("{}", tip);
193 }
194 }
195
196 result
197}