From 2ac0155fa357a656e11422cfe6ee07fcd357109a Mon Sep 17 00:00:00 2001 From: sigoden Date: Sun, 5 Mar 2023 11:11:15 +0800 Subject: feat: accept pipe (#17) `cat data | aichat` works --- Cargo.lock | 21 +++++++++++++++++++++ Cargo.toml | 1 + README.md | 47 +++++++++++++++++++++++++++++++++++++---------- src/main.rs | 13 ++++++++++--- 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59b257f..4055154 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,7 @@ name = "aichat" version = "0.2.0" dependencies = [ "anyhow", + "atty", "bytes", "chrono", "clap", @@ -115,6 +116,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -887,6 +899,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.2.6" diff --git a/Cargo.toml b/Cargo.toml index d70b5ea..68d80ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ crossbeam = "0.8.2" crossterm = "0.26.1" copypasta = "0.8.2" chrono = "0.4.23" +atty = "0.2.14" [dependencies.syntect] version = "5.0.0" diff --git a/README.md b/README.md index aeb9e28..b33ce1d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Chat with ChatGPT-3.5 in the terminal. -![demo](https://user-images.githubusercontent.com/4012553/222897111-dd5015a0-abc1-4c65-a0fb-d491aba3c427.gif) +![demo](https://user-images.githubusercontent.com/4012553/222935716-33dc37df-f58d-4a66-8917-f741fd69682d.gif) ## Install @@ -22,11 +22,9 @@ Download from [Github Releases](https://github.com/sigoden/aichat/releases), unz ## Features - Compared to the browser, the terminal starts faster and needs less resources. -- Interactive chat and imperative query. -- Support highlight. -- Predefine prompts for role playing. -- History query/completion. -- Persist chat messages. +- Highlight chat message and stream. +- Define roles and let AI play them. +- Save chat messages. - Support proxy. - Written in rust, single executable file, cross-platform. @@ -81,16 +79,45 @@ We can predefine a batch of roles in `roles.yaml`. For example, we define a emoj Let ChatGPT answer questions in the role of a emoji translator ``` -$ aichat --role emoji I am very angry +〉.role emoji + +〉I am very angry 😠💢👿 ``` -In interactive chat, we do this: +## CLI ``` -〉.role emoji +Chat with OpenAI GPT-3.5 in the terminal. -〉I am very angry +Usage: aichat [OPTIONS] [TEXT]... + +Arguments: + [TEXT]... Input text, if no input text, enter interactive mode + +Options: + -L, --list-roles List all roles + -r, --role Specify the role that the AI will play + -h, --help Print help + -V, --version Print version +``` + +Interactive chat if no text input: +``` +$ aichat +Welcome to aichat x.x.x +Type ".help" for more information. +〉 +``` + +Imperative request data: +``` +aichat --role emoji I am very angry +``` + +Accept pipe: +``` +cat text | aichat ``` ## License diff --git a/src/main.rs b/src/main.rs index dc54b01..8dfa2fd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod repl; mod term; mod utils; +use std::io::{stdin, Read}; use std::sync::Arc; use std::{io::stdout, process::exit}; @@ -43,9 +44,15 @@ fn start() -> Result<()> { None => None, }; let client = ChatGptClient::init(config.clone())?; - match text { - Some(text) => start_directive(client, config, role, &text), - None => start_interactive(client, config, role), + if atty::isnt(atty::Stream::Stdin) { + let mut text = String::new(); + stdin().read_to_string(&mut text)?; + start_directive(client, config, role, &text) + } else { + match text { + Some(text) => start_directive(client, config, role, &text), + None => start_interactive(client, config, role), + } } } -- cgit v1.2.3