Skip to content

Commit 2706a13

Browse files
committed
Update to clap 4.0
The required code changes are mostly using Arg.num_args(), removing lifetimes, and updating indentation for usage overrides. The user-facing differences are that help formatting and coloring are significantly different.
1 parent 6e9bdd5 commit 2706a13

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+356
-373
lines changed

Cargo.lock

Lines changed: 4 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ anyhow = "1.0"
2121
atty = "0.2"
2222
bstr = { version = "1.0", default-features = false, features = ["std"] }
2323
chrono = { version = "0.4", default-features = false, features = ["clock"] }
24-
clap = { version = "3.2", default-features = false, features = ["color", "std", "suggestions", "wrap_help"] }
24+
clap = { version = "4.0", default-features = false, features = ["color", "help", "std", "string", "suggestions", "usage", "wrap_help"] }
2525
ctrlc = "3.2"
2626
encoding_rs = "0.8"
2727
git2 = { version = "0.15", default-features = false }

src/alias.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,18 @@ impl Alias {
4747
}
4848

4949
/// Make [`clap::Command`] for the alias.
50-
pub(crate) fn make(&self) -> clap::Command<'static> {
50+
pub(crate) fn make(&self) -> clap::Command {
5151
let about = match self.kind {
5252
AliasKind::StGit => format!("Alias for `stg {}`", &self.command),
5353
AliasKind::Shell => format!("Alias for shell command `{}`", &self.command),
5454
};
55-
// TODO: future versions of clap may allow about argument to be something other
56-
// than Into<&'help str>, which could avoid having to do this leak trick.
57-
let about: &'static str = Box::leak(about.into_boxed_str());
58-
clap::Command::new(&self.name)
55+
clap::Command::new(self.name.clone())
5956
.about(about)
6057
.trailing_var_arg(true)
6158
.arg(
6259
clap::Arg::new("args")
6360
.help("Extra arguments to aliased command")
64-
.multiple_values(true)
61+
.num_args(1..)
6562
.allow_hyphen_values(true),
6663
)
6764
}

src/argset.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@
55
use clap::Arg;
66

77
/// The `--branch`/`-b` option for selecting an alternative branch.
8-
pub(crate) fn branch_arg() -> Arg<'static> {
8+
pub(crate) fn branch_arg() -> Arg {
99
Arg::new("branch")
1010
.long("branch")
1111
.short('b')
1212
.help("Use BRANCH instead of current branch")
13-
.takes_value(true)
13+
.num_args(1)
1414
.value_name("branch")
1515
.value_hint(clap::ValueHint::Other)
1616
.value_parser(parse_branch_name)
1717
}
1818

1919
/// The `--keep/-k` option.
20-
pub(crate) fn keep_arg() -> Arg<'static> {
20+
pub(crate) fn keep_arg() -> Arg {
2121
Arg::new("keep")
2222
.long("keep")
2323
.short('k')
@@ -26,7 +26,7 @@ pub(crate) fn keep_arg() -> Arg<'static> {
2626
}
2727

2828
/// The `--merged` option checking for already-merged patches before pushes.
29-
pub(crate) fn merged_arg() -> Arg<'static> {
29+
pub(crate) fn merged_arg() -> Arg {
3030
Arg::new("merged")
3131
.long("merged")
3232
.short('m')
@@ -35,12 +35,12 @@ pub(crate) fn merged_arg() -> Arg<'static> {
3535
}
3636

