From 68a1d98a3dd583c506447e8035f07ea05408f4dd Mon Sep 17 00:00:00 2001 From: sigoden Date: Wed, 27 Mar 2024 11:20:00 +0800 Subject: feat: add repl command `.save session` (#382) --- README.md | 5 +++-- src/config/mod.rs | 39 +++++++++++++++++++++++++++------------ src/config/session.rs | 3 --- src/repl/mod.rs | 30 ++++++++++++++++++++++++++---- 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a7139fb..7d79309 100644 --- a/README.md +++ b/README.md @@ -253,10 +253,11 @@ The REPL supports: .info Print system info .model Switch LLM model .role Use a role -.info role Show role info +.info role Show the role info .exit role Leave current role .session Start a context-aware chat session -.info session Show session info +.info session Show the session info +.save session Save the session to the file .clear messages Clear messages in the session .exit session End the current session .file Attach files to the message and then submit it diff --git a/src/config/mod.rs b/src/config/mod.rs index 2bde0f7..b18bc74 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -423,7 +423,7 @@ impl Config { } } - pub fn sys_info(&self) -> Result { + pub fn system_info(&self) -> Result { let display_path = |path: &Path| path.display().to_string(); let wrap = self .wrap @@ -485,7 +485,7 @@ impl Config { } else if let Some(role) = &self.role { role.export() } else { - self.sys_info() + self.system_info() } } @@ -647,17 +647,18 @@ impl Config { session.name = Text::new("Session name:").prompt()?; } } - let session_path = Self::session_file(session.name())?; - let sessions_dir = session_path.parent().ok_or_else(|| { - anyhow!("Unable to save session file to {}", session_path.display()) - })?; - if !sessions_dir.exists() { - create_dir_all(sessions_dir).with_context(|| { - format!("Failed to create session_dir '{}'", sessions_dir.display()) - })?; - } - session.save(&session_path)?; + Self::save_session_to_file(&mut session)?; + } + } + Ok(()) + } + + pub fn save_session(&mut self, name: &str) -> Result<()> { + if let Some(session) = self.session.as_mut() { + if !name.is_empty() { + session.name = name.to_string(); } + Self::save_session_to_file(session)?; } Ok(()) } @@ -870,6 +871,20 @@ impl Config { .with_context(|| format!("Failed to create/append {}", path.display())) } + fn save_session_to_file(session: &mut Session) -> Result<()> { + let session_path = Self::session_file(session.name())?; + let sessions_dir = session_path + .parent() + .ok_or_else(|| anyhow!("Unable to save session file to {}", session_path.display()))?; + if !sessions_dir.exists() { + create_dir_all(sessions_dir).with_context(|| { + format!("Failed to create session_dir '{}'", sessions_dir.display()) + })?; + } + session.save(&session_path)?; + Ok(()) + } + fn load_config(config_path: &Path) -> Result { let ctx = || format!("Failed to load config at {}", config_path.display()); let content = read_to_string(config_path).with_context(ctx)?; diff --git a/src/config/session.rs b/src/config/session.rs index 6ab855c..801615f 100644 --- a/src/config/session.rs +++ b/src/config/session.rs @@ -241,9 +241,6 @@ impl Session { } pub fn save(&mut self, session_path: &Path) -> Result<()> { - if !self.dirty { - return Ok(()); - } self.path = Some(session_path.display().to_string()); let content = serde_yaml::to_string(&self) diff --git a/src/repl/mod.rs b/src/repl/mod.rs index 0a601c7..1b96d3b 100644 --- a/src/repl/mod.rs +++ b/src/repl/mod.rs @@ -25,19 +25,28 @@ use std::{env, process}; const MENU_NAME: &str = "completion_menu"; lazy_static! { - static ref REPL_COMMANDS: [ReplCommand; 14] = [ + static ref REPL_COMMANDS: [ReplCommand; 15] = [ ReplCommand::new(".help", "Print this help message", State::all()), ReplCommand::new(".info", "Print system info", State::all()), ReplCommand::new(".model", "Switch LLM model", State::all()), ReplCommand::new(".role", "Use a role", State::able_change_role()), - ReplCommand::new(".info role", "Show role info", State::in_role(),), + ReplCommand::new(".info role", "Show the role info", State::in_role(),), ReplCommand::new(".exit role", "Leave current role", State::in_role(),), ReplCommand::new( ".session", "Start a context-aware chat session", State::not_in_session(), ), - ReplCommand::new(".info session", "Show session info", State::in_session(),), + ReplCommand::new( + ".info session", + "Show the session info", + State::in_session(), + ), + ReplCommand::new( + ".save session", + "Save the session to the file", + State::in_session(), + ), ReplCommand::new( ".clear messages", "Clear messages in the session", @@ -160,7 +169,7 @@ impl Repl { } Some(_) => unknown_command()?, None => { - let output = self.config.read().sys_info()?; + let output = self.config.read().system_info()?; println!("{}", output); } }, @@ -187,6 +196,19 @@ impl Repl { ".session" => { self.config.write().start_session(args)?; } + ".save" => { + match args.map(|v| match v.split_once(' ') { + Some((subcmd, args)) => (subcmd, args.trim()), + None => (v, ""), + }) { + Some(("session", name)) => { + self.config.write().save_session(name)?; + } + _ => { + println!(r#"Usage: .save session [name]"#) + } + } + } ".set" => { if let Some(args) = args { self.config.write().update(args)?; -- cgit v1.2.3