refactor(g3-core): reduce lib.rs complexity by extracting utilities
- Extract truncate_to_word_boundary() to utils.rs with tests - Consolidate duplicate detection: use streaming::are_tool_calls_duplicate() instead of inline closures (eliminates code-path aliasing) - Remove unused regex import - Remove wrapper methods format_duration/format_timing_footer that just delegated to streaming module - call streaming::* directly Reduces lib.rs from 2945 to 2897 lines (-48 lines, -1.6%) All 159+ g3-core tests pass. Agent: fowler
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
//! Utility functions for diff parsing, shell escaping, and JSON fixing.
|
||||
//!
|
||||
//! This module contains helper functions used by the agent for:
|
||||
//! - String truncation utilities
|
||||
//! - Applying unified diffs to strings
|
||||
//! - Shell command escaping
|
||||
//! - JSON quote fixing
|
||||
@@ -8,6 +9,42 @@
|
||||
use anyhow::Result;
|
||||
use tracing::debug;
|
||||
|
||||
/// Truncate a string to approximately max_len characters, ending at a word boundary.
|
||||
///
|
||||
/// This function attempts to break at a space character for cleaner display.
|
||||
/// If no suitable word boundary is found (or it would result in too short a string),
|
||||
/// it falls back to character-based truncation.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `s` - The string to truncate
|
||||
/// * `max_len` - Maximum number of characters (approximate)
|
||||
///
|
||||
/// # Returns
|
||||
/// The truncated string with "..." appended if truncation occurred
|
||||
pub fn truncate_to_word_boundary(s: &str, max_len: usize) -> String {
|
||||
let char_count = s.chars().count();
|
||||
if char_count <= max_len {
|
||||
return s.to_string();
|
||||
}
|
||||
|
||||
// Get the byte index of the max_len-th character
|
||||
let byte_index: usize = s.char_indices()
|
||||
.nth(max_len)
|
||||
.map(|(i, _)| i)
|
||||
.unwrap_or(s.len());
|
||||
|
||||
// Find the last space before the character limit
|
||||
let truncated = &s[..byte_index];
|
||||
if let Some(last_space_byte) = truncated.rfind(' ') {
|
||||
if truncated[..last_space_byte].chars().count() > max_len / 2 {
|
||||
// Only use word boundary if it's not too short (in characters)
|
||||
return format!("{}...", &s[..last_space_byte]);
|
||||
}
|
||||
}
|
||||
// Fall back to truncation at character boundary
|
||||
format!("{}...", truncated)
|
||||
}
|
||||
|
||||
/// Normalize Unicode space characters in a file path to regular ASCII spaces.
|
||||
///
|
||||
/// macOS uses special Unicode space characters in certain filenames:
|
||||
@@ -604,4 +641,31 @@ mod tests {
|
||||
let cmd = "cat \"/etc/hosts\"";
|
||||
assert_eq!(resolve_paths_in_shell_command(cmd), cmd);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_to_word_boundary_short_string_unchanged() {
|
||||
assert_eq!(truncate_to_word_boundary("hello", 10), "hello");
|
||||
assert_eq!(truncate_to_word_boundary("hello world", 20), "hello world");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_to_word_boundary_breaks_at_space() {
|
||||
// Should break at word boundary
|
||||
let result = truncate_to_word_boundary("hello world this is a long string", 15);
|
||||
assert_eq!(result, "hello world...");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_to_word_boundary_falls_back_to_char_limit() {
|
||||
// When word boundary would be too short, fall back to char limit
|
||||
let result = truncate_to_word_boundary("a verylongwordwithoutspaces", 10);
|
||||
assert_eq!(result, "a verylong...");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_to_word_boundary_handles_unicode() {
|
||||
// Should handle unicode characters correctly
|
||||
let result = truncate_to_word_boundary("héllo wörld this is long", 12);
|
||||
assert!(result.ends_with("..."));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user