Skip to content

Commit 1fa9654

Browse files
committed
feat: add pluginlab generate-completions
1 parent 970259f commit 1fa9654

File tree

4 files changed

+92
-8
lines changed

4 files changed

+92
-8
lines changed

Cargo.lock

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

crates/pluginlab/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ clap = { workspace = true }
2424
tokio = { workspace = true }
2525
anyhow = { workspace = true }
2626
reqwest = "0.12.20"
27+
clap_complete = "4.5"
2728

2829
[build-dependencies]
2930
wasmtime = { workspace = true }

crates/pluginlab/src/cli.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
use clap::Parser;
1+
use clap::{Parser, Subcommand, ValueEnum};
22
use std::path::PathBuf;
33

44
#[derive(Parser, Debug)]
55
#[command(author, version, about, long_about = None)]
66
pub struct Cli {
7+
#[command(subcommand)]
8+
pub command: Option<Commands>,
9+
710
/// Paths or URLs to WebAssembly plugin files
811
#[arg(long)]
912
pub plugins: Vec<String>,
1013

1114
/// Path or URL to WebAssembly REPL logic file
1215
#[arg(long)]
13-
pub repl_logic: String,
16+
pub repl_logic: Option<String>,
1417

1518
#[arg(long, default_value_t = false)]
1619
pub debug: bool,
@@ -46,3 +49,20 @@ pub struct Cli {
4649
)]
4750
pub allow_all: bool,
4851
}
52+
53+
#[derive(Subcommand, Debug)]
54+
pub enum Commands {
55+
/// Generate completions for your own shell (shipped with the homebrew version)
56+
GenerateCompletions {
57+
/// Specify which shell you target - accepted values: bash, fish, zsh
58+
#[arg(long, value_enum)]
59+
shell: AvailableShells,
60+
},
61+
}
62+
63+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
64+
pub enum AvailableShells {
65+
Bash,
66+
Fish,
67+
Zsh,
68+
}

crates/pluginlab/src/lib.rs

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,68 @@ pub(crate) use wasm_host::WasmHost;
1212
use anyhow::Result;
1313
use api::host_api::repl::api::transport;
1414
use clap::Parser;
15-
use cli::Cli;
15+
use cli::{Cli, Commands};
1616
use helpers::{StatusHandler, StdoutHandler};
1717
use std::io::Write;
1818

1919
/// Main entry point for the REPL application
2020
pub async fn run_async() -> Result<()> {
2121
// Parse command line arguments
2222
let cli = Cli::parse();
23+
24+
// Handle subcommands first
25+
if let Some(command) = &cli.command {
26+
match command {
27+
Commands::GenerateCompletions { shell } => {
28+
return handle_generate_completions(*shell);
29+
}
30+
}
31+
}
32+
33+
// For REPL mode, repl_logic is required
34+
let repl_logic = cli
35+
.repl_logic
36+
.ok_or_else(|| anyhow::anyhow!("--repl-logic is required when running in REPL mode"))?;
37+
2338
let debug = cli.debug;
39+
let plugins = cli.plugins;
40+
let dir = cli.dir;
41+
let allow_net = cli.allow_net;
42+
let allow_read = cli.allow_read;
43+
let allow_write = cli.allow_write;
44+
let allow_all = cli.allow_all;
45+
46+
// Create a new CLI struct for the remaining operations
47+
let repl_cli = Cli {
48+
command: None,
49+
plugins,
50+
repl_logic: Some(repl_logic.clone()),
51+
debug,
52+
dir,
53+
allow_net,
54+
allow_read,
55+
allow_write,
56+
allow_all,
57+
};
58+
2459
println!("[Host] Starting REPL host...");
2560

2661
// Create a WASI context for the host
2762
// Binding stdio, args, env, preopened dir ...
28-
let wasi_ctx = WasmEngine::build_wasi_ctx(&cli)?;
63+
let wasi_ctx = WasmEngine::build_wasi_ctx(&repl_cli)?;
2964

3065
// Create the WebAssembly engine
3166
let engine = WasmEngine::new()?;
3267

3368
// Create the host
34-
let mut host = WasmHost::new(&engine, wasi_ctx, &cli);
69+
let mut host = WasmHost::new(&engine, wasi_ctx, &repl_cli);
3570

36-
println!("[Host] Loading REPL logic from: {}", cli.repl_logic);
71+
println!("[Host] Loading REPL logic from: {}", repl_logic);
3772
// Override the REPL logic in the binary with the one passed by params
38-
host.load_repl_logic(&engine, &cli.repl_logic).await?;
73+
host.load_repl_logic(&engine, &repl_logic).await?;
3974

4075
// Load plugins
41-
for plugin_source in &cli.plugins {
76+
for plugin_source in &repl_cli.plugins {
4277
println!("[Host] Loading plugin: {}", plugin_source);
4378
host.load_plugin(&engine, plugin_source).await?;
4479
}
@@ -216,3 +251,21 @@ pub async fn run_async() -> Result<()> {
216251
}
217252
}
218253
}
254+
255+
/// Handle the generate-completions subcommand
256+
fn handle_generate_completions(shell: cli::AvailableShells) -> Result<()> {
257+
use clap::CommandFactory;
258+
use clap_complete::{generate, Shell};
259+
use cli::Cli;
260+
261+
let mut cmd = Cli::command();
262+
let shell_type = match shell {
263+
cli::AvailableShells::Bash => Shell::Bash,
264+
cli::AvailableShells::Fish => Shell::Fish,
265+
cli::AvailableShells::Zsh => Shell::Zsh,
266+
};
267+
268+
generate(shell_type, &mut cmd, "pluginlab", &mut std::io::stdout());
269+
270+
Ok(())
271+
}

0 commit comments

Comments
 (0)