use super::config::OutputMode;
use crate::error::Result;
use crate::input::Keyboard;
pub struct OutputHandler {
mode: OutputMode,
keyboard: Keyboard,
}
impl OutputHandler {
pub fn new(mode: OutputMode) -> Result<Self> {
let keyboard = Keyboard::new()?;
Ok(Self { mode, keyboard })
}
pub fn mode(&self) -> OutputMode {
self.mode
}
pub fn set_mode(&mut self, mode: OutputMode) {
self.mode = mode;
}
pub fn output(&self, text: &str) -> Result<()> {
if text.is_empty() {
return Ok(());
}
match self.mode {
OutputMode::Keystrokes => {
self.type_text(text)?;
}
OutputMode::Clipboard => {
self.copy_to_clipboard(text)?;
}
OutputMode::Both => {
self.copy_to_clipboard(text)?;
self.paste()?;
}
OutputMode::Logger => {
log::info!("STT Output (Logger): \"{}\"", truncate_for_log(text, 100));
}
}
Ok(())
}
fn type_text(&self, text: &str) -> Result<()> {
log::info!("Typing text: \"{}\"", truncate_for_log(text, 50));
self.keyboard.type_string(text)?;
Ok(())
}
fn copy_to_clipboard(&self, text: &str) -> Result<()> {
log::info!("Copying to clipboard: \"{}\"", truncate_for_log(text, 50));
crate::clipboard::set_text(text)?;
Ok(())
}
fn paste(&self) -> Result<()> {
log::info!("Pasting from clipboard");
#[cfg(target_os = "macos")]
{
self.keyboard.key_tap("v", Some(&["command".to_string()]))?;
}
#[cfg(not(target_os = "macos"))]
{
self.keyboard.key_tap("v", Some(&["control".to_string()]))?;
}
Ok(())
}
}
fn truncate_for_log(text: &str, max_len: usize) -> String {
if text.len() <= max_len { text.to_string() } else { format!("{}...", &text[..max_len]) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_truncate_for_log() {
assert_eq!(truncate_for_log("short", 10), "short");
assert_eq!(truncate_for_log("this is a long string", 10), "this is a ...");
}
#[test]
fn test_output_mode() {
if let Ok(handler) = OutputHandler::new(OutputMode::Keystrokes) {
assert_eq!(handler.mode(), OutputMode::Keystrokes);
}
}
}