use nexus_core::app::{CopyOption, Popup, code_blocks};
use crate::app_view::AppView;
impl AppView {
pub fn open_copy_menu(&mut self) {
let opts = {
let Some(msg) = self
.core
.messages
.iter()
.rev()
.find(|m| m.role == "assistant")
else {
self.push_status("no response to copy");
return;
};
let mut opts = vec![CopyOption {
label: "Entire response".into(),
text: nexus_core::markdown::to_plain(&msg.content),
}];
for (i, (lang, code)) in code_blocks(&msg.content).into_iter().enumerate() {
let label = match lang {
Some(l) => format!("Code block {} ({l})", i + 1),
None => format!("Code block {}", i + 1),
};
opts.push(CopyOption { label, text: code });
}
opts
};
self.copy_options = opts;
self.copy_selected = 0;
self.popup = Popup::Copy;
}
pub fn confirm_copy(&mut self) {
if let Some(text) = self
.copy_options
.get(self.copy_selected)
.map(|o| o.text.clone())
{
self.copy_text(&text);
}
self.popup = Popup::None;
}
pub fn move_copy_selection(&mut self, delta: i32) {
self.copy_selected =
nexus_core::app::clamp_cursor(self.copy_selected, self.copy_options.len(), delta);
}
}
#[cfg(test)]
mod tests {
use super::*;
use nexus_core::app::App;
use nexus_core::db::{Db, Message};
use nexus_core::space::Space;
fn test_space() -> Space {
Space {
root: std::env::temp_dir().join(format!("nexus-copy-flow-{}", uuid::Uuid::new_v4())),
}
}
fn test_app() -> AppView {
AppView::new(App::new(
Db::open_in_memory().unwrap(),
Some("sk-or-test-key"),
test_space(),
))
}
#[test]
fn copy_message_uses_exact_original_content() {
let mut a = test_app();
a.core.messages.push(Message {
role: "user".into(),
content: "raw *user* text".into(),
model: None,
reasoning: None,
tokens: None,
secs: None,
cost: None,
phrase: None,
persona: None,
created_at: None,
});
a.core.messages.push(Message {
role: "assistant".into(),
content: "**bold** reply".into(),
model: Some("a/one".into()),
reasoning: None,
tokens: None,
secs: None,
cost: None,
phrase: None,
persona: None,
created_at: None,
});
let _ = a.last_status(); a.copy_message(0); assert_ne!(a.last_status(), "sentinel");
let _ = a.last_status(); a.copy_message(1); assert_ne!(a.last_status(), "sentinel");
let _ = a.last_status(); a.copy_message(2);
assert_eq!(a.last_status(), "");
}
}