refactor: replace dump with print_now! (#35)

This commit is contained in:
sigoden 2023-03-08 11:58:50 +08:00 committed by GitHub
parent b7cb6f89f1
commit f694a59dcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 48 additions and 37 deletions

View File

@ -163,9 +163,9 @@ impl Config {
Some(role) => { Some(role) => {
let output = format!("{}>> {}", role.name, role.prompt.trim()); let output = format!("{}>> {}", role.name, role.prompt.trim());
self.role = Some(role); self.role = Some(role);
format!("{}\n", output.trim()) output
} }
None => "Error: Unknown role\n".into(), None => "Error: Unknown role".into(),
} }
} }
@ -278,7 +278,7 @@ impl Config {
let value = value.parse().with_context(|| "Invalid value")?; let value = value.parse().with_context(|| "Invalid value")?;
self.dry_run = value; self.dry_run = value;
} }
_ => return Ok(format!("Error: Unknown key `{key}`\n")), _ => return Ok(format!("Error: Unknown key `{key}`")),
} }
Ok("".into()) Ok("".into())
} }

View File

@ -4,6 +4,7 @@ mod config;
mod render; mod render;
mod repl; mod repl;
mod term; mod term;
#[macro_use]
mod utils; mod utils;
use std::cell::RefCell; use std::cell::RefCell;

View File

@ -1,6 +1,6 @@
use super::MarkdownRender; use super::MarkdownRender;
use crate::print_now;
use crate::repl::{ReplyStreamEvent, SharedAbortSignal}; use crate::repl::{ReplyStreamEvent, SharedAbortSignal};
use crate::utils::dump;
use anyhow::Result; use anyhow::Result;
use crossbeam::channel::Receiver; use crossbeam::channel::Receiver;
@ -20,7 +20,7 @@ pub fn cmd_render_stream(rx: Receiver<ReplyStreamEvent>, abort: SharedAbortSigna
let mut lines: Vec<&str> = text.split('\n').collect(); let mut lines: Vec<&str> = text.split('\n').collect();
buffer = lines.pop().unwrap_or_default().to_string(); buffer = lines.pop().unwrap_or_default().to_string();
let output = lines.join("\n"); let output = lines.join("\n");
dump(markdown_render.render(&output), 1); print_now!("{}\n", markdown_render.render(&output))
} else { } else {
buffer = format!("{buffer}{text}"); buffer = format!("{buffer}{text}");
if !(markdown_render.is_code_block() if !(markdown_render.is_code_block()
@ -30,7 +30,7 @@ pub fn cmd_render_stream(rx: Receiver<ReplyStreamEvent>, abort: SharedAbortSigna
|| buffer.starts_with('|')) || buffer.starts_with('|'))
{ {
if let Some((output, remain)) = split_line(&buffer) { if let Some((output, remain)) = split_line(&buffer) {
dump(markdown_render.render_line_stateless(&output), 0); print_now!("{}", markdown_render.render_line_stateless(&output));
buffer = remain buffer = remain
} }
} }
@ -38,7 +38,7 @@ pub fn cmd_render_stream(rx: Receiver<ReplyStreamEvent>, abort: SharedAbortSigna
} }
ReplyStreamEvent::Done => { ReplyStreamEvent::Done => {
let output = markdown_render.render(&buffer); let output = markdown_render.render(&buffer);
dump(output, 2); print_now!("{}\n\n", output);
break; break;
} }
} }

View File

