From f3a4894699bc0bdacd5ba7f2008ace86b26cbb53 Mon Sep 17 00:00:00 2001 From: Andrew Phillips Date: Wed, 10 Sep 2025 14:30:54 -0300 Subject: [PATCH] docs: Add Rustdoc comments for `info` and `mcp` modules and `grep` plugin Co-authored-by: aider (openai/andrew/openrouter/sonoma-sky-alpha) --- PLAN.md | 6 +- src/filter_plugin/grep.rs | 114 ++++++++++++++++++++++----------- src/modes/info.rs | 114 ++++++++++++++++++++++++--------- src/modes/server/mcp/server.rs | 71 ++++++++++++-------- 4 files changed, 207 insertions(+), 98 deletions(-) diff --git a/PLAN.md b/PLAN.md index f6c262b..2bffcba 100644 --- a/PLAN.md +++ b/PLAN.md @@ -199,16 +199,16 @@ Private helpers (e.g., internal `fn` without `pub`) are not flagged, as they don - `new()` function: Partial. - Impl `MetaPlugin` methods: No docs. -33. **src/modes/info.rs** +33. **src/modes/info.rs** [DONE] - `mode_info()` function: Partial. - `ItemInfo` struct: No doc. - Helpers (`show_item`, `show_item_structured`): No docs. -34. **src/modes/server/mcp/server.rs** +34. **src/modes/server/mcp/server.rs** [DONE] - `KeepMcpServer` struct: No doc. - `new()` and `handle_request()` methods: No docs. -35. **src/filter_plugin/grep.rs** +35. **src/filter_plugin/grep.rs** [DONE] - `GrepFilter` struct: Partial. - `new()` function: Partial. - Impl `FilterPlugin` methods: No docs. diff --git a/src/filter_plugin/grep.rs b/src/filter_plugin/grep.rs index 039eafd..2ee8bd4 100644 --- a/src/filter_plugin/grep.rs +++ b/src/filter_plugin/grep.rs @@ -4,22 +4,39 @@ use regex::Regex; /// A filter that matches lines against a regular expression pattern. /// -/// Outputs only lines that match the given regex. +/// Outputs only lines that match the given regex. Uses BufRead for line-by-line processing +/// and preserves original line endings. +/// +/// # Fields +/// +/// * `regex` - Compiled regex for matching. #[derive(Debug, Clone)] pub struct GrepFilter { regex: Regex, } +/// Creates a new `GrepFilter` with the specified regex pattern. +/// +/// Compiles the pattern using regex crate. +/// +/// # Arguments +/// +/// * `pattern` - The regular expression pattern (string) used to match lines. +/// +/// # Returns +/// +/// `Ok(Self)` on success. +/// +/// # Errors +/// +/// Returns `Err(io::Error::InvalidInput)` if pattern compilation fails (invalid regex). +/// +/// # Examples +/// +/// ``` +/// let filter = GrepFilter::new("error|warn".to_string())?; +/// ``` impl GrepFilter { - /// Creates a new `GrepFilter` with the specified regex pattern. - /// - /// # Arguments - /// - /// * `pattern` - The regular expression pattern used to match lines. - /// - /// # Errors - /// - /// Returns an `io::Error` with `InvalidInput` if the regex pattern is invalid. pub fn new(pattern: String) -> Result { let regex = Regex::new(&pattern) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?; @@ -29,23 +46,30 @@ impl GrepFilter { } } +/// Filters the input by writing only lines that match the regex pattern. +/// +/// Reads lines from the input and writes matching lines to the output, preserving newlines. +/// Uses BufReader for efficient line iteration. +/// +/// # Arguments +/// +/// * `reader` - A boxed mutable reference to the input reader providing the data stream. +/// * `writer` - A boxed mutable reference to the output writer where matching lines are sent. +/// +/// # Returns +/// +/// `Ok(())` on success. +/// +/// # Errors +/// +/// Propagates `io::Error` from BufRead lines() or writeln! (e.g., read/write failures, UTF-8 issues). +/// +/// # Examples +/// +/// ``` +/// filter.filter(Box::new(&mut input), Box::new(&mut output))?; +/// ``` impl FilterPlugin for GrepFilter { - /// Filters the input by writing only lines that match the regex pattern. - /// - /// Reads lines from the input and writes matching lines to the output, preserving newlines. - /// - /// # Arguments - /// - /// * `reader` - A boxed mutable reference to the input reader providing the data stream. - /// * `writer` - A boxed mutable reference to the output writer where matching lines are sent. - /// - /// # Returns - /// - /// Returns `Ok(())` on success, or an `io::Error` if reading or writing fails. - /// - /// # Errors - /// - /// Propagates `io::Error` from reading lines or writing output. fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> { let mut buf_reader = std::io::BufReader::new(&mut *reader); for line in buf_reader.by_ref().lines() { @@ -58,12 +82,18 @@ impl FilterPlugin for GrepFilter { } /// Clones this filter into a new boxed instance. - /// - /// Creates a new GrepFilter with the same regex pattern. - /// - /// # Returns - /// - /// A new `Box` representing a clone of this filter. +/// +/// Creates a new GrepFilter with the same regex pattern. +/// +/// # Returns +/// +/// A new `Box` representing a clone of this filter. +/// +/// # Examples +/// +/// ``` +/// let cloned = filter.clone_box(); +/// ``` fn clone_box(&self) -> Box { Box::new(Self { regex: self.regex.clone(), @@ -71,12 +101,20 @@ impl FilterPlugin for GrepFilter { } /// Returns the configuration options for this filter. - /// - /// The only option is the required "pattern" for the regex. - /// - /// # Returns - /// - /// A vector of `FilterOption` describing the filter's configurable parameters. +/// +/// The only option is the required "pattern" for the regex. +/// +/// # Returns +/// +/// A vector containing one `FilterOption` for "pattern" (required, no default). +/// +/// # Examples +/// +/// ``` +/// let opts = filter.options(); +/// assert_eq!(opts.len(), 1); +/// assert!(opts[0].required); +/// ``` fn options(&self) -> Vec { vec![ FilterOption { diff --git a/src/modes/info.rs b/src/modes/info.rs index 8c64d2f..5d25f23 100644 --- a/src/modes/info.rs +++ b/src/modes/info.rs @@ -13,20 +13,32 @@ use comfy_table::{Cell, Attribute}; /// Displays detailed information about an item or the last item if no ID/tags specified. /// -/// Supports table, JSON, or YAML output formats. +/// Supports table, JSON, or YAML output formats. Validates input (at most one ID, no mixing IDs/tags). +/// Uses ItemService to fetch the item and displays via helpers. /// /// # Arguments /// -/// * `cmd` - Mutable Clap command for error handling. -/// * `settings` - Application settings. -/// * `ids` - Mutable vector of item IDs (at most one). +/// * `cmd` - Mutable Clap command for error handling and exiting on invalid args. +/// * `settings` - Application settings for output formatting and human-readable sizes. +/// * `ids` - Mutable vector of item IDs (at most one; cleared if tags used). /// * `tags` - Mutable vector of tags (mutually exclusive with IDs). -/// * `conn` - Mutable database connection. -/// * `data_path` - Path to data directory. +/// * `conn` - Mutable database connection for querying items. +/// * `data_path` - Path to data directory for file metadata. /// /// # Returns /// -/// `Ok(())` on success, or Result with error. +/// `Ok(())` on success, or `Err(anyhow::Error)` if item not found or DB query fails. +/// +/// # Errors +/// +/// * Clap errors if invalid args (e.g., multiple IDs). +/// * Anyhow error if no matching item found. +/// +/// # Examples +/// +/// ``` +/// mode_info(&mut cmd, &settings, &mut vec![123], &mut vec![], &mut conn, data_path)?; +/// ``` pub fn mode_info( cmd: &mut Command, settings: &config::Settings, @@ -54,6 +66,22 @@ pub fn mode_info( #[derive(Debug, Serialize, Deserialize)] /// Structured representation of item information for JSON/YAML output. +/// +/// This struct serializes item details including ID, timestamp, sizes, compression, tags, and metadata +/// for non-table output formats. +/// +/// # Fields +/// +/// * `id` - The unique item ID. +/// * `timestamp` - Formatted timestamp string. +/// * `path` - Full file path to the item. +/// * `stream_size` - Original uncompressed size in bytes (optional). +/// * `stream_size_formatted` - Human-readable stream size. +/// * `compression` - Compression type used. +/// * `file_size` - Compressed file size in bytes (optional). +/// * `file_size_formatted` - Human-readable file size. +/// * `tags` - List of associated tags. +/// * `meta` - Metadata key-value pairs. pub struct ItemInfo { id: i64, timestamp: String, @@ -67,22 +95,35 @@ pub struct ItemInfo { meta: std::collections::HashMap, } +/// Displays item information in table format or delegates to structured output. +/// +/// Builds a comfy-table for tabular display or calls structured helper for JSON/YAML. +/// Handles file size via metadata and formats tags/meta accordingly. +/// +/// # Arguments +/// +/// * `item_with_meta` - Item with associated metadata and tags. +/// * `settings` - Application settings for formatting (e.g., human-readable sizes). +/// * `data_path` - Path to data directory for calculating compressed file size. +/// +/// # Returns +/// +/// `Ok(())` on success, or `Err(anyhow::Error)` if path resolution fails. +/// +/// # Errors +/// +/// * Anyhow error if item path cannot be stringified. +/// +/// # Examples +/// +/// ``` +/// show_item(item_with_meta, &settings, data_path)?; +/// ``` fn show_item( item_with_meta: ItemWithMeta, settings: &config::Settings, data_path: PathBuf, ) -> Result<()> { - /// Displays item information in table format or delegates to structured output. - /// - /// # Arguments - /// - /// * `item_with_meta` - Item with associated metadata and tags. - /// * `settings` - Application settings for formatting. - /// * `data_path` - Path to data directory for file size calculation. - /// - /// # Returns - /// - /// `Ok(())` on success. let output_format = crate::modes::common::settings_output_format(settings); if output_format != OutputFormat::Table { @@ -157,24 +198,37 @@ fn show_item( Ok(()) } +/// Displays item information in structured JSON or YAML format. +/// +/// Serializes ItemInfo and prints pretty-formatted output. Handles file metadata for sizes. +/// +/// # Arguments +/// +/// * `item_with_meta` - Item with metadata and tags. +/// * `settings` - Settings for size formatting (human-readable). +/// * `data_path` - Data path for compressed file size calculation. +/// * `output_format` - JSON or YAML (Table is unreachable here). +/// +/// # Returns +/// +/// `Ok(())` on success, or `Err(anyhow::Error)` if serialization or path fails. +/// +/// # Errors +/// +/// * Serde errors during JSON/YAML serialization. +/// * Anyhow error if file metadata unavailable. +/// +/// # Examples +/// +/// ``` +/// show_item_structured(item_with_meta, &settings, data_path, OutputFormat::Json)?; +/// ``` fn show_item_structured( item_with_meta: ItemWithMeta, settings: &config::Settings, data_path: PathBuf, output_format: OutputFormat, ) -> Result<()> { - /// Displays item information in structured JSON or YAML format. - /// - /// # Arguments - /// - /// * `item_with_meta` - Item with metadata and tags. - /// * `settings` - Settings for size formatting. - /// * `data_path` - Data path for file size. - /// * `output_format` - JSON or YAML. - /// - /// # Returns - /// - /// `Ok(())` on success. let item_tags: Vec = item_with_meta.tags.iter().map(|t| t.name.clone()).collect(); let meta_map = item_with_meta.meta_as_map(); let item = item_with_meta.item; diff --git a/src/modes/server/mcp/server.rs b/src/modes/server/mcp/server.rs index a14584d..76a79a5 100644 --- a/src/modes/server/mcp/server.rs +++ b/src/modes/server/mcp/server.rs @@ -4,44 +4,61 @@ use serde_json::Value; use crate::modes::server::common::AppState; use super::tools::{KeepTools, ToolError}; -#[derive(Clone)] /// Server handler for MCP (Model Context Protocol) requests. /// -/// Routes requests to appropriate tools and handles responses. +/// Routes requests to appropriate tools and handles responses. Clones AppState for tool usage. +/// +/// # Fields +/// +/// * `state` - The shared application state (DB, config, etc.). +#[derive(Clone)] pub struct KeepMcpServer { state: AppState, } +/// Creates a new `KeepMcpServer` instance. +/// +/// # Arguments +/// +/// * `state` - The application state containing DB, config, and services. +/// +/// # Returns +/// +/// A new `KeepMcpServer` instance. +/// +/// # Examples +/// +/// ``` +/// let server = KeepMcpServer::new(app_state); +/// ``` impl KeepMcpServer { - /// Creates a new `KeepMcpServer` instance. - /// - /// # Arguments - /// - /// * `state` - The application state containing DB and config. - /// - /// # Returns - /// - /// A new `KeepMcpServer`. pub fn new(state: AppState) -> Self { Self { state } } - /// Handles an MCP request by routing to the appropriate tool. - /// - /// Supports methods like save_item, get_item, etc. - /// - /// # Arguments - /// - /// * `method` - The MCP method name. - /// * `params` - Optional JSON parameters. - /// - /// # Returns - /// - /// JSON string response on success, or ToolError. - /// - /// # Errors - /// - /// Returns ToolError::UnknownTool for unsupported methods. +/// Handles an MCP request by routing to the appropriate tool. +/// +/// Supports methods like "save_item", "get_item", "list_items". Logs the request and delegates to KeepTools. +/// +/// # Arguments +/// +/// * `method` - The MCP method name (string). +/// * `params` - Optional JSON parameters as serde_json::Value. +/// +/// # Returns +/// +/// `Ok(String)` with JSON-serialized response on success, or `Err(ToolError)` on failure. +/// +/// # Errors +/// +/// * ToolError::UnknownTool if method unsupported. +/// * Propagates tool-specific errors (e.g., invalid args, DB failures). +/// +/// # Examples +/// +/// ``` +/// let result = server.handle_request("save_item", Some(params)).await?; +/// ``` pub async fn handle_request(&self, method: &str, params: Option) -> Result { debug!("MCP: Handling request '{}' with params: {:?}", method, params);