Skip to main content

fur_cli/commands/
chat.rs

1use chrono::Utc;
2use colored::*;
3use std::fs;
4use std::io::{self, Read, Write};
5use std::path::Path;
6
7use crate::commands::jot::{self, JotArgs};
8
9/// Interactive chat-style jot for long / structured messages
10pub fn run_chat(avatar: Option<String>) {
11    println!(
12        "{}",
13        "💬 Write / Copy-Paste your Markdown or text below.".bright_cyan()
14    );
15    println!(
16        "{}",
17        "↪ Finish with Ctrl+D (Linux/macOS) or Ctrl+Z then Enter (Windows).".white()
18    );
19    println!("{}", "↪ Press Ctrl+C to cancel.".white());
20
21    // --- Capture multi-line input
22    let mut buffer = String::new();
23    io::stdin().read_to_string(&mut buffer).unwrap();
24
25    if buffer.trim().is_empty() {
26        println!("⚠️ No content provided. Aborting.");
27        return;
28    }
29
30    // --- Confirm
31    print!("You have finished writing. Continue? [Y/n]: ");
32    io::stdout().flush().unwrap();
33    let mut confirm = String::new();
34    io::stdin().read_line(&mut confirm).unwrap();
35    if confirm.trim().eq_ignore_ascii_case("n") {
36        println!("❌ Cancelled.");
37        return;
38    }
39
40    // --- Filename suggestion
41    //
42    // viceroy: long-form files used to land in `chats/` root and were then
43    // *copied* into the conversation folder, leaving the original behind as an
44    // orphan that rebuild could not see but `lock` still encrypted. They are
45    // written straight into `chats/<slug>/` now.
46    let folder = crate::schema::bridge::active_folder(Path::new("."))
47        .unwrap_or_else(|| Path::new("chats").to_path_buf());
48
49    let default_name = folder
50        .join(format!("CHAT-{}.md", Utc::now().format("%Y%m%d-%H%M%S")))
51        .to_string_lossy()
52        .to_string();
53
54    println!("Save as? (default: {})", default_name);
55    print!("> ");
56    io::stdout().flush().unwrap();
57    let mut fname = String::new();
58    io::stdin().read_line(&mut fname).unwrap();
59    let fname = fname.trim();
60    let path = if fname.is_empty() {
61        default_name
62    } else {
63        fname.to_string()
64    };
65
66    // Ensure the destination dir exists
67    if let Some(parent) = Path::new(&path).parent() {
68        fs::create_dir_all(parent).ok();
69    }
70
71    fs::write(&path, &buffer).expect("❌ Failed to write file");
72    println!("💾 Saved to {}", path.green());
73
74    // --- Reuse jot logic to attach to conversation
75    let args = JotArgs {
76        avatar,
77        positional_text: None,
78        text: None,
79        markdown: Some(path),
80        img: None,
81        parent: None,
82    };
83    jot::run_jot(args);
84}