feat: -f/--file take one value and no enter REPL (#399)

This commit is contained in:
sigoden 2024-04-10 20:36:12 +08:00 committed by GitHub
parent a0bd6e1d5d
commit 4a5ee3ecb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 35 additions and 24 deletions

View File

@ -18,14 +18,14 @@ Chat REPL mode:
- Support most of the LLM platforms
- OpenAI: GPT3.5/GPT4 (paid, vision)
- Gemini (free, vision)
- Claude: (paid)
- Gemini: Gemini-1.0/Gemini-1.5 (free, vision)
- Claude: Claude3 (paid)
- Mistral (paid)
- Cohere (paid)
- OpenAI-Compatible (local)
- OpenAI-Compatible
- Ollama (free, local)
- Azure-OpenAI (paid)
- VertexAI: Gemini-1/Gemini-1.5 (paid, vision)
- VertexAI (paid, vision)
- Ernie (paid)
- Qianwen (paid, vision)
- Moonshot (paid)
@ -122,7 +122,7 @@ Options:
-s, --session [<SESSION>] Create or reuse a session
-e, --execute Execute commands using natural language
-c, --code Generate only code
-f, --file <FILE>... Attach files to the message to be sent
-f, --file <FILE> Attach files to the message
-H, --no-highlight Disable syntax highlighting
-S, --no-stream No stream output
-w, --wrap <WRAP> Specify the text-wrapping mode (no, auto, <max-width>)
@ -153,7 +153,7 @@ aichat -s session1 --info # Session info
cat data.toml | aichat -c to json > data.json # Pipe IO
aichat --file a.png b.png -- diff images # Attach files
aichat --file a.png --file b.png diff images # Attach files
```
### Shell commands

View File

@ -21,9 +21,9 @@ pub struct Cli {
/// Generate only code
#[clap(short = 'c', long)]
pub code: bool,
/// Attach files to the message to be sent
#[clap(short = 'f', long, num_args = 1.., value_name = "FILE")]
pub file: Option<Vec<String>>,
/// Attach files to the message
#[clap(short = 'f', long, value_name = "FILE")]
pub file: Vec<String>,
/// Disable syntax highlighting
#[clap(short = 'H', long)]
pub no_highlight: bool,

View File

@ -87,18 +87,19 @@ fn main() -> Result<()> {
return Ok(());
}
let text = aggregate_text(text)?;
let input = create_input(&config, text, &cli.file)?;
if cli.execute {
match text {
Some(text) => {
execute(&config, &text)?;
match input {
Some(input) => {
execute(&config, input)?;
return Ok(());
}
None => bail!("No input text"),
}
}
config.write().prelude()?;
if let Err(err) = match text {
Some(text) => start_directive(&config, &text, cli.file, cli.no_stream, cli.code),
if let Err(err) = match input {
Some(input) => start_directive(&config, input, cli.no_stream, cli.code),
None => start_interactive(&config),
} {
let highlight = stderr().is_terminal() && config.read().highlight;
@ -109,16 +110,10 @@ fn main() -> Result<()> {
fn start_directive(
config: &GlobalConfig,
text: &str,
include: Option<Vec<String>>,
input: Input,
no_stream: bool,
code_mode: bool,
) -> Result<()> {
let input = Input::new(
text,
include.unwrap_or_default(),
config.read().input_context(),
)?;
let mut client = init_client(config)?;
ensure_model_capabilities(client.as_mut(), input.required_capabilities())?;
config.read().maybe_print_send_tokens(&input);
@ -153,8 +148,7 @@ fn start_interactive(config: &GlobalConfig) -> Result<()> {
repl.run()
}
fn execute(config: &GlobalConfig, text: &str) -> Result<()> {
let input = Input::from_str(text, config.read().input_context());
fn execute(config: &GlobalConfig, input: Input) -> Result<()> {
let client = init_client(config)?;
config.read().maybe_print_send_tokens(&input);
let mut eval_str = client.send_message(input.clone())?;
@ -228,3 +222,20 @@ fn aggregate_text(text: Option<String>) -> Result<Option<String>> {
};
Ok(text)
}
fn create_input(
config: &GlobalConfig,
text: Option<String>,
file: &[String],
) -> Result<Option<Input>> {
if text.is_none() && file.is_empty() {
return Ok(None);
}
let input_context = config.read().input_context();
let input = if file.is_empty() {
Input::from_str(&text.unwrap_or_default(), input_context)
} else {
Input::new(&text.unwrap_or_default(), file.to_vec(), input_context)?
};
Ok(Some(input))
}

View File

@ -234,7 +234,7 @@ impl Repl {
let input = Input::new(text, files, self.config.read().input_context())?;
self.ask(input)?;
}
None => println!("Usage: .file <files>...[ -- <text>...]"),
None => println!("Usage: .file <files>... [-- <text>...]"),
},
".exit" => match args {
Some("role") => {