Add the library to your Cargo.toml
:
[dependencies]
mod-cli = "0.6.3"
Add the library to your Cargo.toml
with features:
[dependencies]
mod-cli = { version = "0.6.3", features = ["plugins"] }
Feature |
Description |
internal-commands |
Enables built-in test/dev commands like ping , hello |
custom-commands |
Enables CLI custom command creation. |
json-loader |
Enables external command loading from JSON config |
plugins |
Enables plugin support for dynamic runtime command injection |
Basic Usage
use modcli::ModCli;
fn main() {
let args: Vec<String> = std::env::args().skip(1).collect();
let mut cli = ModCli::new();
cli.run(args);
}
Set a custom prefix
use modcli::ModCli;
fn main() {
let args: Vec<String> = std::env::args().skip(1).collect();
let mut cli = ModCli::new();
cli.set_prefix("myCLI");
cli.run(args);
}
Using named colors
let teal = colors::get("teal"); let demo = build()
.part("Color Demo:").space()
.part("Teal").color(teal).bold().get();
print::line(&demo, 0);
Using Gradients
Two-color gradient:
use modcli::output::{
gradient,
print,
RED, ORANGE
};
let gradient_text = gradient::two_color("Two color gradient", RED, ORANGE);
print::line(&gradient_text);
Three-color gradient:
use modcli::output::{
gradient,
print,
BLUE, GREEN, YELLOW
};
let gradient_text = gradient::three_color("Three color gradient", BLUE, GREEN, YELLOW);
print::line(&gradient_text);
Multi-color gradient:
use modcli::output::{
gradient,
print,
RED, ORANGE, YELLOW, GREEN, BLUE
};
let gradient_text = gradient::multi_color("Multi-color gradient", vec![RED, ORANGE, YELLOW, GREEN, BLUE]);
print::line(&gradient_text);
Using RGB with gradients:
use modcli::output::{
gradient,
print
};
let gradient_text = gradient::two_color(
"Gradient Output",
Color::Rgb { r: 255, g: 0, b: 0 },
Color::Rgb { r: 0, g: 0, b: 255 },
);
print::line(&gradient_text);
Output Styles
use modcli::output::{
print,
build,
BLUE
};
let testing = build()
.part("Testing")
.color(BLUE)
.bold()
.get();
print::line(&testing);
Multiple Styles:
use modcli::output::{
gradient,
print,
build,
BLUE, LIGHT_BLUE
};
let testing = build()
.part("Label:").color(BLUE).bold().space()
.part("This content has").space()
.part("multiple").color(LIGHT_BLUE).bold().space()
.part("styles").underline().space()
.part("and").italic().space()
.part("colors").underline().space()
.part("!")
.get();
print::line(&testing);
Style + Gradients:
use modcli::output::{
print,
build,
BLUE, GREEN
};
let gradient_text = gradient::two_color("Gradient Output", BLUE, GREEN);
let testing = build()
.part(&gradient_text).bold().space()
.part("+ Styled!")
.get();
print::line(&testing);
Progress Bar & Animated Loaders
Auto Progress:
use modcli::output::{
progress::{
show_progress_bar,
}
};
show_progress_bar("Testing", 45, 1500);
Displays
Label [#############################################] 100% Done!
Manual control:
use modcli::output::{
build,
progress::{
ProgressBar,
ProgressStyle,
},
LIGHT_BLUE
};
let label = build()
.part("Loading")
.color(LIGHT_BLUE)
.bold()
.get();
let mut bar = ProgressBar::new(30, ProgressStyle {
fill: '■',
done_label: "Complete!",
color: Some(LIGHT_BLUE),
..Default::default()
});
bar.set_label(&label);
bar.start_auto(2000);
Manual .tick() control (like during a loop):
use std::time::Duration;
use modcli::output::{
progress::{
ProgressBar,
ProgressStyle
},
ORANGE
};
use modcli::console::run_shell;
let mut bar = ProgressBar::new(10, ProgressStyle {
fill: '■',
done_label: "Done!",
color: Some(ORANGE),
..Default::default()
});
bar.set_label("Syncing");
for _ in 0..10 {
bar.tick();
std::thread::sleep(Duration::from_millis(200));
}
println!(" {}", bar.style.done_label);
Animated Spinner (Loading/Waiting):
use modcli::output::{
progress::{
show_spinner
}
};
show_spinner("Loading", 20, 100);
Animated Percentage Loader:
use std::thread::sleep;
use std::time::Duration;
use modcli::output::{
progress::{
show_percent_progress
}
};
for i in (0..=100).step_by(10) {
show_percent_progress("Loading", i);
sleep(Duration::from_millis(100));
}
println!();
Tables
Table Example: Flex Width, Heavy Borders
use crate::output::table::{render_table, TableMode, TableStyle};
let headers = ["Name", "Age", "Role"];
let rows = vec![
vec!["Alice", "29", "Engineer"],
vec!["Bob", "35", "Manager"],
vec!["Charlie", "41", "CTO"],
];
render_table(&headers, &rows, TableMode::Flex, TableStyle::Heavy);
Outputs
┏━━━━━━━━┳━━━━━━━━┳━━━━━━━━┓
┃Name ┃Age ┃Role ┃
┣━━━━━━━━╋━━━━━━━━╋━━━━━━━━┫
┃Alice ┃29 ┃Engineer┃
┃Bob ┃35 ┃Manager ┃
┃Charlie ┃41 ┃CTO ┃
┗━━━━━━━━┻━━━━━━━━┻━━━━━━━━┛
Table Example: Fixed Width, Rounded Borders
use crate::output::table::{render_table, TableMode, TableStyle};
let headers = ["Name", "Age", "Role"];
let rows = vec![
vec!["Alice", "29", "Engineer"],
vec!["Bob", "35", "Manager"],
vec!["Charlie", "41", "CTO"],
];
render_table(&headers, &rows, TableMode::Fixed(15), TableStyle::Rounded);
Outputs
╭───────────────┬───────────────┬───────────────╮
│Name │Age │Role │
├───────────────┼───────────────┼───────────────┤
│Alice │29 │Engineer │
│Bob │35 │Manager │
│Charlie │41 │CTO │
╰───────────────┴───────────────┴───────────────╯
Table Example: Fixed Width, Ascii Borders
use crate::output::table::{render_table, TableMode, TableStyle};
let headers = ["Name", "Age", "Role"];
let rows = vec![
vec!["Alice", "29", "Engineer"],
vec!["Bob", "35", "Manager"],
vec!["Charlie", "41", "CTO"],
];
render_table(&headers, &rows, TableMode::Fixed(15), TableStyle::Ascii);
Outputs
+---------------+---------------+---------------+
|Name |Age |Role |
+---------------+---------------+---------------+
|Alice |29 |Engineer |
|Bob |35 |Manager |
|Charlie |41 |CTO |
+---------------+---------------+---------------+
File Structure
my_project/
├── src/
│ ├── commands/
│ │ └── greet.rs ← define `GreetCommand` here
Create a commands folder in src/, then put the command in its own file:
Custom Command File
use modcli::command::Command;
pub struct GreetCommand;
impl Command for GreetCommand {
fn name(&self) -> &str {
"greet"
}
fn aliases(&self) -> &[&str] {
&["hi"]
}
fn help(&self) -> Option<&str> {
Some("Greets the user.")
}
fn validate(&self, _args: &[String]) -> Result<(), String> {
Ok(())
}
fn execute(&self, _args: &[String]) {
println!("Greetings!");
}
}
greet.rs
Register your command in main.rs
, tool.rs
, etc.
mod commands;
use modcli::ModCli;
use commands::greet::GreetCommand;
fn main() {
let args: Vec<String> = std::env::args().skip(1).collect();
let mut cli = ModCli::new();
cli.registry.register(Box::new(GreetCommand));
cli.run(args);
}
Test Command
$ myCLI greet
Greetings!
$ myCLI help
List of available commands...
ModCLI supports an interactive console mode (like a REPL):
use modcli::config::CliConfig;
use modcli::console::run_shell;
fn main() {
let config = CliConfig::load(None);
run_shell(config);
}
Adding a custom console command for shell
:
use modcli::ModCli;
use modcli::shell_commands::{register, ShellCommand};
fn greet_handler(_input: &str) -> bool {
println!("👋 Hello from shell command!");
true
}
fn main() {
register(ShellCommand {
name: "greet",
aliases: &["hi", "wave"],
help: "Greets the user with a friendly hello",
handler: greet_handler,
});
}
Config File Example (config.json)
{
"modcli": {
"name" : "mod-cli",
"prefix": "mod",
"banner": "Welcome to ModCLI",
"delay" : 0,
"theme" : "default",
"strict": false,
"force_shell": false,
"shell": {
"prompt": "Tool >",
"welcome": ["Welcome to the console."],
"goodbye": ["Bye!"]
},
"messages": {
"no_command": "No command provided.",
"not_found": "Command not found."
}
}
}
Default location: project_root/config.json
Manually set the config path (if not project root)
use modcli::config;
fn main() {
config::set_path(("my/custom/config.json");
[!WARNING]
Pre-release: This project is in active development.
The core is stable but features are evolving. Production use is possible,
but interfaces may still evolve until 1.0.