3737
/// The `--diff-opts`/`-O` option for pass-through to subordinate `git` processes.
38-
pub(crate) fn diff_opts_arg() -> Arg<'static> {
38+
pub(crate) fn diff_opts_arg() -> Arg {
3939
Arg::new("diff-opts")
4040
.long("diff-opts")
4141
.short('O')
4242
.help("Extra options to pass to \"git diff\"")
43-
.takes_value(true)
43+
.num_args(1)
4444
.allow_hyphen_values(true)
4545
.action(clap::ArgAction::Append)
4646
.value_name("options")

src/cmd/branch.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub(super) const STGIT_COMMAND: super::StGitCommand = super::StGitCommand {
2424
run,
2525
};
2626

27-
fn make() -> clap::Command<'static> {
27+
fn make() -> clap::Command {
2828
clap::Command::new(STGIT_COMMAND.name)
2929
.about("Branch operations: switch, list, create, rename, delete, ...")
3030
.long_about(
@@ -36,17 +36,17 @@ fn make() -> clap::Command<'static> {
3636
)
3737
.disable_help_subcommand(true)
3838
.override_usage(
39-
"stg branch\n \
40-
stg branch [--merge] <branch>\n \
41-
stg branch {--list,-l}\n \
42-
stg branch {--create,-c} <new-branch> [committish]\n \
43-
stg branch --clone [new-branch]\n \
44-
stg branch {--rename,-r} [old-name] <new-name>\n \
45-
stg branch {--protect,-p} [branch]\n \
46-
stg branch {--unprotect,-u} [branch]\n \
47-
stg branch --delete [--force] <branch>\n \
48-
stg branch --cleanup [--force] [branch]\n \
49-
stg branch {--describe,-d} <description> [branch]",
39+
"stg branch\
40+
\n stg branch [--merge] <branch>\
41+
\n stg branch {--list,-l}\
42+
\n stg branch {--create,-c} <new-branch> [committish]\
43+
\n stg branch --clone [new-branch]\
44+
\n stg branch {--rename,-r} [old-name] <new-name>\
45+
\n stg branch {--protect,-p} [branch]\
46+
\n stg branch {--unprotect,-u} [branch]\
47+
\n stg branch --delete [--force] <branch>\
48+
\n stg branch --cleanup [--force] [branch]\
49+
\n stg branch {--describe,-d} <description> [branch]",
5050
)
5151
.subcommand(
5252
clap::Command::new("--list")
@@ -115,9 +115,7 @@ fn make() -> clap::Command<'static> {
115115
.help("Optional name of branch to rename and new branch name")
116116
.hide_short_help(true)
117117
.required(true)
118-
.multiple_values(true)
119-
.min_values(1)
120-
.max_values(2)
118+
.num_args(1..=2)
121119
.value_parser(argset::parse_branch_name),
122120
),
123121
)

src/cmd/clean.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub(super) const STGIT_COMMAND: super::StGitCommand = super::StGitCommand {
2121
run,
2222
};
2323

24-
fn make() -> clap::Command<'static> {
24+
fn make() -> clap::Command {
2525
clap::Command::new(STGIT_COMMAND.name)
2626
.about("Delete empty patches from the series")
2727
.long_about(

src/cmd/commit.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub(super) const STGIT_COMMAND: super::StGitCommand = super::StGitCommand {
1919
run,
2020
};
2121

22-
fn make() -> clap::Command<'static> {
22+
fn make() -> clap::Command {
2323
clap::Command::new(STGIT_COMMAND.name)
2424
.about("Finalize patches to the stack base")
2525
.long_about(
@@ -37,17 +37,17 @@ fn make() -> clap::Command<'static> {
3737
all applied patches are committed.",
3838
)
3939
.override_usage(
40-
"stg commit [OPTIONS] [patch]...\n \
41-
stg commit [OPTIONS] -n <number>\n \
40+
"stg commit [OPTIONS] [patch]...\n \
41+
stg commit [OPTIONS] -n <number>\n \
4242
stg commit [OPTIONS] --all",
4343
)
4444
.arg(
4545
Arg::new("patchranges")
4646
.help("Patches to commit")
4747
.value_name("patch")
48-
.multiple_values(true)
48+
.num_args(1..)
4949
.value_parser(clap::value_parser!(patchrange::Specification))
50-
.conflicts_with_all(&["all", "number"]),
50+
.conflicts_with_all(["all", "number"]),
5151
)
5252
.arg(
5353
Arg::new("number")

src/cmd/completion/bash.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{format as f, path::PathBuf};
88

99
use super::shstream::ShStream;
1010

11-
pub(super) fn command() -> clap::Command<'static> {
11+
pub(super) fn command() -> clap::Command {
1212
clap::Command::new("bash")
1313
.about("Generate bash completion script")
1414
.arg(
@@ -139,11 +139,14 @@ fn write_command_func(script: &mut ShStream, fname: &str, command: &clap::Comman
139139

140140
let mut pos_index = 0;
141141
for arg in command.get_positionals() {
142+
let value_range = arg.get_num_args().expect("num_args is some for built arg");
143+
let num_vals = (value_range.max_values() > 1 && value_range.max_values() < usize::MAX)
144+
.then_some(value_range.max_values());
142145
script.ensure_blank_line();
143146
if matches!(arg.get_action(), clap::ArgAction::Append)
144-
|| (arg.is_multiple_values_set() && arg.get_value_delimiter() == Some(' '))
147+
|| (num_vals.is_some() && arg.get_value_delimiter() == Some(' '))
145148
{
146-
if let Some(num_vals) = arg.get_num_vals() {
149+
if let Some(num_vals) = num_vals {
147150
script.line(&f!(
148151
"if (( pos_index >= {pos_index} && pos_index < {})); then",
149152
pos_index + num_vals
@@ -167,7 +170,7 @@ fn write_command_func(script: &mut ShStream, fname: &str, command: &clap::Comman
167170
}
168171
script.dedent();
169172

170-
pos_index += 1 + arg.get_num_vals().unwrap_or(0);
173+
pos_index += 1 + num_vals.unwrap_or(0);
171174

172175
script.line("fi");
173176
}
@@ -191,7 +194,7 @@ fn write_command_func(script: &mut ShStream, fname: &str, command: &clap::Comman
191194

192195
/// Insert COMPREPLY line into script for given arg.
193196
fn insert_compreply(script: &mut ShStream, arg: &clap::Arg) {
194-
assert!(arg.is_takes_value_set());
197+
assert!(arg.get_num_args().unwrap().takes_values());
195198

196199
if let Some(possible_values) = arg.get_value_parser().possible_values() {
197200
let mut possible = ShStream::new();
@@ -205,7 +208,7 @@ fn insert_compreply(script: &mut ShStream, arg: &clap::Arg) {
205208
arg.get_value_hint(),
206209
clap::ValueHint::Unknown | clap::ValueHint::Other
207210
) {
208-
match arg.get_id() {
211+
match arg.get_id().as_str() {
209212
"branch" | "ref-branch" => {
210213
script.line("mapfile -t COMPREPLY < <(compgen -W \"$(_stg_branches)\" -- \"$cur\")")
211214
}
@@ -301,7 +304,11 @@ fn get_flags(command: &clap::Command) -> (ShStream, ShStream) {
301304
}
302305
if let Some(longs) = arg.get_long_and_visible_aliases() {
303306
for name in longs {
304-
if arg.is_takes_value_set() {
307+
if arg
308+
.get_num_args()
309+
.map(|value_range| value_range.takes_values())
310+
.unwrap_or(false)
311+
{
305312
long_flags.word(&f!("--{name}="));
306313
} else {
307314
long_flags.word(&f!("'--{name} '"));
@@ -400,10 +407,13 @@ fn get_options_pattern(command: &clap::Command) -> ShStream {
400407
fn get_cmd_flags_pattern(command: &clap::Command) -> ShStream {
401408
let mut flags = ShStream::new();
402409
flags.word_sep('|');
403-
for arg in command
404-
.get_arguments()
405-
.filter(|arg| !arg.is_positional() && !arg.is_takes_value_set())
406-
{
410+
for arg in command.get_arguments().filter(|arg| {
411+
!arg.is_positional()
412+
&& !arg
413+
.get_num_args()
414+
.expect("num_args is some for built arg")
415+
.takes_values()
416+
}) {
407417
flags.word(get_arg_flags_pattern(arg).as_ref());
408418
}
409419
flags

src/cmd/completion/fish.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{format as f, path::PathBuf};
88

99
use super::shstream::ShStream;
1010

11-
pub(super) fn command() -> clap::Command<'static> {
11+
pub(super) fn command() -> clap::Command {
1212
clap::Command::new("fish")
1313
.about("Generate fish shell completion script")
1414
.arg(
@@ -260,10 +260,15 @@ fn write_command_completions(
260260
script.end_line();
261261
}
262262

263-
for arg in command
264-
.get_arguments()
265-
.filter(|arg| !arg.is_positional() && !arg.is_takes_value_set() && !arg.is_hide_set())
266-
{
263+
// Flags
264+
for arg in command.get_arguments().filter(|arg| {
265+
!arg.is_positional()
266+
&& !arg
267+
.get_num_args()
268+
.expect("num_args is some for built arg")
269+
.takes_values()
270+
&& !arg.is_hide_set()
271+
}) {
267272
script.word(complete_common.as_ref());
268273
script.word(get_arg_flags_params(arg).as_ref());
269274
script.word(get_arg_help_param(arg).as_ref());
@@ -340,7 +345,7 @@ fn get_arg_flags_params(arg: &clap::Arg) -> ShStream {
340345
}
341346

342347
fn get_arg_completion_params(arg: &clap::Arg) -> ShStream {
343-
assert!(arg.is_takes_value_set());
348+
assert!(arg.get_num_args().unwrap().takes_values());
344349

345350
let mut params = ShStream::new();
346351

@@ -354,7 +359,7 @@ fn get_arg_completion_params(arg: &clap::Arg) -> ShStream {
354359
arg.get_value_hint(),
355360
clap::ValueHint::Unknown | clap::ValueHint::Other
356361
) {
357-
match arg.get_id() {
362+
match arg.get_id().as_str() {
358363
"branch" | "ref-branch" => params.word("-xa '(__fish_stg_stg_branches)'"),
359364
"branch-any" => params.word("-xa '(__fish_stg_all_branches)'"),
360365
"committish" => params.word("-xa '(__fish_stg_commit)'"),
@@ -397,6 +402,7 @@ fn get_arg_help_param(arg: &clap::Arg) -> ShStream {
397402
let help = arg
398403
.get_help()
399404
.unwrap_or_default()
405+
.to_string()
400406
.replace('\\', "\\\\")
401407
.replace('\'', "\\'");
402408
params.word(&f!("-d '{help}'"));

src/cmd/completion/list.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use anyhow::Result;
88

99
use crate::cmd::STGIT_COMMANDS;
1010

11-
pub(super) fn command() -> clap::Command<'static> {
11+
pub(super) fn command() -> clap::Command {
1212
clap::Command::new("list")
1313
.about("List StGit command information")
1414
.arg(
@@ -101,11 +101,11 @@ fn list_aliases(
101101
crate::alias::AliasKind::Shell => "!",
102102
crate::alias::AliasKind::StGit => "",
103103
};
104-
std::borrow::Cow::Owned(format!("{prefix}{expansion}"))
104+
format!("{prefix}{expansion}")
105105
} else {
106106
let mut cmd = alias.make();
107107
cmd.build();
108-
std::borrow::Cow::Borrowed(cmd.get_about().unwrap_or_default())
108+
cmd.get_about().unwrap_or_default().to_string()
109109
};
110110
match style {
111111
OutputStyle::NameOnly => writeln!(output, "{name}"),

0 commit comments

Comments
 (0)