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:
@@ -1,4 +1,6 @@
|
||||
use std::io::{Result, Read, Write};
|
||||
use std::str::FromStr;
|
||||
use strum::{EnumString, EnumVariantNames};
|
||||
|
||||
pub mod head;
|
||||
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<()>;
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumString, EnumVariantNames)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
enum FilterType {
|
||||
HeadBytes,
|
||||
HeadLines,
|
||||
TailBytes,
|
||||
TailLines,
|
||||
SkipBytes,
|
||||
SkipLines,
|
||||
Grep,
|
||||
StripAnsi,
|
||||
}
|
||||
|
||||
pub struct FilterChain {
|
||||
plugins: Vec<Box<dyn FilterPlugin>>,
|
||||
}
|
||||
@@ -72,39 +87,70 @@ pub fn parse_filter_string(filter_str: &str) -> Result<FilterChain> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Define a macro to reduce duplication in filter parsing
|
||||
macro_rules! parse_filter {
|
||||
($prefix:expr, $suffix:expr, $constructor:expr) => {{
|
||||
if let Some(stripped) = part.strip_prefix($prefix).and_then(|s| s.strip_suffix($suffix)) {
|
||||
let count = utils::parse_number(stripped)?;
|
||||
chain.add_plugin(Box::new($constructor(count)));
|
||||
// Parse the filter type
|
||||
if let Ok(filter_type) = FilterType::from_str(part) {
|
||||
match filter_type {
|
||||
FilterType::StripAnsi => {
|
||||
chain.add_plugin(Box::new(strip_ansi::StripAnsiFilter::new()));
|
||||
continue;
|
||||
}
|
||||
}};
|
||||
_ => {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
format!("Filter '{}' requires parameters", part)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle strip_ansi filter
|
||||
if part == "strip_ansi" {
|
||||
chain.add_plugin(Box::new(strip_ansi::StripAnsiFilter::new()));
|
||||
continue;
|
||||
// Handle filters with parameters
|
||||
// Extract the filter name and parameters
|
||||
if let Some((filter_name, params)) = part.split_once('(') {
|
||||
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
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
|
||||
Reference in New Issue
Block a user