feat: Add --filter option to --get mode for content filtering
Co-authored-by: aider (openai/andrew/openrouter/deepseek/deepseek-chat-v3.1) <aider@aider.chat>
This commit is contained in:
@@ -8,6 +8,7 @@ use crate::services::item_service::ItemService;
|
|||||||
use clap::Command;
|
use clap::Command;
|
||||||
use is_terminal::IsTerminal;
|
use is_terminal::IsTerminal;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
pub fn mode_get(
|
pub fn mode_get(
|
||||||
cmd: &mut Command,
|
cmd: &mut Command,
|
||||||
@@ -16,6 +17,7 @@ pub fn mode_get(
|
|||||||
tags: &mut Vec<String>,
|
tags: &mut Vec<String>,
|
||||||
conn: &mut rusqlite::Connection,
|
conn: &mut rusqlite::Connection,
|
||||||
data_path: PathBuf,
|
data_path: PathBuf,
|
||||||
|
filters: &Vec<String>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if !ids.is_empty() && !tags.is_empty() {
|
if !ids.is_empty() && !tags.is_empty() {
|
||||||
cmd.error(clap::error::ErrorKind::InvalidValue, "Both ID and tags given, you must supply either IDs or tags when using --get").exit();
|
cmd.error(clap::error::ErrorKind::InvalidValue, "Both ID and tags given, you must supply either IDs or tags when using --get").exit();
|
||||||
@@ -46,10 +48,27 @@ pub fn mode_get(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use streaming approach to handle large files
|
// Join all filter strings with | to create a single filter string
|
||||||
let mut reader = item_service.get_compression_service().stream_item_content(
|
let filter_str = if filters.is_empty() {
|
||||||
data_path.join(item_id.to_string()),
|
None
|
||||||
&item_with_meta.item.compression
|
} else {
|
||||||
|
Some(filters.join(" | "))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a reader that applies the filters
|
||||||
|
let (mut reader, _, _) = item_service.get_item_content_info_streaming(
|
||||||
|
conn,
|
||||||
|
item_id,
|
||||||
|
None, // head_bytes
|
||||||
|
None, // head_words
|
||||||
|
None, // head_lines
|
||||||
|
None, // tail_bytes
|
||||||
|
None, // tail_words
|
||||||
|
None, // tail_lines
|
||||||
|
None, // line_start
|
||||||
|
None, // line_end
|
||||||
|
None, // grep
|
||||||
|
filter_str,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if detect_binary {
|
if detect_binary {
|
||||||
@@ -62,10 +81,21 @@ pub fn mode_get(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
// We need to create a new reader since we consumed some bytes
|
// We need to create a new reader since we consumed some bytes
|
||||||
reader = item_service.get_compression_service().stream_item_content(
|
let (new_reader, _, _) = item_service.get_item_content_info_streaming(
|
||||||
data_path.join(item_id.to_string()),
|
conn,
|
||||||
&item_with_meta.item.compression
|
item_id,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
filter_str,
|
||||||
)?;
|
)?;
|
||||||
|
reader = new_reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stream the content to stdout
|
// Stream the content to stdout
|
||||||
|
|||||||
@@ -190,14 +190,13 @@ impl ItemService {
|
|||||||
filter_parts.push(format!("tail_lines({})", lines));
|
filter_parts.push(format!("tail_lines({})", lines));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the provided filter string if available, otherwise build from parts
|
// Handle the provided filter string
|
||||||
let filter_str = filter.or_else(|| {
|
let filter_str = match (filter, filter_parts.is_empty()) {
|
||||||
if filter_parts.is_empty() {
|
(Some(f), true) => Some(f),
|
||||||
None
|
(Some(f), false) => Some(format!("{} | {}", f, filter_parts.join(" | "))),
|
||||||
} else {
|
(None, true) => None,
|
||||||
Some(filter_parts.join(" | "))
|
(None, false) => Some(filter_parts.join(" | ")),
|
||||||
}
|
};
|
||||||
});
|
|
||||||
|
|
||||||
// Create filter chain
|
// Create filter chain
|
||||||
self.filter_service.create_filter_chain(filter_str.as_deref())
|
self.filter_service.create_filter_chain(filter_str.as_deref())
|
||||||
@@ -239,6 +238,7 @@ impl ItemService {
|
|||||||
_line_start: Option<usize>,
|
_line_start: Option<usize>,
|
||||||
_line_end: Option<usize>,
|
_line_end: Option<usize>,
|
||||||
grep: Option<String>,
|
grep: Option<String>,
|
||||||
|
filter: Option<String>,
|
||||||
) -> Result<(Box<dyn Read + Send>, String, bool), CoreError> {
|
) -> Result<(Box<dyn Read + Send>, String, bool), CoreError> {
|
||||||
let item_with_meta = self.get_item(conn, id)?;
|
let item_with_meta = self.get_item(conn, id)?;
|
||||||
let item_id = item_with_meta.item.id.ok_or_else(|| CoreError::InvalidInput("Item missing ID".to_string()))?;
|
let item_id = item_with_meta.item.id.ok_or_else(|| CoreError::InvalidInput("Item missing ID".to_string()))?;
|
||||||
@@ -257,7 +257,7 @@ impl ItemService {
|
|||||||
|
|
||||||
// Create filter chain
|
// Create filter chain
|
||||||
let filter_chain = self.create_filter_chain(
|
let filter_chain = self.create_filter_chain(
|
||||||
grep, head_bytes, head_lines, tail_bytes, tail_lines, None
|
grep, head_bytes, head_lines, tail_bytes, tail_lines, filter
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Wrap the reader with filtering
|
// Wrap the reader with filtering
|
||||||
|
|||||||
Reference in New Issue
Block a user