refactor: Use strum for filter plugin type determination
Co-authored-by: aider (openai/andrew/openrouter/deepseek/deepseek-chat-v3.1) <aider@aider.chat>
This commit is contained in:
@@ -51,7 +51,6 @@ sha2 = "0.10.0"
|
|||||||
md5 = "0.7.0"
|
md5 = "0.7.0"
|
||||||
stderrlog = "0.6.0"
|
stderrlog = "0.6.0"
|
||||||
strum = { version = "0.27.2", features = ["derive"] }
|
strum = { version = "0.27.2", features = ["derive"] }
|
||||||
strum_macros = "0.27.2"
|
|
||||||
term = "1.1.0"
|
term = "1.1.0"
|
||||||
termsize = "0.1.9"
|
termsize = "0.1.9"
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
tokio = { version = "1.0", features = ["full"] }
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use std::io::{Result, Read, Write};
|
use std::io::{Result, Read, Write};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use strum::{EnumString, EnumVariantNames};
|
||||||
|
|
||||||
pub mod head;
|
pub mod head;
|
||||||
pub mod tail;
|
pub mod tail;
|
||||||
@@ -11,6 +13,19 @@ pub trait FilterPlugin: Send {
|
|||||||
fn filter(&mut self, reader: Box<&mut dyn Read>, writer: Box<&mut dyn Write>) -> Result<()>;
|
fn filter(&mut self, reader: Box<&mut dyn Read>, writer: Box<&mut dyn Write>) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, EnumString, EnumVariantNames)]
|
||||||
|
#[strum(serialize_all = "snake_case")]
|
||||||
|
enum FilterType {
|
||||||
|
HeadBytes,
|
||||||
|
HeadLines,
|
||||||
|
TailBytes,
|
||||||
|
TailLines,
|
||||||
|
SkipBytes,
|
||||||
|
SkipLines,
|
||||||
|
Grep,
|
||||||
|
StripAnsi,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FilterChain {
|
pub struct FilterChain {
|
||||||
plugins: Vec<Box<dyn FilterPlugin>>,
|
plugins: Vec<Box<dyn FilterPlugin>>,
|
||||||
}
|
}
|
||||||
@@ -72,39 +87,70 @@ pub fn parse_filter_string(filter_str: &str) -> Result<FilterChain> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a macro to reduce duplication in filter parsing
|
// Parse the filter type
|
||||||
macro_rules! parse_filter {
|
if let Ok(filter_type) = FilterType::from_str(part) {
|
||||||
($prefix:expr, $suffix:expr, $constructor:expr) => {{
|
match filter_type {
|
||||||
if let Some(stripped) = part.strip_prefix($prefix).and_then(|s| s.strip_suffix($suffix)) {
|
FilterType::StripAnsi => {
|
||||||
let count = utils::parse_number(stripped)?;
|
chain.add_plugin(Box::new(strip_ansi::StripAnsiFilter::new()));
|
||||||
chain.add_plugin(Box::new($constructor(count)));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}};
|
_ => {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::InvalidInput,
|
||||||
|
format!("Filter '{}' requires parameters", part)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle strip_ansi filter
|
// Handle filters with parameters
|
||||||
if part == "strip_ansi" {
|
// Extract the filter name and parameters
|
||||||
chain.add_plugin(Box::new(strip_ansi::StripAnsiFilter::new()));
|
if let Some((filter_name, params)) = part.split_once('(') {
|
||||||
continue;
|
if let Some(params) = params.strip_suffix(')') {
|
||||||
|
if let Ok(filter_type) = FilterType::from_str(filter_name) {
|
||||||
|
match filter_type {
|
||||||
|
FilterType::Grep => {
|
||||||
|
// Remove quotes if present
|
||||||
|
let pattern = params.trim_matches(|c| c == '\'' || c == '"');
|
||||||
|
chain.add_plugin(Box::new(grep::GrepFilter::new(pattern.to_string())?));
|
||||||
|
}
|
||||||
|
FilterType::HeadBytes => {
|
||||||
|
let count = utils::parse_number(params)?;
|
||||||
|
chain.add_plugin(Box::new(head::HeadBytesFilter::new(count)));
|
||||||
|
}
|
||||||
|
FilterType::HeadLines => {
|
||||||
|
let count = utils::parse_number(params)?;
|
||||||
|
chain.add_plugin(Box::new(head::HeadLinesFilter::new(count)));
|
||||||
|
}
|
||||||
|
FilterType::TailBytes => {
|
||||||
|
let count = utils::parse_number(params)?;
|
||||||
|
chain.add_plugin(Box::new(tail::TailBytesFilter::new(count)));
|
||||||
|
}
|
||||||
|
FilterType::TailLines => {
|
||||||
|
let count = utils::parse_number(params)?;
|
||||||
|
chain.add_plugin(Box::new(tail::TailLinesFilter::new(count)));
|
||||||
|
}
|
||||||
|
FilterType::SkipBytes => {
|
||||||
|
let count = utils::parse_number(params)?;
|
||||||
|
chain.add_plugin(Box::new(skip::SkipBytesFilter::new(count)));
|
||||||
|
}
|
||||||
|
FilterType::SkipLines => {
|
||||||
|
let count = utils::parse_number(params)?;
|
||||||
|
chain.add_plugin(Box::new(skip::SkipLinesFilter::new(count)));
|
||||||
|
}
|
||||||
|
FilterType::StripAnsi => {
|
||||||
|
// This should not happen as strip_ansi doesn't take parameters
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::InvalidInput,
|
||||||
|
"strip_ansi filter doesn't take parameters"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle grep filter
|
|
||||||
if let Some(stripped) = part.strip_prefix("grep(").and_then(|s| s.strip_suffix(')')) {
|
|
||||||
// Remove quotes if present
|
|
||||||
let pattern = stripped.trim_matches(|c| c == '\'' || c == '"');
|
|
||||||
chain.add_plugin(Box::new(grep::GrepFilter::new(pattern.to_string())?));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle other filters using the macro
|
|
||||||
parse_filter!("head_bytes(", ")", head::HeadBytesFilter::new);
|
|
||||||
parse_filter!("head_lines(", ")", head::HeadLinesFilter::new);
|
|
||||||
parse_filter!("tail_bytes(", ")", tail::TailBytesFilter::new);
|
|
||||||
parse_filter!("tail_lines(", ")", tail::TailLinesFilter::new);
|
|
||||||
parse_filter!("skip_bytes(", ")", skip::SkipBytesFilter::new);
|
|
||||||
parse_filter!("skip_lines(", ")", skip::SkipLinesFilter::new);
|
|
||||||
|
|
||||||
// If we get here, the filter wasn't recognized
|
// If we get here, the filter wasn't recognized
|
||||||
return Err(std::io::Error::new(
|
return Err(std::io::Error::new(
|
||||||
std::io::ErrorKind::InvalidInput,
|
std::io::ErrorKind::InvalidInput,
|
||||||
|
|||||||
Reference in New Issue
Block a user