diff --git a/Cargo.lock b/Cargo.lock index b174fcc..f3aeabd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -200,6 +200,24 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +[[package]] +name = "arboard" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" +dependencies = [ + "clipboard-win", + "core-graphics", + "image", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "parking_lot", + "windows-sys 0.48.0", + "x11rb", +] + [[package]] name = "arg_enum_proc_macro" version = "0.3.4" @@ -363,9 +381,9 @@ dependencies = [ [[package]] name = "async-openai" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6db3286b4f52b6556ac5208fb575d035eca61a2bf40d7e75d1db2733ffc599f" +checksum = "1b17e44510f88a904cb3102a020d7ea11929dcddadfaff756e71112cb2cb7bd0" dependencies = [ "async-convert", "backoff", @@ -509,7 +527,7 @@ dependencies = [ "miniz_oxide 0.8.0", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -654,6 +672,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2", +] + [[package]] name = "blowfish" version = "0.9.1" @@ -896,7 +923,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1078,6 +1105,30 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + [[package]] name = "cpufeatures" version = "0.2.14" @@ -1603,7 +1654,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", ] [[package]] @@ -1612,6 +1684,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1810,6 +1888,16 @@ dependencies = [ "libm", ] +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -2459,7 +2547,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2905,6 +2993,105 @@ dependencies = [ "libc", ] +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + [[package]] name = "object" version = "0.36.5" @@ -2966,7 +3153,7 @@ checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.6.0", "cfg-if", - "foreign-types", + "foreign-types 0.3.2", "libc", "once_cell", "openssl-macros", @@ -3028,7 +3215,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3997,6 +4184,7 @@ checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" name = "rusty-buddy" version = "1.0.1" dependencies = [ + "arboard", "async-channel 2.3.1", "async-openai", "async-trait", @@ -5475,7 +5663,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5486,7 +5674,7 @@ checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5495,7 +5683,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5505,7 +5693,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ "windows-result", - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -5514,7 +5711,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5523,7 +5720,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -5532,28 +5744,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5566,24 +5796,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -5627,6 +5881,23 @@ dependencies = [ "tap", ] +[[package]] +name = "x11rb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +dependencies = [ + "gethostname", + "rustix", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/Cargo.toml b/Cargo.toml index 3f92a96..1ea1fe8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -async-openai = "0.24.0" +async-openai = "0.25.0" dotenvy = "0.15.7" clap = { version = "4", features = ["derive"] } clap_complete = "4" @@ -36,3 +36,4 @@ chrono-tz = "0.10" surrealdb = { version = "2.0", features = ["kv-rocksdb"] } async-channel = "2.3" fern = "0.6" +arboard = "3.4" diff --git a/docs/docs/commands.md b/docs/docs/commands.md index abb48c4..18b3d7b 100644 --- a/docs/docs/commands.md +++ b/docs/docs/commands.md @@ -104,13 +104,13 @@ You can also fetch knowledge before running a one-shot query to the AI. rusty-buddy chat --one-shot "Need help optimizing memory management" --knowledge ``` -### Slash Commands in Chat +## Slash Commands in Chat -Within a chat session, enhance your experience with the following slash commands: +Within a chat session, you can enhance your experience with the following slash commands: #### Renew Context -Refresh the chat context, clearing previous interactions and reloading specified directory files. +Refresh the current chat context to reload any previous interactions or settings: ``` /renew @@ -120,14 +120,13 @@ Refresh the chat context, clearing previous interactions and reloading specified Save code blocks from the assistant's last message to files. +- **Standard Mode:** The users will be prompted for each block. + ``` /save-files ``` -Options: - -- **Interactive Mode:** You'll be prompted for each code block. -- **Greedy Mode:** Quickly save all code blocks without prompts. +- **Greedy Mode:** Quickly save all code blocks without user prompts. ``` /save-files greedy @@ -145,7 +144,41 @@ Type the slash command within the chat interface. Use `exit` to end the session, --- -By using these updated options, you can maximize the efficiency and effectiveness of Rusty Buddy's chat functionality. Whether for quick responses or engaging full sessions with varied contexts, these enhancements enable comprehensive interaction with the AI capabilities. +#### Copy Last Message + +Copy the last message from the assistant to your clipboard. This command is useful for quickly storing a response that you may want to refer back to or use in another application. + +``` +/copy-last-message +``` + +**Key Points:** +- Copies the last assistant message directly to the clipboard using platform-specific clipboard access. +- Useful for efficiently using snippets from the conversation in other contexts or applications. + +#### Copy Files + +Extract and copy code blocks from the last assistant message to the clipboard. + +- **Standard Mode:** Iterate over each code block, presenting the user with an option to copy. + +``` +/copy-files +``` + +- **Greedy Mode:** Automatically copies all detected code blocks in the assistant message without prompt. + +``` +/copy-files greedy +``` + +**Key Points:** +- Designed to streamline the process of acquiring code snippets from chat sessions. +- Can dramatically speed up the workflow when working on multiple projects or tasks that involve frequent context-switching. + +--- + +Using these new commands, you can create a more efficient interaction loop, allowing Rusty Buddy to assist you with actionable insights and facilitating easy integration into your current workflow. By harnessing these capabilities, you greatly enhance the utility of the chat sessions, accessing and reusing information more effectively. --- diff --git a/extracted_content.txt b/extracted_content.txt deleted file mode 100644 index 40cc602..0000000 --- a/extracted_content.txt +++ /dev/null @@ -1,37 +0,0 @@ -//! This module defines a messaging system tailored for chat applications, -//! facilitating interactions between users and an AI assistant. It includes -//! message types and interfaces to send messages and manage chat sessions. -//! Utilizing the `async_trait` for asynchronous operations, alongside the -//! `serde` library for serialization and deserialization, the system supports -//! extensible message handling and session management. -//! -//! ## Key Components -//! -//! - **Message**: -//! Encapsulates the message's role (e.g., User, Assistant) and its content. -//! It also includes optional metadata through the `MessageInfo` struct, -//! which provides context about the message's origin and associated details. -//! -//! - **MessageRole**: -//! An enum that defines different roles a message may assume (e.g., System, User, Assistant), -//! allowing for clear distinction and handling of messages based on who authored them. -//! -//! - **MessageInfo**: -//! A structure containing additional contextual information about the message, including -//! the timestamp of creation and various model-related metadata. This aids in analytics -//! and debugging within chat sessions. -//! -//! - **ChatBackend**: -//! A trait that provides an interface for sending messages to a chat model asynchronously. -//! It facilitates the implementation of various backends, enabling flexible integrations -//! with models (e.g., OpenAI, Ollama). -//! -//! - **ChatStorage**: -//! A trait that facilitates management of chat sessions. It allows for loading, saving, -//! and listing chat sessions, ensuring state persistence across application runs. -//! -//! ## Examples -//! -//! This section illustrates how to create a new message and utilize the `ChatBackend` trait: -//! -//! \ No newline at end of file diff --git a/src/chat/commands/copy_files.rs b/src/chat/commands/copy_files.rs new file mode 100644 index 0000000..2fb35f7 --- /dev/null +++ b/src/chat/commands/copy_files.rs @@ -0,0 +1,64 @@ +use crate::chat::command::{ChatCommand, RegisterableCommand}; +use crate::chat::command_registry::CommandRegistry; +use crate::chat::message_helpers::find_last_assistant_message; +use crate::chat::service::ChatService; +use crate::cli::editor::get_user_input; +use arboard::Clipboard; +use regex::Regex; +use std::error::Error; + +pub struct CopyFilesCommand; + +impl CopyFilesCommand { + pub fn new() -> Self { + CopyFilesCommand {} + } + + fn copy_to_clipboard(content: &str) -> Result<(), Box> { + let mut clipboard = Clipboard::new()?; + clipboard.set_text(content.to_string())?; + Ok(()) + } +} + +impl ChatCommand for CopyFilesCommand { + fn execute(&self, args: &[&str], chat_service: &mut ChatService) -> Result<(), Box> { + let assistant_answer = + find_last_assistant_message(chat_service).ok_or("No assistant message found.")?; + + let greedy_mode = args.contains(&"greedy"); + let re = Regex::new(r"```(?s)(.*?)```")?; + + if greedy_mode { + if let Some(start) = assistant_answer.find("```") { + if let Some(end) = assistant_answer.rfind("```") { + if start < end { + let block_content = &assistant_answer[start + 3..end].trim(); + Self::copy_to_clipboard(block_content)?; + } + } + } + } else { + let mut counter = 1; + for cap in re.captures_iter(&assistant_answer) { + let block_content = &cap[1]; + Self::copy_to_clipboard(block_content)?; + println!("Copied code block {}", counter); + get_user_input("Press enter for next block: ")?; + counter += 1; + } + } + Ok(()) + } +} + +impl RegisterableCommand for CopyFilesCommand { + fn register_with_registry(registry: &mut CommandRegistry) { + let command = CopyFilesCommand::new(); + registry.register_command( + "/copy-files", + Box::new(command), + vec!["copy-files".to_string(), "copy-files greedy".to_string()], + ); + } +} diff --git a/src/chat/commands/copy_last_answer.rs b/src/chat/commands/copy_last_answer.rs new file mode 100644 index 0000000..6ab080b --- /dev/null +++ b/src/chat/commands/copy_last_answer.rs @@ -0,0 +1,47 @@ +use crate::chat::command::{ChatCommand, RegisterableCommand}; +use crate::chat::command_registry::CommandRegistry; +use crate::chat::message_helpers::find_last_assistant_message; +use crate::chat::service::ChatService; +use arboard::Clipboard; +use std::error::Error; + +pub struct CopyLastMessageCommand; + +impl CopyLastMessageCommand { + pub fn new() -> Self { + CopyLastMessageCommand {} + } + + fn copy_to_clipboard(content: &str) -> Result<(), Box> { + let mut clipboard = Clipboard::new()?; + clipboard.set_text(content.to_string())?; + Ok(()) + } +} + +impl ChatCommand for CopyLastMessageCommand { + fn execute( + &self, + _args: &[&str], + chat_service: &mut ChatService, + ) -> Result<(), Box> { + if let Some(last_message) = find_last_assistant_message(chat_service) { + Self::copy_to_clipboard(&last_message)?; + println!("Last assistant message copied to clipboard."); + } else { + println!("No assistant message to copy."); + } + Ok(()) + } +} + +impl RegisterableCommand for CopyLastMessageCommand { + fn register_with_registry(registry: &mut CommandRegistry) { + let command = CopyLastMessageCommand::new(); + registry.register_command( + "/copy-last-message", + Box::new(command), + vec!["copy-last-message".to_string()], + ); + } +} diff --git a/src/chat/commands/mod.rs b/src/chat/commands/mod.rs index 7d34813..88ca32c 100644 --- a/src/chat/commands/mod.rs +++ b/src/chat/commands/mod.rs @@ -31,10 +31,14 @@ use crate::chat::command::RegisterableCommand; use crate::chat::command_registry::CommandRegistry; +use crate::chat::commands::copy_files::CopyFilesCommand; +use crate::chat::commands::copy_last_answer::CopyLastMessageCommand; use crate::chat::commands::refresh::RenewCommand; use crate::chat::commands::save_files::SaveFilesCommand; use crate::chat::commands::save_last_answer::SaveLastAnswerCommand; +mod copy_files; +mod copy_last_answer; mod refresh; mod save_files; mod save_last_answer; @@ -44,4 +48,6 @@ pub fn initialize_commands(registry: &mut CommandRegistry) { RenewCommand::register_with_registry(registry); SaveFilesCommand::register_with_registry(registry); SaveLastAnswerCommand::register_with_registry(registry); + CopyFilesCommand::register_with_registry(registry); + CopyLastMessageCommand::register_with_registry(registry); } diff --git a/src/chat/commands/save_files.rs b/src/chat/commands/save_files.rs index 0dcf46f..3cbf123 100644 --- a/src/chat/commands/save_files.rs +++ b/src/chat/commands/save_files.rs @@ -89,7 +89,6 @@ fn save_block(block_content: &str) -> Result<(), Box> { fn prompt_and_save_block(index: usize, block_content: &str) -> Result<(), Box> { println!("Found code block #{}:", index + 1); - println!("{}", block_content); if get_user_input("Do you want to save this code block? (y/n): ")? .trim()