use crate::cli::{
args::{SteleArgs, SteleCommand, SteleDecodeArgs, SteleEncodeArgs, SteleMode},
global::GlobalArgs,
};
use base_d::{
DetectedMode, DictionaryRegistry, decode_stele, decode_stele_path, detect_stele_mode,
encode_markdown_stele, encode_markdown_stele_ascii, encode_markdown_stele_light,
encode_markdown_stele_markdown, encode_markdown_stele_readable, encode_stele,
encode_stele_ascii, encode_stele_light, encode_stele_path, encode_stele_readable,
};
use std::fs;
use std::io::{self, Read};
use std::path::PathBuf;
pub fn handle(
args: SteleArgs,
_global: &GlobalArgs,
_config: &DictionaryRegistry,
) -> Result<(), Box<dyn std::error::Error>> {
match args.command {
Some(SteleCommand::Encode(encode_args)) => handle_encode(encode_args),
Some(SteleCommand::Decode(decode_args)) => handle_decode(decode_args),
None => {
let encode_args = SteleEncodeArgs {
mode: args.mode.unwrap_or_default(),
output: args.output,
input: args.input,
multiline: args.multiline,
markdown: args.markdown,
};
handle_encode(encode_args)
}
}
}
fn handle_encode(args: SteleEncodeArgs) -> Result<(), Box<dyn std::error::Error>> {
let input_text = read_input(args.input.as_deref())?;
let minify = !args.multiline;
let mode = match args.mode {
SteleMode::Auto if !args.markdown => {
let detected = detect_stele_mode(input_text.trim());
match detected {
DetectedMode::Full => SteleMode::Full,
DetectedMode::Path => SteleMode::Path,
}
}
SteleMode::Auto => SteleMode::None, other => other,
};
let output = if args.markdown {
match mode {
SteleMode::Auto => unreachable!("Auto should be resolved by now"),
SteleMode::None => encode_markdown_stele_readable(input_text.trim(), minify)?,
SteleMode::Light => encode_markdown_stele_light(input_text.trim(), minify)?,
SteleMode::Full => encode_markdown_stele(input_text.trim(), minify)?,
SteleMode::Path => {
return Err("Path mode is not supported for markdown input".into());
}
SteleMode::Ascii => encode_markdown_stele_ascii(input_text.trim())?,
SteleMode::Markdown => encode_markdown_stele_markdown(input_text.trim())?,
}
} else {
match mode {
SteleMode::Auto => unreachable!("Auto should be resolved by now"),
SteleMode::None => encode_stele_readable(input_text.trim(), minify)?,
SteleMode::Light => encode_stele_light(input_text.trim(), minify)?,
SteleMode::Full => encode_stele(input_text.trim(), minify)?,
SteleMode::Path => encode_stele_path(input_text.trim())?,
SteleMode::Ascii => encode_stele_ascii(input_text.trim())?,
SteleMode::Markdown => {
return Err("Markdown mode requires --markdown flag (markdown input only)".into());
}
}
};
write_output(&output, args.output.as_ref())?;
Ok(())
}
fn handle_decode(args: SteleDecodeArgs) -> Result<(), Box<dyn std::error::Error>> {
let input_text = read_input(args.input.as_deref())?;
let trimmed = input_text.trim();
let has_row_marker = trimmed.lines().any(|line| line.starts_with("◉"));
let has_field_sep = trimmed.contains('┃');
let is_path_mode = has_field_sep && !has_row_marker;
let output = if is_path_mode {
decode_stele_path(trimmed)?
} else {
decode_stele(trimmed, args.pretty)?
};
write_output(&output, args.output.as_ref())?;
Ok(())
}
fn read_input(input: Option<&str>) -> Result<String, Box<dyn std::error::Error>> {
if let Some(input_str) = input {
if let Ok(content) = fs::read_to_string(input_str) {
Ok(content)
} else {
Ok(input_str.to_string())
}
} else {
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer)?;
Ok(buffer)
}
}
fn write_output(
content: &str,
output_path: Option<&PathBuf>,
) -> Result<(), Box<dyn std::error::Error>> {
if let Some(path) = output_path {
fs::write(path, content.as_bytes())?;
} else {
println!("{}", content);
}
Ok(())
}