diff --git a/src/modes/get.rs b/src/modes/get.rs index dfe0313..80d6f85 100644 --- a/src/modes/get.rs +++ b/src/modes/get.rs @@ -8,6 +8,7 @@ use crate::services::item_service::ItemService; use clap::Command; use is_terminal::IsTerminal; use std::path::PathBuf; +use std::io::Read; pub fn mode_get( cmd: &mut Command, @@ -16,6 +17,7 @@ pub fn mode_get( tags: &mut Vec, conn: &mut rusqlite::Connection, data_path: PathBuf, + filters: &Vec, ) -> Result<()> { 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(); @@ -46,10 +48,27 @@ pub fn mode_get( } } - // Use streaming approach to handle large files - let mut reader = item_service.get_compression_service().stream_item_content( - data_path.join(item_id.to_string()), - &item_with_meta.item.compression + // Join all filter strings with | to create a single filter string + let filter_str = if filters.is_empty() { + None + } 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 { @@ -62,10 +81,21 @@ pub fn mode_get( )); } // We need to create a new reader since we consumed some bytes - reader = item_service.get_compression_service().stream_item_content( - data_path.join(item_id.to_string()), - &item_with_meta.item.compression + let (new_reader, _, _) = item_service.get_item_content_info_streaming( + conn, + item_id, + None, + None, + None, + None, + None, + None, + None, + None, + None, + filter_str, )?; + reader = new_reader; } // Stream the content to stdout diff --git a/src/services/item_service.rs b/src/services/item_service.rs index d5038d9..6dc6ada 100644 --- a/src/services/item_service.rs +++ b/src/services/item_service.rs @@ -190,14 +190,13 @@ impl ItemService { filter_parts.push(format!("tail_lines({})", lines)); } - // Use the provided filter string if available, otherwise build from parts - let filter_str = filter.or_else(|| { - if filter_parts.is_empty() { - None - } else { - Some(filter_parts.join(" | ")) - } - }); + // Handle the provided filter string + let filter_str = match (filter, filter_parts.is_empty()) { + (Some(f), true) => Some(f), + (Some(f), false) => Some(format!("{} | {}", f, filter_parts.join(" | "))), + (None, true) => None, + (None, false) => Some(filter_parts.join(" | ")), + }; // Create filter chain self.filter_service.create_filter_chain(filter_str.as_deref()) @@ -239,6 +238,7 @@ impl ItemService { _line_start: Option, _line_end: Option, grep: Option, + filter: Option, ) -> Result<(Box, String, bool), CoreError> { 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()))?; @@ -257,7 +257,7 @@ impl ItemService { // 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