pub mod commands;
pub mod format;
pub mod handler;
pub mod runtime;
use clap::{Parser, Subcommand};
use std::path::PathBuf;
pub use commands::CommandHandler;
pub use format::OutputFormat;
pub use handler::DefaultCommandHandler;
#[derive(Parser)]
#[command(name = "xls-rs")]
#[command(
about = "A CLI tool for reading, writing, converting spreadsheet files with formula support",
version = env!("CARGO_PKG_VERSION")
)]
pub struct Cli {
#[arg(long)]
pub config: Option<PathBuf>,
#[arg(long, default_value_t = false)]
pub quiet: bool,
#[arg(long, default_value_t = false)]
pub verbose: bool,
#[arg(long, default_value_t = false)]
pub overwrite: bool,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
Read {
#[arg(short, long)]
input: String,
#[arg(short, long)]
sheet: Option<String>,
#[arg(short, long)]
range: Option<String>,
#[arg(short = 'f', long)]
format: Option<OutputFormat>,
},
Write {
#[arg(short, long)]
output: String,
#[arg(short, long)]
csv: Option<String>,
#[arg(short, long)]
sheet: Option<String>,
},
Convert {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
sheet: Option<String>,
},
Formula {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
formula: String,
#[arg(short, long)]
cell: String,
#[arg(short, long)]
sheet: Option<String>,
},
Serve,
Sort {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
#[arg(short, long)]
ascending: bool,
},
Filter {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short = 'w', long)]
where_clause: String,
},
Replace {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
find: String,
#[arg(short, long)]
replace: String,
#[arg(short, long)]
column: Option<String>,
},
Dedupe {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
columns: Option<String>,
},
Transpose {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
},
Append {
#[arg(short, long)]
source: String,
#[arg(short, long)]
target: String,
},
Sheets {
#[arg(short, long)]
input: String,
},
ReadAll {
#[arg(short, long)]
input: String,
#[arg(short = 'f', long)]
format: Option<OutputFormat>,
},
WriteRange {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
start: String,
},
Select {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
columns: String,
},
Head {
#[arg(short, long)]
input: String,
#[arg(short = 'n', long, default_value = "10")]
n: usize,
#[arg(short = 'f', long, default_value = "csv")]
format: OutputFormat,
},
Tail {
#[arg(short, long)]
input: String,
#[arg(short = 'n', long, default_value = "10")]
n: usize,
#[arg(short = 'f', long, default_value = "csv")]
format: OutputFormat,
},
Sample {
#[arg(short, long)]
input: String,
#[arg(short = 'n', long, default_value = "10")]
n: usize,
#[arg(short, long)]
seed: Option<u64>,
#[arg(short = 'f', long, default_value = "csv")]
format: OutputFormat,
},
Describe {
#[arg(short, long)]
input: String,
#[arg(short = 'f', long, default_value = "csv")]
format: OutputFormat,
},
ValueCounts {
#[arg(short, long)]
input: String,
#[arg(short, long)]
column: String,
},
Corr {
#[arg(short, long)]
input: String,
#[arg(short, long)]
columns: Option<String>,
},
Groupby {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
by: String,
#[arg(short, long)]
agg: String,
},
Join {
#[arg(short, long)]
left: String,
#[arg(short, long)]
right: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
on: String,
#[arg(short, long)]
how: String,
},
Concat {
#[arg(short, long)]
inputs: String,
#[arg(short, long)]
output: String,
},
Mutate {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
#[arg(short, long)]
formula: String,
},
Rename {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
from: String,
#[arg(short, long)]
to: String,
},
Drop {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
columns: String,
},
Fillna {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
value: String,
#[arg(short, long)]
columns: Option<String>,
},
Dropna {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
},
Dtypes {
#[arg(short, long)]
input: String,
},
Astype {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
#[arg(short = 't', long)]
target_type: String,
},
Unique {
#[arg(short, long)]
input: String,
#[arg(short, long)]
column: String,
},
Info {
#[arg(short, long)]
input: String,
},
Clip {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
#[arg(short, long)]
min: String,
#[arg(short, long)]
max: String,
},
Normalize {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
},
Zscore {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
},
Query {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short = 'w', long)]
where_clause: String,
},
Pivot {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
index: String,
#[arg(short, long)]
columns: String,
#[arg(short, long)]
values: String,
#[arg(short, long)]
agg: String,
},
Rolling {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
#[arg(short, long)]
window: usize,
#[arg(long, default_value = "mean")]
agg: String,
#[arg(long)]
name: Option<String>,
},
Crosstab {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
rows: String,
#[arg(short, long)]
cols: String,
},
Melt {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(long)]
id_vars: String,
#[arg(long)]
value_vars: Option<String>,
},
ParseDate {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
#[arg(short, long)]
from_format: String,
#[arg(short, long)]
to_format: String,
},
RegexFilter {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
#[arg(short, long)]
pattern: String,
},
RegexReplace {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
column: String,
#[arg(short, long)]
pattern: String,
#[arg(short, long)]
replacement: String,
},
Diff {
#[arg(short, long)]
left: String,
#[arg(short, long)]
right: String,
#[arg(short, long)]
key: Option<String>,
},
Histogram {
#[arg(short, long)]
input: String,
#[arg(short, long)]
column: String,
#[arg(short = 'n', long, default_value = "10")]
bins: usize,
#[arg(short, long, default_value = "40")]
width: usize,
},
#[command(name = "schema")]
Schema {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: Option<String>,
},
#[command(name = "to-sql")]
ToSql {
#[arg(short, long)]
input: String,
#[arg(short, long)]
table: String,
#[arg(short, long)]
output: Option<String>,
#[arg(short, long)]
batch_size: Option<usize>,
},
Profile {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: Option<String>,
},
Validate {
#[arg(short, long)]
input: String,
#[arg(short, long)]
rules: String,
#[arg(short, long)]
output: Option<String>,
#[arg(short, long)]
report: Option<String>,
},
Chart {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
chart_type: String,
#[arg(short, long)]
title: Option<String>,
#[arg(short, long)]
x_column: Option<String>,
#[arg(short, long)]
y_column: Option<String>,
},
Encrypt {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
algorithm: String,
#[arg(short, long)]
key_file: Option<String>,
},
Decrypt {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
key_file: Option<String>,
},
Batch {
#[arg(short, long)]
inputs: String,
#[arg(short, long)]
output_dir: String,
#[arg(short, long)]
operation: String,
#[arg(short, long)]
args: Vec<String>,
},
Plugin {
#[arg(short, long)]
function: String,
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
args: Vec<String>,
},
Stream {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(long, default_value_t = 1000)]
chunk_size: usize,
},
Completions {
#[arg(short, long)]
shell: String,
},
ExamplesGenerate,
#[cfg(feature = "watch")]
Watch {
#[arg(short, long)]
input: String,
#[arg(short, long)]
command: String,
},
ConfigInit,
ExportStyled {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
style: Option<String>,
},
AddChart {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
chart_type: String,
#[arg(short, long)]
title: Option<String>,
#[arg(short, long)]
category_column: Option<usize>,
#[arg(short, long)]
value_columns: Option<Vec<usize>>,
},
AddSparkline {
#[arg(short, long)]
output: String,
#[arg(short, long)]
data_range: String,
#[arg(short, long)]
sparkline_cell: String,
#[arg(short, long)]
sheet: Option<String>,
},
ConditionalFormat {
#[arg(short, long)]
output: String,
#[arg(short, long)]
range: String,
#[arg(short, long)]
condition: String,
#[arg(short, long)]
bg_color: Option<String>,
#[arg(short, long)]
font_color: Option<String>,
#[arg(short = 'b', long)]
bold: Option<bool>,
#[arg(short, long)]
sheet: Option<String>,
},
ApplyFormulaRange {
#[arg(short, long)]
input: String,
#[arg(short, long)]
output: String,
#[arg(short, long)]
formula: String,
#[arg(short, long)]
range: String,
#[arg(short, long)]
sheet: Option<String>,
},
GSheetsList {
#[arg(short, long)]
spreadsheet: String,
},
GSheetsAuth,
GSheetsSetDefault {
#[arg(short, long)]
spreadsheet: String,
},
}
pub fn run(command: Commands) -> anyhow::Result<()> {
let handler = DefaultCommandHandler::new();
handler.handle(command)
}