@ -1,7 +1,7 @@
use crate::client::ChatGptClient; use crate::client::ChatGptClient;
use crate::config::SharedConfig; use crate::config::SharedConfig;
use crate::print_now;
use crate::render::render_stream; use crate::render::render_stream;
use crate::utils::dump;
use anyhow::Result; use anyhow::Result;
use crossbeam::channel::Sender; use crossbeam::channel::Sender;
@ -67,23 +67,28 @@ impl ReplCmdHandler {
} }
ReplCmd::SetRole(name) => { ReplCmd::SetRole(name) => {
let output = self.config.borrow_mut().change_role(&name); let output = self.config.borrow_mut().change_role(&name);
dump(output, 1); print_now!("{}\n\n", output.trim_end());
} }
ReplCmd::ClearRole => { ReplCmd::ClearRole => {
self.config.borrow_mut().role = None; self.config.borrow_mut().role = None;
dump("", 1); print_now!("\n");
} }
ReplCmd::Prompt(prompt) => { ReplCmd::Prompt(prompt) => {
self.config.borrow_mut().create_temp_role(&prompt); self.config.borrow_mut().create_temp_role(&prompt);
dump("", 1); print_now!("\n");
} }
ReplCmd::Info => { ReplCmd::Info => {
let output = self.config.borrow().info()?; let output = self.config.borrow().info()?;
dump(output, 1); print_now!("{}\n\n", output.trim_end());
} }
ReplCmd::UpdateConfig(input) => { ReplCmd::UpdateConfig(input) => {
let output = self.config.borrow_mut().update(&input)?; let output = self.config.borrow_mut().update(&input)?;
dump(output, 1); let output = output.trim();
if output.is_empty() {
print_now!("\n");
} else {
print_now!("{}\n\n", output);
}
} }
} }
Ok(()) Ok(())
@ -111,7 +116,7 @@ impl ReplyStreamHandler {
let _ = tx.send(ReplyStreamEvent::Text(text.to_string())); let _ = tx.send(ReplyStreamEvent::Text(text.to_string()));
} }
None => { None => {
dump(text, 0); print_now!("{}", text);
} }
} }
self.buffer.push_str(text); self.buffer.push_str(text);
@ -123,7 +128,11 @@ impl ReplyStreamHandler {
let _ = tx.send(ReplyStreamEvent::Done); let _ = tx.send(ReplyStreamEvent::Done);
} }
None => { None => {
dump("", 2); if self.buffer.ends_with('\n') {
print_now!("\n");
} else {
print_now!("\n\n");
}
} }
} }
} }

View File

