1use std::fs;
2use colored::*;
3use crate::frs::{parser, persist_frs};
4use crate::commands::{timeline, tree};
5use crate::commands::timeline::TimelineArgs;
6use crate::commands::tree::TreeArgs;
7
8pub fn run_frs(path: &str) {
14 let raw = fs::read_to_string(path)
15 .unwrap_or_else(|_| panic!("❌ Could not read .frs file: {}", path));
16
17 let lines: Vec<String> = raw
18 .lines()
19 .map(|l| l.trim().to_string())
20 .filter(|l| !l.is_empty() && !l.starts_with('#'))
21 .collect();
22
23 let conversation = parser::parse_frs(path);
24 let mut stored = false;
25
26 for (lineno, line) in lines.iter().enumerate() {
27 if line == "store" {
29 if !stored {
30 let tid = persist_frs(&conversation);
31 println!("✔️ Thread persisted at line {} → {}", lineno + 1, &tid[..8]);
32 stored = true;
33 } else {
34 eprintln!(
35 "{}",
36 format!("⚠️ Ignoring extra `store` at line {} — already persisted", lineno + 1)
37 .yellow()
38 .bold()
39 );
40 }
41 continue;
42 }
43
44 if line.starts_with("status") {
46 with_ephemeral(stored, &conversation, |tid_override| {
47 let args = crate::commands::status::StatusArgs {
48 conversation_override: tid_override,
49 };
50 crate::commands::status::run_status(args);
51 });
52 continue;
53 }
54
55 if line.starts_with("timeline") {
57 let parts: Vec<&str> = line.split_whitespace().collect();
58 let mut args = TimelineArgs {
59 verbose: false,
60 contents: false,
61 out: None,
62 conversation_override: None,
63 };
64 for (i, p) in parts.iter().enumerate() {
65 if *p == "--out" {
66 args.out = parts.get(i + 1).map(|s| s.to_string());
67 }
68 if *p == "--contents" {
69 args.contents = true;
70 }
71 }
72
73 with_ephemeral(stored, &conversation, |tid_override| {
74 let mut args = args.clone();
75 args.conversation_override = tid_override;
76 timeline::run_timeline(args);
77 });
78 continue;
79 }
80
81 if line.starts_with("tree") {
83 let args = TreeArgs { conversation_override: None };
84 with_ephemeral(stored, &conversation, |tid_override| {
85 let mut args = args.clone();
86 args.conversation_override = tid_override;
87 tree::run_tree(args);
88 });
89 continue;
90 }
91
92 }
94
95 if !stored {
96 eprintln!("{}", "⚠️ Script finished without a `store` — nothing persisted.".yellow());
97 }
98}
99
100fn with_ephemeral<F>(stored: bool, conversation: &crate::frs::ast::Thread, mut f: F)
102where
103 F: FnMut(Option<String>),
104{
105 if !stored {
106 let tid = crate::frs::persist::persist_ephemeral(conversation);
107 f(Some(tid.clone()));
108 crate::frs::persist::cleanup_ephemeral(&tid);
109 } else {
110 f(None);
111 }
112}