use std::path::PathBuf;
use clap::Parser;
use crate::Error;
#[derive(Debug, Parser)]
#[command(name = "hawk")]
#[command(version = "0.2.2")]
#[command(about = "Modern data analysis tool for structured data and text files")]
#[command(long_about = "
hawk is a command-line data analysis tool that brings pandas-like functionality
to your terminal. It supports JSON, YAML, CSV, and plain text formats with automatic
detection, powerful filtering, grouping, aggregation, and string manipulation capabilities.
EXAMPLES:
# Basic field access
hawk ‘.users[0].name’ data.json
hawk ‘.users.name’ data.csv
# Text processing (NEW in v0.2.0!)
hawk '. | select(. | contains(\"ERROR\"))' app.log
hawk '. | map(. | trim | upper)' data.txt
hawk '. | map(. | substring(0, 19))' access.log
# String operations
hawk '. | map(. | replace(\"old\", \"new\"))' text.txt
hawk '. | map(. | split(\",\") | join(\" | \"))' csv_lines.txt
# Filtering and aggregation
hawk '.users[] | select(.age > 30)' data.yaml
hawk '.sales | group_by(.region) | avg(.amount)' sales.csv
# Statistical analysis (NEW!)
hawk '. | unique | sort' numbers.txt
hawk '.scores[] | median(.value)' scores.json
hawk '.data[] | stddev(.measurement)' sensor_data.csv
# Complex pipelines
hawk '. | select(. | contains(\"WARN\")) | map(. | substring(11, 8)) | unique' app.log
hawk '.users[] | map(.email | lower | trim) | select(. | ends_with(\".com\"))' users.csv
# Data exploration
hawk '. | info' data.json
hawk '.users | count' data.csv
hawk '. | length' any_file.txt
SUPPORTED FORMATS:
JSON, YAML, CSV, Plain Text (automatically detected)
QUERY SYNTAX:
# Field Access
.field - Access field
.array[0] - Access array element
.array[] - Access all array elements
# Text Processing (NEW!)
. | map(. | upper) - Convert to uppercase
. | map(. | lower) - Convert to lowercase
. | map(. | trim) - Remove whitespace
. | map(. | length) - Get string length
. | map(. | reverse) - Reverse string
# String Manipulation
. | map(. | replace(\"a\", \"b\")) - Replace text
. | map(. | substring(0, 5)) - Extract substring
. | map(. | split(\",\")) - Split by delimiter
.array[] | join(\", \") - Join array elements
# String Filtering
. | select(. | contains(\"text\")) - Contains pattern
. | select(. | starts_with(\"pre\")) - Starts with pattern
. | select(. | ends_with(\"suf\")) - Ends with pattern
# Statistical Functions (NEW!)
. | unique - Remove duplicates
. | sort - Sort values
. | median - Calculate median
. | stddev - Calculate standard deviation
. | length - Get array/text length
# Filtering & Aggregation
. | select(.field > 10) - Filter data
. | group_by(.category) - Group data
. | count/sum/avg/min/max - Aggregate functions
# Data Transformation
. | map(.field | operation) - Transform data with string operations
OUTPUT FORMATS:
–format table - Colored table output (default for structured data)
–format json - JSON output with syntax highlighting
–format list - Simple list output
–format auto - Smart format detection (default)
COLORED OUTPUT:
Automatic color detection (TTY), respects NO_COLOR environment variable
")]
pub struct Args {
pub query: String,
pub path: Option<PathBuf>,
#[arg(long, default_value = "auto")]
#[arg(value_parser = ["auto", "table", "json", "list", "csv"])]
pub format: String,
#[arg(long, short)]
#[arg(help = "Force text format (skip auto-detection)")]
pub text: bool,
}
#[derive(Debug, Clone)]
pub enum OutputFormat {
Auto,
Json,
Table,
List,
Csv,
}
impl std::str::FromStr for OutputFormat {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"auto" => Ok(OutputFormat::Auto),
"json" => Ok(OutputFormat::Json),
"table" => Ok(OutputFormat::Table),
"list" => Ok(OutputFormat::List),
"csv" => Ok(OutputFormat::Csv),
_ => Err(Error::InvalidFormat(format!(
"Invalid format: {}. Valid options: auto, json, table, list",
s
))),
}
}
}