diff --git a/src/discord.rs b/src/discord.rs index 5b4bb8b0..ef16de65 100644 --- a/src/discord.rs +++ b/src/discord.rs @@ -232,25 +232,19 @@ async fn stream_prompt( let mut buf_rx = buf_rx.clone(); tokio::spawn(async move { let mut last_content = String::new(); - let mut current_edit_msg = msg_id; + let current_edit_msg = msg_id; loop { tokio::time::sleep(std::time::Duration::from_millis(1500)).await; if buf_rx.has_changed().unwrap_or(false) { let content = buf_rx.borrow_and_update().clone(); if content != last_content { - if content.len() > 1900 { - let chunks = format::split_message(&content, 1900); - if let Some(first) = chunks.first() { - let _ = edit(&ctx, channel, current_edit_msg, first).await; - } - for chunk in chunks.iter().skip(1) { - if let Ok(new_msg) = channel.say(&ctx.http, chunk).await { - current_edit_msg = new_msg.id; - } - } + let display = if content.chars().count() > 1900 { + let truncated: String = content.chars().take(1900).collect(); + format!("{truncated}…") } else { - let _ = edit(&ctx, channel, current_edit_msg, &content).await; - } + content.clone() + }; + let _ = edit(&ctx, channel, current_edit_msg, &display).await; last_content = content; } } diff --git a/src/format.rs b/src/format.rs index a0026ebb..63081e6e 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,31 +1,44 @@ -/// Split text into chunks at line boundaries, each <= limit chars. +/// Split text into chunks at line boundaries, each <= limit **characters**. pub fn split_message(text: &str, limit: usize) -> Vec { - if text.len() <= limit { + if text.chars().count() <= limit { return vec![text.to_string()]; } let mut chunks = Vec::new(); let mut current = String::new(); + let mut current_chars = 0usize; for line in text.split('\n') { + let line_chars = line.chars().count(); // +1 for the newline - if !current.is_empty() && current.len() + line.len() + 1 > limit { + if !current.is_empty() && current_chars + line_chars + 1 > limit { chunks.push(current); current = String::new(); + current_chars = 0; } if !current.is_empty() { current.push('\n'); + current_chars += 1; } - // If a single line exceeds limit, hard-split it - if line.len() > limit { - for chunk in line.as_bytes().chunks(limit) { - if !current.is_empty() { + // If a single line exceeds limit, hard-split it at char boundaries + if line_chars > limit { + let mut chars = line.chars(); + loop { + let chunk: String = chars.by_ref().take(limit - current_chars).collect(); + if chunk.is_empty() { + break; + } + current.push_str(&chunk); + current_chars += chunk.chars().count(); + if current_chars >= limit { chunks.push(current); + current = String::new(); + current_chars = 0; } - current = String::from_utf8_lossy(chunk).to_string(); } } else { current.push_str(line); + current_chars += line_chars; } } if !current.is_empty() {