Skip to content

Commit a493b67

Browse files
committed
feat: add subcommand to generate shell completions
Use `clarinet completions <shell>` to generate the completions file for the specified shell. Supported shells are bash, elvish, fish, powershell, and zsh. Resolves #146
1 parent 8f18182 commit a493b67

File tree

3 files changed

+99
-47
lines changed

3 files changed

+99
-47
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ winapi = "0.3.9"
1717
winres = "0.1.11"
1818

1919
[dependencies]
20-
clap = { version = "=3.0.0-beta.4", optional = true }
20+
clap = { version = "3.0.14", features = ["derive"], optional = true }
21+
clap_generate = { version = "3.0.3", optional = true }
2122
toml = { version = "0.5.6", features = ["preserve_order"] }
2223
serde = "1"
2324
serde_json = "1"
@@ -96,7 +97,7 @@ path = "src/bin.rs"
9697

9798
[features]
9899
default = ["cli", "telemetry"]
99-
cli = ["swc_common", "deno", "deno_runtime", "deno_core", "clap", "tower-lsp"]
100+
cli = ["swc_common", "deno", "deno_runtime", "deno_core", "clap", "clap_generate", "tower-lsp"]
100101
telemetry = ["segment", "mac_address"]
101102

102103
[workspace]

src/frontend/cli.rs

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,64 +19,69 @@ use clarity_repl::clarity::costs::LimitedCostTracker;
1919
use clarity_repl::clarity::types::QualifiedContractIdentifier;
2020
use clarity_repl::{analysis, repl};
2121

22-
use clap::Clap;
22+
use clap::{IntoApp, Parser, Subcommand};
23+
use clap_generate::{Generator, Shell};
2324
use toml;
2425

2526
#[cfg(feature = "telemetry")]
2627
use super::telemetry::{telemetry_report_event, DeveloperUsageDigest, DeveloperUsageEvent};
2728

28-
#[derive(Clap, PartialEq, Clone, Debug)]
29-
#[clap(version = option_env!("CARGO_PKG_VERSION").expect("Unable to detect version"))]
29+
#[derive(Parser, PartialEq, Clone, Debug)]
30+
#[clap(version = option_env!("CARGO_PKG_VERSION").expect("Unable to detect version"), bin_name = "clarinet")]
3031
struct Opts {
3132
#[clap(subcommand)]
3233
command: Command,
3334
}
3435

35-
#[derive(Clap, PartialEq, Clone, Debug)]
36+
#[derive(Subcommand, PartialEq, Clone, Debug)]
3637
enum Command {
3738
/// Create and scaffold a new project
38-
#[clap(name = "new")]
39+
#[clap(name = "new", bin_name = "new")]
3940
New(GenerateProject),
4041
/// Subcommands for working with contracts
4142
#[clap(subcommand, name = "contract")]
4243
Contract(Contract),
4344
/// Load contracts in a REPL for an interactive session
44-
#[clap(name = "console", aliases = &["poke"])]
45+
#[clap(name = "console", aliases = &["poke"], bin_name = "console")]
4546
Console(Console),
4647
/// Execute test suite
47-
#[clap(name = "test")]
48+
#[clap(name = "test", bin_name = "test")]
4849
Test(Test),
4950
/// Check syntax of your contracts
50-
#[clap(name = "check")]
51+
#[clap(name = "check", bin_name = "check")]
5152
Check(Check),
5253
/// Publish contracts on chain
53-
#[clap(name = "publish")]
54+
#[clap(name = "publish", bin_name = "publish")]
5455
Publish(Publish),
5556
/// Execute Clarinet extension
56-
#[clap(name = "run")]
57+
#[clap(name = "run", bin_name = "run")]
5758
Run(Run),
5859
/// Start devnet environment for integration testing
59-
#[clap(name = "integrate")]
60+
#[clap(name = "integrate", bin_name = "integrate")]
6061
Integrate(Integrate),
6162
/// Start an LSP server (for integration with editors)
62-
#[clap(name = "lsp")]
63+
#[clap(name = "lsp", bin_name = "lsp")]
6364
LSP,
65+
/// Generate shell completions scripts
66+
#[clap(name = "completions", bin_name = "completions")]
67+
Completions(Completions),
6468
}
6569

66-
#[derive(Clap, PartialEq, Clone, Debug)]
70+
#[derive(Subcommand, PartialEq, Clone, Debug)]
71+
#[clap(bin_name = "contract")]
6772
enum Contract {
6873
/// Generate files and settings for a new contract
69-
#[clap(name = "new")]
74+
#[clap(name = "new", bin_name = "new")]
7075
NewContract(NewContract),
7176
/// Add third-party requirements to this project
72-
#[clap(name = "requirement")]
77+
#[clap(name = "requirement", bin_name = "requirement")]
7378
Requirement(Requirement),
7479
/// Replicate a third-party contract into this project
75-
#[clap(name = "fork")]
80+
#[clap(name = "fork", bin_name = "fork")]
7681
ForkContract(ForkContract),
7782
}
7883

