feat: use enum_dispatch for command dispatch and add Open command
Replace manual dynamic dispatch using Box <dyn Runnable> with enum_dispatch for improved performance and cleaner code. Add a new Open command to allow opening the TUI as the default behavior when no subcommand is provided. Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
This commit is contained in:
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -339,6 +339,18 @@ version = "1.15.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum_dispatch"
|
||||||
|
version = "0.3.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -494,6 +506,7 @@ dependencies = [
|
|||||||
"crossterm",
|
"crossterm",
|
||||||
"csv",
|
"csv",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"enum_dispatch",
|
||||||
"flate2",
|
"flate2",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"proptest",
|
"proptest",
|
||||||
|
|||||||
@ -23,6 +23,7 @@ unicode-width = "0.2"
|
|||||||
dirs = "5"
|
dirs = "5"
|
||||||
csv = "1"
|
csv = "1"
|
||||||
clap = { version = "4.6.0", features = ["derive"] }
|
clap = { version = "4.6.0", features = ["derive"] }
|
||||||
|
enum_dispatch = "0.3.13"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
proptest = "1"
|
proptest = "1"
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
pkgs.pkg-config
|
pkgs.pkg-config
|
||||||
pkgs.rust-analyzer
|
pkgs.rust-analyzer
|
||||||
crate2nix.packages.${system}.default
|
crate2nix.packages.${system}.default
|
||||||
|
pkgs.cargo-expand
|
||||||
];
|
];
|
||||||
RUST_BACKTRACE = "1";
|
RUST_BACKTRACE = "1";
|
||||||
};
|
};
|
||||||
|
|||||||
37
src/main.rs
37
src/main.rs
@ -14,6 +14,7 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use enum_dispatch::enum_dispatch;
|
||||||
|
|
||||||
use draw::run_tui;
|
use draw::run_tui;
|
||||||
use model::Model;
|
use model::Model;
|
||||||
@ -29,7 +30,13 @@ struct Cli {
|
|||||||
command: Option<Commands>,
|
command: Option<Commands>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[enum_dispatch]
|
||||||
|
trait Runnable {
|
||||||
|
fn run(self, model_file: Option<PathBuf>) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
|
#[enum_dispatch(Runnable)]
|
||||||
enum Commands {
|
enum Commands {
|
||||||
/// Import JSON or CSV data, then open TUI (or save with --output)
|
/// Import JSON or CSV data, then open TUI (or save with --output)
|
||||||
Import(ImportArgs),
|
Import(ImportArgs),
|
||||||
@ -37,6 +44,8 @@ enum Commands {
|
|||||||
Cmd(CmdArgs),
|
Cmd(CmdArgs),
|
||||||
/// Run commands from a script file headless
|
/// Run commands from a script file headless
|
||||||
Script(ScriptArgs),
|
Script(ScriptArgs),
|
||||||
|
/// Open the TUI (default when no subcommand given)
|
||||||
|
Open(OpenTui),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
@ -105,23 +114,10 @@ struct ScriptArgs {
|
|||||||
file: Option<PathBuf>,
|
file: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Runnable {
|
#[derive(clap::Args)]
|
||||||
fn run(self: Box<Self>, model_file: Option<PathBuf>) -> Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Commands> for Box<dyn Runnable> {
|
|
||||||
fn from(cmd: Commands) -> Self {
|
|
||||||
match cmd {
|
|
||||||
Commands::Import(args) => Box::new(args),
|
|
||||||
Commands::Cmd(args) => Box::new(args),
|
|
||||||
Commands::Script(args) => Box::new(args),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OpenTui;
|
struct OpenTui;
|
||||||
impl Runnable for OpenTui {
|
impl Runnable for OpenTui {
|
||||||
fn run(self: Box<Self>, model_file: Option<PathBuf>) -> Result<()> {
|
fn run(self, model_file: Option<PathBuf>) -> Result<()> {
|
||||||
let model = get_initial_model(&model_file)?;
|
let model = get_initial_model(&model_file)?;
|
||||||
run_tui(model, model_file, None)
|
run_tui(model, model_file, None)
|
||||||
}
|
}
|
||||||
@ -129,15 +125,12 @@ impl Runnable for OpenTui {
|
|||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let cmd: Box<dyn Runnable> = cli
|
let cmd = cli.command.unwrap_or(Commands::Open(OpenTui));
|
||||||
.command
|
|
||||||
.map(|c| -> Box<dyn Runnable> { c.into() })
|
|
||||||
.unwrap_or_else(|| Box::new(OpenTui));
|
|
||||||
cmd.run(cli.file)
|
cmd.run(cli.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Runnable for ImportArgs {
|
impl Runnable for ImportArgs {
|
||||||
fn run(self: Box<Self>, model_file: Option<PathBuf>) -> Result<()> {
|
fn run(self, model_file: Option<PathBuf>) -> Result<()> {
|
||||||
if self.files.is_empty() {
|
if self.files.is_empty() {
|
||||||
anyhow::bail!("No files specified for import");
|
anyhow::bail!("No files specified for import");
|
||||||
}
|
}
|
||||||
@ -164,13 +157,13 @@ impl Runnable for ImportArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Runnable for CmdArgs {
|
impl Runnable for CmdArgs {
|
||||||
fn run(self: Box<Self>, _model_file: Option<PathBuf>) -> Result<()> {
|
fn run(self, _model_file: Option<PathBuf>) -> Result<()> {
|
||||||
run_headless_commands(&self.json, &self.file)
|
run_headless_commands(&self.json, &self.file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Runnable for ScriptArgs {
|
impl Runnable for ScriptArgs {
|
||||||
fn run(self: Box<Self>, _model_file: Option<PathBuf>) -> Result<()> {
|
fn run(self, _model_file: Option<PathBuf>) -> Result<()> {
|
||||||
run_headless_script(&self.path, &self.file)
|
run_headless_script(&self.path, &self.file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user