use std::cell::Cell;
use serde::{Deserialize, Serialize};
use server_less::{CliGlobals, cli};
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct Item {
pub name: String,
pub category: String,
}
impl std::fmt::Display for Item {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} ({})", self.name, self.category)
}
}
#[derive(Clone, Default)]
pub struct AdvancedApp {
verbose: Cell<bool>,
debug: Cell<bool>,
}
impl CliGlobals for AdvancedApp {
fn set_global_flag(&self, name: &str, value: bool) {
match name {
"verbose" => self.verbose.set(value),
"debug" => self.debug.set(value),
_ => {}
}
}
}
impl AdvancedApp {
fn get_defaults(&self, key: &str) -> Option<String> {
match key {
"host" => Some("localhost".to_string()),
"port" => Some("5432".to_string()),
_ => None,
}
}
#[allow(clippy::ptr_arg)] fn format_items(&self, items: &Vec<Item>) -> String {
items
.iter()
.enumerate()
.map(|(i, item)| format!(" {}. {} [{}]", i + 1, item.name, item.category))
.collect::<Vec<_>>()
.join("\n")
}
fn seed_data(&self) -> Vec<Item> {
vec![
Item {
name: "Widget".to_string(),
category: "hardware".to_string(),
},
Item {
name: "Gadget".to_string(),
category: "hardware".to_string(),
},
Item {
name: "Script".to_string(),
category: "software".to_string(),
},
]
}
}
#[cli(
name = "advanced-cli",
version = "0.1.0",
description = "Demo of advanced CLI features",
global = [verbose, debug],
defaults = "get_defaults"
)]
impl AdvancedApp {
#[cli(display_with = "format_items")]
pub fn list_items(&self) -> Vec<Item> {
let items = self.seed_data();
if self.verbose.get() {
eprintln!("[verbose] returning {} items", items.len());
}
items
}
pub fn connect(&self, host: String, port: u16) -> String {
if self.verbose.get() {
eprintln!("[verbose] connecting to {}:{}", host, port);
}
format!("Connected to {}:{}", host, port)
}
#[cli(skip)]
pub fn internal_status(&self) -> String {
"ok".to_string()
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let app = AdvancedApp::default();
app.cli_run()
}