From 053f389b1efbbe86f6ba2c959f9ce51ee85476bd Mon Sep 17 00:00:00 2001 From: vikingowl Date: Tue, 30 Sep 2025 02:54:07 +0200 Subject: [PATCH] Refactor: simplify word navigation logic, improve line wrapping, and enhance parameter initialization across core and TUI modules. --- crates/owlen-core/src/router.rs | 6 ++---- crates/owlen-core/src/types.rs | 14 ++------------ crates/owlen-core/src/ui.rs | 12 +++--------- crates/owlen-core/src/wrap_cursor.rs | 26 ++++++++++++-------------- crates/owlen-tui/src/chat_app.rs | 8 +++++--- crates/owlen-tui/src/ui.rs | 6 +++--- 6 files changed, 27 insertions(+), 45 deletions(-) diff --git a/crates/owlen-core/src/router.rs b/crates/owlen-core/src/router.rs index d3d4bdd..118d554 100644 --- a/crates/owlen-core/src/router.rs +++ b/crates/owlen-core/src/router.rs @@ -106,13 +106,11 @@ impl Router { return true; } - if pattern.ends_with('*') { - let prefix = &pattern[..pattern.len() - 1]; + if let Some(prefix) = pattern.strip_suffix('*') { return model.starts_with(prefix); } - if pattern.starts_with('*') { - let suffix = &pattern[1..]; + if let Some(suffix) = pattern.strip_prefix('*') { return model.ends_with(suffix); } diff --git a/crates/owlen-core/src/types.rs b/crates/owlen-core/src/types.rs index cb34593..74ffd47 100644 --- a/crates/owlen-core/src/types.rs +++ b/crates/owlen-core/src/types.rs @@ -72,7 +72,7 @@ pub struct ChatRequest { } /// Parameters for chat completion -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct ChatParameters { /// Temperature for randomness (0.0 to 2.0) #[serde(skip_serializing_if = "Option::is_none")] @@ -85,20 +85,10 @@ pub struct ChatParameters { pub stream: bool, /// Additional provider-specific parameters #[serde(flatten)] + #[serde(default)] pub extra: HashMap, } -impl Default for ChatParameters { - fn default() -> Self { - Self { - temperature: None, - max_tokens: None, - stream: false, - extra: HashMap::new(), - } - } -} - /// Response from a chat completion request #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChatResponse { diff --git a/crates/owlen-core/src/ui.rs b/crates/owlen-core/src/ui.rs index 313ca0b..33674e3 100644 --- a/crates/owlen-core/src/ui.rs +++ b/crates/owlen-core/src/ui.rs @@ -305,9 +305,7 @@ pub fn find_word_end(line: &str, col: usize) -> Option { pos += 1; } // Move back one to be ON the last character - if pos > 0 { - pos -= 1; - } + pos = pos.saturating_sub(1); } else { // Skip non-word characters while pos < chars.len() && !is_word_char(chars[pos]) { @@ -317,9 +315,7 @@ pub fn find_word_end(line: &str, col: usize) -> Option { while pos < chars.len() && is_word_char(chars[pos]) { pos += 1; } - if pos > 0 { - pos -= 1; - } + pos = pos.saturating_sub(1); } Some(pos) @@ -336,9 +332,7 @@ pub fn find_prev_word_boundary(line: &str, col: usize) -> Option { let is_word_char = |c: char| c.is_alphanumeric() || c == '_'; // Move back one position first - if pos > 0 { - pos -= 1; - } + pos = pos.saturating_sub(1); // Skip non-word characters while pos > 0 && !is_word_char(chars[pos]) { diff --git a/crates/owlen-core/src/wrap_cursor.rs b/crates/owlen-core/src/wrap_cursor.rs index 5d15463..3a89657 100644 --- a/crates/owlen-core/src/wrap_cursor.rs +++ b/crates/owlen-core/src/wrap_cursor.rs @@ -52,23 +52,21 @@ pub fn build_cursor_map(text: &str, width: u16) -> Vec { word_start_col = col; word_start_idx = byte_offset + grapheme.len(); } - } else { - if col + grapheme_width > width { - if word_start_col > 0 && byte_offset == word_start_idx { - // This is the first character of a new word that won't fit, wrap it - row += 1; - col = grapheme_width; - } else if word_start_col == 0 { - // No previous word boundary, hard break - row += 1; - col = grapheme_width; - } else { - // This is part of a word already on the line, let it extend beyond width - col += grapheme_width; - } + } else if col + grapheme_width > width { + if word_start_col > 0 && byte_offset == word_start_idx { + // This is the first character of a new word that won't fit, wrap it + row += 1; + col = grapheme_width; + } else if word_start_col == 0 { + // No previous word boundary, hard break + row += 1; + col = grapheme_width; } else { + // This is part of a word already on the line, let it extend beyond width col += grapheme_width; } + } else { + col += grapheme_width; } // Set position for the end of this grapheme and any intermediate bytes diff --git a/crates/owlen-tui/src/chat_app.rs b/crates/owlen-tui/src/chat_app.rs index 18707d4..45d0545 100644 --- a/crates/owlen-tui/src/chat_app.rs +++ b/crates/owlen-tui/src/chat_app.rs @@ -1320,8 +1320,10 @@ impl ChatApp { self.status = format!("Loading model '{}'...", self.controller.selected_model()); self.start_loading_animation(); - let mut parameters = ChatParameters::default(); - parameters.stream = self.controller.config().general.enable_streaming; + let parameters = ChatParameters { + stream: self.controller.config().general.enable_streaming, + ..Default::default() + }; // Step 2: Start the actual request match self @@ -1392,7 +1394,7 @@ impl ChatApp { } else { // If the current model is not in the filtered list, select the first one self.selected_model = Some(0); - if let Some(model) = filtered_models.get(0) { + if let Some(model) = filtered_models.first() { self.controller.set_model(model.id.clone()); // Also update the config with the new model and provider self.controller.config_mut().general.default_model = Some(model.id.clone()); diff --git a/crates/owlen-tui/src/ui.rs b/crates/owlen-tui/src/ui.rs index 8b73442..4ba86af 100644 --- a/crates/owlen-tui/src/ui.rs +++ b/crates/owlen-tui/src/ui.rs @@ -30,7 +30,7 @@ pub fn render_chat(frame: &mut Frame<'_>, app: &mut ChatApp) { } else { buffer_text.lines().collect() }; - let visual_lines = calculate_wrapped_line_count(lines.into_iter(), available_width); + let visual_lines = calculate_wrapped_line_count(lines, available_width); (visual_lines as u16).min(10) + 2 // +2 for borders }; @@ -283,7 +283,7 @@ fn compute_cursor_metrics( for (row_idx, line) in lines.iter().enumerate() { let display_owned = mask_char.map(|mask| mask_line(line, mask)); - let display_line = display_owned.as_deref().unwrap_or_else(|| line.as_str()); + let display_line = display_owned.as_deref().unwrap_or(line.as_str()); let mut segments = if wrap_lines { wrap_line_segments(display_line, content_width) @@ -889,7 +889,7 @@ fn render_input(frame: &mut Frame<'_>, area: Rect, app: &mut ChatApp) { let lines: Vec = if input_text.is_empty() { vec![Line::from("Press 'i' to start typing")] } else { - input_text.lines().map(|line| Line::from(line)).collect() + input_text.lines().map(Line::from).collect() }; let paragraph = Paragraph::new(lines)