@ -4,8 +4,8 @@ mod init;
use crate::client::ChatGptClient; use crate::client::ChatGptClient;
use crate::config::SharedConfig; use crate::config::SharedConfig;
use crate::print_now;
use crate::term; use crate::term;
use crate::utils::dump;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use reedline::{DefaultPrompt, Reedline, Signal}; use reedline::{DefaultPrompt, Reedline, Signal};
@ -36,11 +36,8 @@ impl Repl {
pub fn run(&mut self, client: ChatGptClient, config: SharedConfig) -> Result<()> { pub fn run(&mut self, client: ChatGptClient, config: SharedConfig) -> Result<()> {
let abort = AbortSignal::new(); let abort = AbortSignal::new();
let handler = ReplCmdHandler::init(client, config, abort.clone())?; let handler = ReplCmdHandler::init(client, config, abort.clone())?;
dump( print_now!("Welcome to aichat {}\n", env!("CARGO_PKG_VERSION"));
format!("Welcome to aichat {}", env!("CARGO_PKG_VERSION")), print_now!("Type \".help\" for more information.\n");
1,
);
dump("Type \".help\" for more information.", 1);
let mut already_ctrlc = false; let mut already_ctrlc = false;
let handler = Arc::new(handler); let handler = Arc::new(handler);
loop { loop {
@ -63,7 +60,7 @@ impl Repl {
} }
Err(err) => { Err(err) => {
let err = format!("{err:?}"); let err = format!("{err:?}");
dump(err.trim(), 2); print_now!("{}\n\n", err.trim());
} }
} }
} }
@ -71,7 +68,7 @@ impl Repl {
abort.set_ctrlc(); abort.set_ctrlc();
if !already_ctrlc { if !already_ctrlc {
already_ctrlc = true; already_ctrlc = true;
dump("(To exit, press Ctrl+C again or Ctrl+D or type .exit)", 2); print_now!("(To exit, press Ctrl+C again or Ctrl+D or type .exit)\n\n");
} else { } else {
break; break;
} }
@ -104,18 +101,18 @@ impl Repl {
Some("history") => { Some("history") => {
let history = Box::new(self.editor.history_mut()); let history = Box::new(self.editor.history_mut());
history.clear().with_context(|| "Failed to clear history")?; history.clear().with_context(|| "Failed to clear history")?;
dump("", 1); print_now!("\n");
} }
Some("role") => handler.handle(ReplCmd::ClearRole)?, Some("role") => handler.handle(ReplCmd::ClearRole)?,
_ => dump_unknown_command(), _ => dump_unknown_command(),
}, },
".history" => { ".history" => {
self.editor.print_history()?; self.editor.print_history()?;
dump("", 1); print_now!("\n");
} }
".role" => match args { ".role" => match args {
Some(name) => handler.handle(ReplCmd::SetRole(name.to_string()))?, Some(name) => handler.handle(ReplCmd::SetRole(name.to_string()))?,
None => dump("Usage: .role <name>", 2), None => print_now!("Usage: .role <name>\n\n"),
}, },
".info" => { ".info" => {
handler.handle(ReplCmd::Info)?; handler.handle(ReplCmd::Info)?;
@ -123,7 +120,7 @@ impl Repl {
".editor" => { ".editor" => {
let mut text = args.unwrap_or_default().to_string(); let mut text = args.unwrap_or_default().to_string();
if text.is_empty() { if text.is_empty() {
dump("Usage: .editor { <your multiline/paste content> }", 2); print_now!("Usage: .editor {{ <your multiline/paste content here> }}\n\n");
} else { } else {
if text.starts_with('{') && text.ends_with('}') { if text.starts_with('{') && text.ends_with('}') {
text = text[1..text.len() - 1].to_string() text = text[1..text.len() - 1].to_string()
@ -137,7 +134,7 @@ impl Repl {
".prompt" => { ".prompt" => {
let mut text = args.unwrap_or_default().to_string(); let mut text = args.unwrap_or_default().to_string();
if text.is_empty() { if text.is_empty() {
dump("Usage: .prompt { <your multiline/paste content> }.", 2); print_now!("Usage: .prompt {{ <your content here> }}.\n\n");
} else { } else {
if text.starts_with('{') && text.ends_with('}') { if text.starts_with('{') && text.ends_with('}') {
text = text[1..text.len() - 1].to_string() text = text[1..text.len() - 1].to_string()
@ -156,10 +153,7 @@ impl Repl {
} }
fn dump_unknown_command() { fn dump_unknown_command() {
dump( print_now!("Error: Unknown command. Type \".help\" for more information.\n\n");
"Error: Unknown command. Type \".help\" for more information.",
2,
);
} }
fn dump_repl_help() { fn dump_repl_help() {
@ -168,8 +162,8 @@ fn dump_repl_help() {
.map(|(name, desc, _)| format!("{name:<15} {desc}")) .map(|(name, desc, _)| format!("{name:<15} {desc}"))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("\n"); .join("\n");
dump( print_now!(
format!("{head}\n\nPress Ctrl+C to abort session, Ctrl+D to exit the REPL"), "{}\n\nPress Ctrl+C to abort session, Ctrl+D to exit the REPL\n\n",
2, head,
); );
} }

View File

@ -1,8 +1,15 @@
use chrono::prelude::*; use chrono::prelude::*;
use std::io::{stdout, Write}; use std::io::{stdout, Write};
pub fn dump<T: ToString>(text: T, newlines: usize) { #[macro_export]
print!("{}{}", text.to_string(), "\n".repeat(newlines)); macro_rules! print_now {
($($arg:tt)*) => {
$crate::utils::print_now(&format!($($arg)*))
};
}
pub fn print_now<T: ToString>(text: T) {
print!("{}", text.to_string());
let _ = stdout().flush(); let _ = stdout().flush();
} }