Skip to content

Commit e078072

Browse files
committed
add completions
1 parent 97df48b commit e078072

File tree

3 files changed

+53
-38
lines changed

3 files changed

+53
-38
lines changed

src/main.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
use std::{env, fs::canonicalize};
33

44
use anyhow::{Context, Result, anyhow, bail, ensure};
5-
use clap::{Parser, Subcommand};
5+
use clap::{CommandFactory, Parser, Subcommand};
6+
use clap_complete::{Shell, generate};
67
use colored::Colorize;
78
use git::{after_text, git_checkout_main, git_fetch, git_trunk, run_git_status};
89
use state::{Branch, RestackStep, StackMethod};
@@ -142,6 +143,12 @@ enum Command {
142143
#[command(subcommand)]
143144
action: CacheAction,
144145
},
146+
/// Generate shell completions.
147+
Completions {
148+
/// Shell to generate completions for.
149+
#[arg(value_enum)]
150+
shell: Shell,
151+
},
145152
/// Sync local git-stack state with GitHub PRs.
146153
/// Default: weak push then weak pull (bidirectional sync).
147154
Sync {
@@ -260,6 +267,13 @@ fn inner_main() -> Result<()> {
260267
unsafe { std::env::set_var("GIT_STACK_BENCHMARK_JSON", "1") };
261268
}
262269

270+
// Handle completions early (doesn't require git repo)
271+
if let Some(Command::Completions { shell }) = args.command {
272+
let mut cmd = Args::command();
273+
generate(shell, &mut cmd, "git-stack", &mut std::io::stdout());
274+
return Ok(());
275+
}
276+
263277
let repo = canonicalize(
264278
run_git(&["rev-parse", "--show-toplevel"])?.output_or("No git directory found")?,
265279
)?
@@ -398,6 +412,7 @@ fn inner_main() -> Result<()> {
398412
};
399413
sync::sync(&git_repo, &mut state, &repo, options)
400414
}
415+
Some(Command::Completions { .. }) => unreachable!("handled above"),
401416
None => {
402417
state.try_auto_mount(&git_repo, &repo, &current_branch)?;
403418
status(

src/state.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -632,12 +632,13 @@ impl State {
632632
let trunk = self.ensure_trunk(git_repo, repo);
633633

634634
if let Some(ref trunk) = trunk
635-
&& trunk.main_branch == branch_name {
636-
bail!(
637-
"Branch {branch_name} cannot be stacked on anything else.",
638-
branch_name = branch_name.red()
639-
);
640-
}
635+
&& trunk.main_branch == branch_name
636+
{
637+
bail!(
638+
"Branch {branch_name} cannot be stacked on anything else.",
639+
branch_name = branch_name.red()
640+
);
641+
}
641642

642643
let parent_branch = parent_branch
643644
.or_else(|| trunk.map(|t| t.main_branch))

src/tui/app.rs

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -272,37 +272,36 @@ fn render_branch_item(branch: &RenderableBranch, verbose: bool) -> ListItem<'sta
272272
}
273273

274274
// PR info (non-verbose mode)
275-
if !verbose
276-
&& let Some(ref pr) = branch.pr_info {
277-
let state_color = match pr.state {
278-
PrDisplayState::Draft => apply_dim(theme::GRAY, dim),
279-
PrDisplayState::Open => apply_dim(theme::GREEN, dim),
280-
PrDisplayState::Merged => apply_dim(theme::PURPLE, dim),
281-
PrDisplayState::Closed => apply_dim(theme::RED, dim),
282-
};
283-
284-
let author_rgb = string_to_color(&pr.author);
285-
let author_color = apply_dim(author_rgb, dim);
286-
287-
spans.push(Span::styled(
288-
" ",
289-
Style::default().fg(apply_dim(theme::PR_ARROW, dim)),
290-
));
291-
spans.push(Span::styled(
292-
format!("@{}", pr.author),
293-
Style::default().fg(author_color),
294-
));
295-
spans.push(Span::raw(" "));
296-
spans.push(Span::styled(
297-
format!("#{}", pr.number),
298-
Style::default().fg(apply_dim(theme::PR_NUMBER, dim)),
299-
));
300-
spans.push(Span::raw(" "));
301-
spans.push(Span::styled(
302-
format!("[{}]", pr.state),
303-
Style::default().fg(state_color),
304-
));
305-
}
275+
if !verbose && let Some(ref pr) = branch.pr_info {
276+
let state_color = match pr.state {
277+
PrDisplayState::Draft => apply_dim(theme::GRAY, dim),
278+
PrDisplayState::Open => apply_dim(theme::GREEN, dim),
279+
PrDisplayState::Merged => apply_dim(theme::PURPLE, dim),
280+
PrDisplayState::Closed => apply_dim(theme::RED, dim),
281+
};
282+
283+
let author_rgb = string_to_color(&pr.author);
284+
let author_color = apply_dim(author_rgb, dim);
285+
286+
spans.push(Span::styled(
287+
" ",
288+
Style::default().fg(apply_dim(theme::PR_ARROW, dim)),
289+
));
290+
spans.push(Span::styled(
291+
format!("@{}", pr.author),
292+
Style::default().fg(author_color),
293+
));
294+
spans.push(Span::raw(" "));
295+
spans.push(Span::styled(
296+
format!("#{}", pr.number),
297+
Style::default().fg(apply_dim(theme::PR_NUMBER, dim)),
298+
));
299+
spans.push(Span::raw(" "));
300+
spans.push(Span::styled(
301+
format!("[{}]", pr.state),
302+
Style::default().fg(state_color),
303+
));
304+
}
306305

307306
ListItem::new(Line::from(spans))
308307
}

0 commit comments

Comments
 (0)