mod actions;
mod render;
use std::io::{IsTerminal, Read};
use clap::{Args as ClapArgs, Subcommand};
use crate::context::Ctx;
use crate::errors::CliError;
#[derive(Debug, ClapArgs)]
#[command(after_help = "Examples:\n \
qn kv set put mykey myvalue\n \
qn kv set get mykey\n \
qn kv list create mylist item1 item2\n \
qn kv list contains mylist item1")]
pub struct Args {
#[command(subcommand)]
pub cmd: KvCmd,
}
#[derive(Debug, Subcommand)]
pub enum KvCmd {
#[command(subcommand)]
Set(SetCmd),
#[command(subcommand)]
List(ListCmd),
}
#[derive(Debug, Subcommand)]
pub enum SetCmd {
Put { key: String, value: String },
Get { key: String },
#[command(visible_alias = "ls")]
List(SetsLsArgs),
Delete { key: String },
Bulk(BulkArgs),
}
#[derive(Debug, ClapArgs)]
pub struct SetsLsArgs {
#[arg(long)]
pub limit: Option<i64>,
#[arg(long)]
pub cursor: Option<String>,
}
#[derive(Debug, ClapArgs)]
pub struct BulkArgs {
#[arg(long = "add")]
pub add: Vec<String>,
#[arg(long = "delete")]
pub delete: Vec<String>,
}
#[derive(Debug, Subcommand)]
pub enum ListCmd {
#[command(visible_alias = "ls")]
List(ListsLsArgs),
Get(ListGetArgs),
Create { key: String, items: Vec<String> },
Append { key: String, item: String },
Contains { key: String, item: String },
RemoveItem { key: String, item: String },
Update(ListUpdateArgs),
Delete { key: String },
}
#[derive(Debug, ClapArgs)]
pub struct ListsLsArgs {
#[arg(long)]
pub limit: Option<i64>,
#[arg(long)]
pub cursor: Option<String>,
}
#[derive(Debug, ClapArgs)]
pub struct ListGetArgs {
pub key: String,
#[arg(long)]
pub limit: Option<i64>,
#[arg(long)]
pub cursor: Option<String>,
}
#[derive(Debug, ClapArgs)]
pub struct ListUpdateArgs {
pub key: String,
#[arg(long = "add")]
pub add_items: Vec<String>,
#[arg(long = "remove")]
pub remove_items: Vec<String>,
}
pub async fn run(args: Args, ctx: Ctx) -> Result<(), CliError> {
match args.cmd {
KvCmd::Set(c) => actions::set(c, ctx).await,
KvCmd::List(c) => actions::list(c, ctx).await,
}
}
fn read_stdin() -> Result<String, CliError> {
if std::io::stdin().is_terminal() {
return Err(CliError::Arg(
"value `-` requires stdin to be piped".to_string(),
));
}
let mut buf = String::new();
std::io::stdin().read_to_string(&mut buf)?;
Ok(buf.trim_end_matches('\n').to_string())
}