mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
chore: release 0.1.0
This commit is contained in:
commit
54a12e8178
12 changed files with 475 additions and 0 deletions
38
.github/workflows/ci.yaml
vendored
Normal file
38
.github/workflows/ci.yaml
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
name: CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
build: [stable, beta, nightly]
|
||||
include:
|
||||
- build: stable
|
||||
os: ubuntu-latest
|
||||
rust: stable
|
||||
- build: beta
|
||||
os: ubuntu-latest
|
||||
rust: beta
|
||||
- build: nightly
|
||||
os: ubuntu-latest
|
||||
rust: nightly
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Install Rust (rustup)
|
||||
run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }}
|
||||
shell: bash
|
||||
- run: cargo build --examples -v --workspace
|
||||
- run: cargo doc -v --workspace
|
||||
- run: cargo test -v --workspace
|
||||
- run: cargo clean
|
||||
|
||||
rustfmt:
|
||||
name: Rustfmt
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Install Rust
|
||||
run: rustup update stable && rustup default stable && rustup component add rustfmt
|
||||
- run: cargo fmt -- --check
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/Cargo.lock
|
26
Cargo.toml
Normal file
26
Cargo.toml
Normal file
|
@ -0,0 +1,26 @@
|
|||
[package]
|
||||
name = "clap_complete_nushell"
|
||||
authors = [ "nibon7 <nibon7@163.com>" ]
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "A generator library used with clap for Nushell completion scripts"
|
||||
repository = "https://github.com/nibon7/clap_complete_nushell"
|
||||
readme = "./README.md"
|
||||
categories = ["command-line-interface"]
|
||||
keywords = [
|
||||
"clap",
|
||||
"cli",
|
||||
"completion",
|
||||
"nushell"
|
||||
]
|
||||
exclude = [ "tests/*" ]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.0", default-features = false }
|
||||
clap_complete = "4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
snapbox = { version = "0.4", features = ["diff"] }
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 nibon7 <nibon7@163.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
97
README.md
Normal file
97
README.md
Normal file
|
@ -0,0 +1,97 @@
|
|||
# clap_complete_nushell
|
||||
|
||||
Generates [Nushell](https://github.com/nushell/nushell) completions for [`clap`](https://github.com/clap-rs/clap) based CLIs
|
||||
|
||||
## Examples
|
||||
|
||||
### myapp.rs
|
||||
|
||||
```rust
|
||||
use clap::{Arg, ArgAction, Command};
|
||||
use clap_complete::generate;
|
||||
use clap_complete_nushell::Nushell;
|
||||
use std::io;
|
||||
|
||||
fn main() {
|
||||
let mut cmd = Command::new("myapp")
|
||||
.version("3.0")
|
||||
.propagate_version(true)
|
||||
.about("Tests completions")
|
||||
.arg(
|
||||
Arg::new("file")
|
||||
.value_hint(clap::ValueHint::FilePath)
|
||||
.help("some input file"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("config")
|
||||
.action(ArgAction::Count)
|
||||
.help("some config file")
|
||||
.short('c')
|
||||
.visible_short_alias('C')
|
||||
.long("config")
|
||||
.visible_alias("conf"),
|
||||
)
|
||||
.arg(Arg::new("choice").value_parser(["first", "second"]))
|
||||
.subcommand(
|
||||
Command::new("test").about("tests things").arg(
|
||||
Arg::new("case")
|
||||
.long("case")
|
||||
.action(ArgAction::Set)
|
||||
.help("the case to test"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
Command::new("some_cmd")
|
||||
.about("top level subcommand")
|
||||
.subcommand(
|
||||
Command::new("sub_cmd").about("sub-subcommand").arg(
|
||||
Arg::new("config")
|
||||
.long("config")
|
||||
.action(ArgAction::Set)
|
||||
.value_parser([clap::builder::PossibleValue::new(
|
||||
"Lest quotes aren't escaped.",
|
||||
)])
|
||||
.help("the other case to test"),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
generate(Nushell, &mut cmd, "myapp", &mut io::stdout());
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### myapp.nu
|
||||
|
||||
```nu
|
||||
module completions {
|
||||
|
||||
# Tests completions
|
||||
export extern myapp [
|
||||
file?: string # some input file
|
||||
--config(-c) # some config file
|
||||
choice?: string
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
# tests things
|
||||
export extern "myapp test" [
|
||||
--case: string # the case to test
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
# top level subcommand
|
||||
export extern "myapp some_cmd" [
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
# sub-subcommand
|
||||
export extern "myapp some_cmd sub_cmd" [
|
||||
--config: string # the other case to test
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
use completions *
|
||||
```
|
12
examples/nushell_completion.rs
Normal file
12
examples/nushell_completion.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use clap::Command;
|
||||
use clap_complete::generate;
|
||||
use clap_complete_nushell::Nushell;
|
||||
use std::io;
|
||||
|
||||
fn main() {
|
||||
let mut cmd = Command::new("myapp")
|
||||
.subcommand(Command::new("test").subcommand(Command::new("config")))
|
||||
.subcommand(Command::new("hello"));
|
||||
|
||||
generate(Nushell, &mut cmd, "myapp", &mut io::stdout());
|
||||
}
|
95
src/lib.rs
Normal file
95
src/lib.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
//! Generates [Nushell](https://github.com/nushell/nushell) completions for [`clap`](https://github.com/clap-rs/clap) based CLIs
|
||||
|
||||
use clap::Command;
|
||||
use clap_complete::Generator;
|
||||
|
||||
/// Generate Nushell complete file
|
||||
pub struct Nushell;
|
||||
|
||||
impl Generator for Nushell {
|
||||
fn file_name(&self, name: &str) -> String {
|
||||
format!("{}.nu", name)
|
||||
}
|
||||
|
||||
fn generate(&self, cmd: &Command, buf: &mut dyn std::io::Write) {
|
||||
let mut completions = String::new();
|
||||
|
||||
completions.push_str("module completions {\n\n");
|
||||
|
||||
generate_completion(&mut completions, cmd, false);
|
||||
|
||||
for sub in cmd.get_subcommands() {
|
||||
generate_completion(&mut completions, sub, true);
|
||||
}
|
||||
|
||||
completions.push_str("}\n\n");
|
||||
completions.push_str("use completions *\n");
|
||||
|
||||
buf.write_all(completions.as_bytes())
|
||||
.expect("Failed to write to generated file")
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_completion(completions: &mut String, cmd: &Command, is_subcommand: bool) {
|
||||
if let Some(about) = cmd.get_about() {
|
||||
completions.push_str(format!(" # {}\n", about).as_str());
|
||||
}
|
||||
|
||||
let bin_name = cmd.get_bin_name().expect("Failed to get bin name");
|
||||
|
||||
if is_subcommand {
|
||||
completions.push_str(format!(" export extern \"{}\" [\n", bin_name).as_str());
|
||||
} else {
|
||||
completions.push_str(format!(" export extern {} [\n", bin_name).as_str());
|
||||
}
|
||||
|
||||
let mut s = String::new();
|
||||
for arg in cmd.get_arguments() {
|
||||
if arg.is_positional() {
|
||||
s.push_str(format!(" {}", arg.get_id()).as_str());
|
||||
if !arg.is_required_set() {
|
||||
s.push('?');
|
||||
}
|
||||
}
|
||||
|
||||
let long = arg.get_long();
|
||||
if let Some(opt) = long {
|
||||
s.push_str(format!(" --{}", opt).as_str());
|
||||
}
|
||||
|
||||
let short = arg.get_short();
|
||||
if let Some(opt) = short {
|
||||
if long.is_some() {
|
||||
s.push_str(format!("(-{})", opt).as_str());
|
||||
} else {
|
||||
s.push_str(format!(" -{}", opt).as_str());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(v) = arg.get_num_args() {
|
||||
if v.takes_values() {
|
||||
// TODO: add more types?
|
||||
// TODO: add possible values?
|
||||
s.push_str(": string");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(msg) = arg.get_help() {
|
||||
if arg.is_positional() || long.is_some() || short.is_some() {
|
||||
s.push_str(format!("\t# {}", msg).as_str());
|
||||
}
|
||||
}
|
||||
|
||||
s.push('\n');
|
||||
}
|
||||
|
||||
completions.push_str(&s);
|
||||
completions.push_str(" ]\n\n");
|
||||
|
||||
// For sub-subcommands
|
||||
if is_subcommand {
|
||||
for sub in cmd.get_subcommands() {
|
||||
generate_completion(completions, sub, true);
|
||||
}
|
||||
}
|
||||
}
|
82
tests/common.rs
Normal file
82
tests/common.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
use clap::{builder::PossibleValue, Arg, ArgAction, Command, ValueHint};
|
||||
|
||||
pub fn basic_command(name: &'static str) -> Command {
|
||||
Command::new(name)
|
||||
.arg(
|
||||
Arg::new("config")
|
||||
.short('c')
|
||||
.global(true)
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("v")
|
||||
.short('v')
|
||||
.conflicts_with("config")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.subcommand(
|
||||
Command::new("test")
|
||||
.about("Subcommand")
|
||||
.arg(Arg::new("debug").short('d').action(ArgAction::Count)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn feature_sample_command(name: &'static str) -> Command {
|
||||
Command::new(name)
|
||||
.version("3.0")
|
||||
.propagate_version(true)
|
||||
.about("Tests completions")
|
||||
.arg(
|
||||
Arg::new("file")
|
||||
.value_hint(ValueHint::FilePath)
|
||||
.help("some input file"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("config")
|
||||
.action(ArgAction::Count)
|
||||
.help("some config file")
|
||||
.short('c')
|
||||
.visible_short_alias('C')
|
||||
.long("config")
|
||||
.visible_alias("conf"),
|
||||
)
|
||||
.arg(Arg::new("choice").value_parser(["first", "second"]))
|
||||
.subcommand(
|
||||
Command::new("test").about("tests things").arg(
|
||||
Arg::new("case")
|
||||
.long("case")
|
||||
.action(ArgAction::Set)
|
||||
.help("the case to test"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn sub_subcommands_command(name: &'static str) -> Command {
|
||||
feature_sample_command(name).subcommand(
|
||||
Command::new("some_cmd")
|
||||
.about("top level subcommand")
|
||||
.subcommand(
|
||||
Command::new("sub_cmd").about("sub-subcommand").arg(
|
||||
Arg::new("config")
|
||||
.long("config")
|
||||
.action(ArgAction::Set)
|
||||
.value_parser([PossibleValue::new("Lest quotes aren't escaped.")])
|
||||
.help("the other case to test"),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn assert_matches_path(
|
||||
expected_path: impl AsRef<std::path::Path>,
|
||||
gen: impl clap_complete::Generator,
|
||||
mut cmd: Command,
|
||||
name: &'static str,
|
||||
) {
|
||||
let mut buf = vec![];
|
||||
clap_complete::generate(gen, &mut cmd, name, &mut buf);
|
||||
|
||||
snapbox::Assert::new()
|
||||
.action_env("SNAPSHOTS")
|
||||
.matches_path(expected_path, buf);
|
||||
}
|
37
tests/nushell.rs
Normal file
37
tests/nushell.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
mod common;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
let name = "my-app";
|
||||
let cmd = common::basic_command(name);
|
||||
common::assert_matches_path(
|
||||
"tests/snapshots/basic.nu",
|
||||
clap_complete_nushell::Nushell,
|
||||
cmd,
|
||||
name,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn feature_sample() {
|
||||
let name = "my-app";
|
||||
let cmd = common::feature_sample_command(name);
|
||||
common::assert_matches_path(
|
||||
"tests/snapshots/feature_sample.nu",
|
||||
clap_complete_nushell::Nushell,
|
||||
cmd,
|
||||
name,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sub_subcommands() {
|
||||
let name = "my-app";
|
||||
let cmd = common::sub_subcommands_command(name);
|
||||
common::assert_matches_path(
|
||||
"tests/snapshots/sub_subcommands.nu",
|
||||
clap_complete_nushell::Nushell,
|
||||
cmd,
|
||||
name,
|
||||
);
|
||||
}
|
16
tests/snapshots/basic.nu
Normal file
16
tests/snapshots/basic.nu
Normal file
|
@ -0,0 +1,16 @@
|
|||
module completions {
|
||||
|
||||
export extern my-app [
|
||||
-c
|
||||
-v
|
||||
]
|
||||
|
||||
# Subcommand
|
||||
export extern "my-app test" [
|
||||
-d
|
||||
-c
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
use completions *
|
19
tests/snapshots/feature_sample.nu
Normal file
19
tests/snapshots/feature_sample.nu
Normal file
|
@ -0,0 +1,19 @@
|
|||
module completions {
|
||||
|
||||
# Tests completions
|
||||
export extern my-app [
|
||||
file?: string # some input file
|
||||
--config(-c) # some config file
|
||||
choice?: string
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
# tests things
|
||||
export extern "my-app test" [
|
||||
--case: string # the case to test
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
use completions *
|
30
tests/snapshots/sub_subcommands.nu
Normal file
30
tests/snapshots/sub_subcommands.nu
Normal file
|
@ -0,0 +1,30 @@
|
|||
module completions {
|
||||
|
||||
# Tests completions
|
||||
export extern my-app [
|
||||
file?: string # some input file
|
||||
--config(-c) # some config file
|
||||
choice?: string
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
# tests things
|
||||
export extern "my-app test" [
|
||||
--case: string # the case to test
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
# top level subcommand
|
||||
export extern "my-app some_cmd" [
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
# sub-subcommand
|
||||
export extern "my-app some_cmd sub_cmd" [
|
||||
--config: string # the other case to test
|
||||
--version(-V) # Print version information
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
use completions *
|
Loading…
Reference in a new issue