Skip to content

Commit e1d376c

Browse files
committed
Add CLI tests
1 parent cf06bf1 commit e1d376c

File tree

4 files changed

+78
-73
lines changed

4 files changed

+78
-73
lines changed

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ license = "MIT"
77

88
[dependencies]
99
clap = { version = "4.5.29", features = ["derive"] }
10-
transformrs = "0.5.0"
1110
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
11+
transformrs = "0.5.0"
1212

1313
[dev-dependencies]
14+
assert_cmd = "2"
15+
predicates = "3"
1416
pretty_assertions = "1"

README.md

Lines changed: 11 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,24 @@
1-
2-
<h1 align="center"><b>
3-
NOTE
4-
</b></h1>
5-
6-
<h3 align="center">
7-
Instead of using <code>ata</code>, I would advice most people to use
8-
<a href="https://github.com/simonw/llm"><code>llm</code></a>
9-
by Simon Willison instead.
10-
It supports more models and ways to interact with models.
11-
</h3>
12-
13-
<br>
14-
<br>
15-
<br>
16-
171
<h1 align="center"><code>ata</code>: Ask the Terminal Anything</h1>
182

19-
<h3 align="center">ChatGPT in the terminal</h3>
20-
21-
<p align="center">
22-
<a href="https://asciinema.org/a/565384"><img src="https://asciinema.org/a/565384.svg" alt="asciicast"></a>
23-
</p>
24-
25-
<h3 align=center>
26-
TIP:<br>
27-
Run a terminal with this tool in your background and show/hide it with a keypress.<br>
28-
This can be done via: Iterm2 (Mac), Guake (Ubuntu), scratchpad (i3/sway), or the quake mode for the Windows Terminal.
29-
</h3>
30-
31-
## Productivity benefits
32-
33-
- The terminal starts more quickly and requires **less resources** than a browser.
34-
- The **keyboard shortcuts** allow for quick interaction with the query. For example, press `CTRL + c` to cancel the stream, `CTRL + ↑` to get the previous query again, and `CTRL + w` to remove the last word.
35-
- A terminal can be set to **run in the background and show/hide with one keypress**. To do this, use iTerm2 (Mac), Guake (Ubuntu), scratchpad (i3/sway), or the quake mode for the Windows Terminal.
36-
- The prompts are **reproducible** because each prompt is sent as a stand-alone prompt without history. Tweaking the prompt can be done by pressing `CTRL + ↑` and making changes.
37-
38-
## Usage
3+
<h3 align="center">Use AI in the terminal</h3>
394

40-
Download the binary for your system from [Releases](https://github.com/rikhuijzer/ata/releases).
41-
Or use your package manager to install the application.
42-
For example, Brew on MacOS or AUR on Arch Linux have packages available.
5+
## Philosophy
436

44-
To specify the API key and some basic model settings, start the application.
45-
It should give an error and the option to create a configuration file called `ata.toml` for you.
46-
Press `y` and `ENTER` to create a `ata.toml` file.
7+
The philosophy of this project is mainly to not handle state.
8+
Like curl or ffmpeg, this should make it easier to use in scripts and to share examples online.
9+
Settings are done via command line arguments and environment variables.
4710

48-
Next, request an API key via <https://platform.openai.com/api-keys> and update the key in the example configuration file.
49-
They key permissions can be "Restricted" to only "Model capabilities".
11+
## Goals (not implemented yet)
5012

51-
For more information, see:
13+
Use the OpenAI API to generate audio from text (text to speech).
5214

5315
```sh
54-
$ ata --help
16+
$ OPENAI_KEY=<KEY> cat myfile.txt | ata --tts
5517
```
5618

57-
## FAQ
58-
59-
**How much will I have to pay for the API?**
60-
61-
Using OpenAI's API for chat is very cheap.
62-
Let's say that an average response is about 500 tokens, so costs about $0.015 (with GPT-4).
63-
That means that if you do 50 requests per day, then that will cost you about $0.75 per day ($15 per month assuming you only use it only on workdays).
64-
If you use GPT-3.5, then the costs will be much lower.
65-
66-
**How does this compare to LLM-based search engines such as You.com or Bing Chat?**
67-
68-
At the time of writing, the OpenAI API responds much quicker than the large language model-based search engines and contains no adds.
69-
It is particularly useful to quickly look up some things like Unicode symbols, historical facts, or word meanings.
70-
71-
**Can I build the binary myself?**
72-
73-
Yes, you can clone the repository and build the project via [`Cargo`](https://github.com/rust-lang/cargo).
74-
Make sure that you have `Cargo` installed and then run:
19+
Here, `ata` will try to do `tts` (text to speech) on the input text.
20+
Because only the `OPENAI_KEY` is provided, it will use some default OpenAI model to get the audio.
7521

7622
```sh
77-
$ git clone https://github.com/rikhuijzer/ata.git
78-
79-
$ cd ata/
80-
81-
$ cargo build --release
23+
$ OPENAI_KEY=<KEY> cat myfile.txt | ata --tts --voice=ash
8224
```
83-
After this, your binary should be available at `target/release/ata` (Unix-based) or `target/release/ata.exe` (Windows).

src/main.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1-
fn main() {
2-
println!("Hello, world!");
1+
use clap::Parser;
2+
use std::io::{self, Read};
3+
4+
#[derive(Parser)]
5+
#[command(author, version, about = "Ask the Terminal Anything - Use AI in the terminal")]
6+
struct Arguments {
7+
/// Enable text-to-speech conversion
8+
#[arg(long)]
9+
tts: bool,
10+
11+
/// Voice to use for text-to-speech (optional)
12+
#[arg(long)]
13+
voice: Option<String>,
14+
}
15+
16+
#[tokio::main]
17+
async fn main() {
18+
let args = Arguments::parse();
19+
20+
// Read all input from stdin
21+
let mut input = String::new();
22+
io::stdin().read_to_string(&mut input).unwrap();
23+
24+
// TODO: add logic to transformrs to just get the key without .env file.
25+
let _openai_key = std::env::var("OPENAI_KEY").expect("OPENAI_KEY must be set");
26+
27+
if args.tts {
28+
if let Some(voice) = args.voice {
29+
todo!("Implement TTS with voice: {}", voice);
30+
} else {
31+
todo!("Implement TTS with default voice");
32+
}
33+
} else {
34+
eprintln!("No action specified. Use --tts to convert text to speech.");
35+
std::process::exit(1);
36+
}
337
}

tests/cli.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use assert_cmd::prelude::*;
2+
use predicates::prelude::*;
3+
use std::process::Command;
4+
5+
#[test]
6+
fn unexpected_argument() -> Result<(), Box<dyn std::error::Error>> {
7+
let mut cmd = Command::cargo_bin("ata")?;
8+
9+
cmd.arg("foobar");
10+
cmd.assert()
11+
.failure()
12+
.stderr(predicate::str::contains("unexpected argument"));
13+
14+
Ok(())
15+
}
16+
17+
18+
#[test]
19+
fn help() -> Result<(), Box<dyn std::error::Error>> {
20+
let mut cmd = Command::cargo_bin("ata")?;
21+
22+
cmd.arg("--help");
23+
cmd.assert()
24+
.success()
25+
.stdout(predicate::str::contains("Usage: ata"));
26+
27+
Ok(())
28+
}

0 commit comments

Comments
 (0)