summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsigoden <sigoden@gmail.com>2023-03-05 11:11:15 +0800
committerGitHub <noreply@github.com>2023-03-05 11:11:15 +0800
commit2ac0155fa357a656e11422cfe6ee07fcd357109a (patch)
tree4feaac76437fb4ae8255fda30559e7708bc5ba16
parentd876818df17ad7b25ebb38a678aa23c79b826e38 (diff)
downloadaichat-2ac0155fa357a656e11422cfe6ee07fcd357109a.tar.gz
feat: accept pipe (#17)
`cat data | aichat` works
-rw-r--r--Cargo.lock21
-rw-r--r--Cargo.toml1
-rw-r--r--README.md47
-rw-r--r--src/main.rs13
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",
@@ -116,6 +117,17 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -889,6 +901,15 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
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 <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),
+ }
}
}