79-
#[derive(Clap, PartialEq, Clone, Debug)]
84+
#[derive(Parser, PartialEq, Clone, Debug)]
8085
struct GenerateProject {
8186
/// Project's name
8287
pub name: String,
@@ -85,7 +90,7 @@ struct GenerateProject {
8590
pub disable_telemetry: bool,
8691
}
8792

88-
#[derive(Clap, PartialEq, Clone, Debug)]
93+
#[derive(Parser, PartialEq, Clone, Debug)]
8994
struct NewContract {
9095
/// Contract's name
9196
pub name: String,
@@ -94,7 +99,7 @@ struct NewContract {
9499
pub manifest_path: Option<String>,
95100
}
96101

97-
#[derive(Clap, PartialEq, Clone, Debug)]
102+
#[derive(Parser, PartialEq, Clone, Debug)]
98103
struct Requirement {
99104
/// Contract id (ex. " SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait")
100105
pub contract_id: String,
@@ -103,7 +108,7 @@ struct Requirement {
103108
pub manifest_path: Option<String>,
104109
}
105110

106-
#[derive(Clap, PartialEq, Clone, Debug)]
111+
#[derive(Parser, PartialEq, Clone, Debug)]
107112
struct ForkContract {
108113
/// Contract id (ex. " SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait")
109114
pub contract_id: String,
@@ -115,14 +120,14 @@ struct ForkContract {
115120
// pub recursive: bool,
116121
}
117122

118-
#[derive(Clap, PartialEq, Clone, Debug)]
123+
#[derive(Parser, PartialEq, Clone, Debug)]
119124
struct Console {
120125
/// Path to Clarinet.toml
121126
#[clap(long = "manifest-path")]
122127
pub manifest_path: Option<String>,
123128
}
124129

125-
#[derive(Clap, PartialEq, Clone, Debug)]
130+
#[derive(Parser, PartialEq, Clone, Debug)]
126131
struct Integrate {
127132
/// Path to Clarinet.toml
128133
#[clap(long = "manifest-path")]
@@ -132,7 +137,7 @@ struct Integrate {
132137
pub no_dashboard: bool,
133138
}
134139

135-
#[derive(Clap, PartialEq, Clone, Debug)]
140+
#[derive(Parser, PartialEq, Clone, Debug)]
136141
struct Test {
137142
/// Generate coverage file (coverage.lcov)
138143
#[clap(long = "coverage")]
@@ -150,7 +155,7 @@ struct Test {
150155
pub files: Vec<String>,
151156
}
152157

153-
#[derive(Clap, PartialEq, Clone, Debug)]
158+
#[derive(Parser, PartialEq, Clone, Debug)]
154159
struct Run {
155160
/// Script to run
156161
pub script: String,
@@ -169,7 +174,7 @@ struct Run {
169174
pub allow_disk_read: bool,
170175
}
171176

172-
#[derive(Clap, PartialEq, Clone, Debug)]
177+
#[derive(Parser, PartialEq, Clone, Debug)]
173178
struct Publish {
174179
/// Deploy contracts on devnet, using settings/Devnet.toml
175180
#[clap(
@@ -197,7 +202,7 @@ struct Publish {
197202
pub manifest_path: Option<String>,
198203
}
199204

200-
#[derive(Clap, PartialEq, Clone, Debug)]
205+
#[derive(Parser, PartialEq, Clone, Debug)]
201206
struct Check {
202207
/// Path to Clarinet.toml
203208
#[clap(long = "manifest-path")]
@@ -206,6 +211,13 @@ struct Check {
206211
pub file: Option<String>,
207212
}
208213

214+
#[derive(Parser, PartialEq, Clone, Debug)]
215+
struct Completions {
216+
/// Specify which shell to generation completions script for
217+
#[clap(arg_enum, ignore_case = true)]
218+
pub shell: Shell,
219+
}
220+
209221
pub fn main() {
210222
let opts: Opts = match Opts::try_parse() {
211223
Ok(opts) => opts,
@@ -610,6 +622,20 @@ pub fn main() {
610622
}
611623
}
612624
Command::LSP => run_lsp(),
625+
Command::Completions(cmd) => {
626+
let mut app = Opts::command();
627+
let file_name = cmd.shell.file_name("clarinet");
628+
let mut file = match File::create(file_name.clone()) {
629+
Ok(file) => file,
630+
Err(e) => {
631+
println!("error creating {}: {}", file_name, e);
632+
return;
633+
}
634+
};
635+
cmd.shell.generate(&mut app, &mut file);
636+
println!("generated: {}", file_name.clone());
637+
println!("Check your shell's documentation for details about using this file to enable completions for clarinet");
638+
}
613639
};
614640
}
615641

0 commit comments

Comments
 (0)