use std::io::Write;
use google_translator::*;
use clap::Parser;
#[cfg(windows)]
const EOL: &str = "\r\n";
#[cfg(not(windows))]
const EOL: &str = "\n";
#[derive(Parser, Debug)]
struct Args {
#[arg(short, long = "input", default_value_t = String::from("auto"))]
input_lang: String,
#[arg(short, long = "output", default_value_t = String::from("en"))]
output_lang: String,
#[arg(short = 'm', long = "mode", default_value_t = 1)]
mode: u8,
#[arg(short = 'a', long = "args")]
args: Option<String>,
#[arg(short = 'f', long = "output file")]
output_file: Option<String>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
let output_file = args.output_file;
let input_lang = args.input_lang;
let output_lang = args.output_lang;
match args.mode {
1 => match args.args {
Some(args) => {
print_one_line(
&output_file,
&format!(
"{}",
translate_one_line(args, input_lang, output_lang).await?
),
)?;
}
None => {
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
print_one_line(
&output_file,
&format!(
"{}",
translate_one_line(input, input_lang, output_lang).await?
),
)?;
}
},
2 => {
let file_path = args.args.unwrap();
let lines = std::fs::read_to_string(file_path)?
.split("\n")
.map(|x| x.trim().to_owned())
.collect::<Vec<_>>();
let mut translated = Vec::new();
let mut count = 0;
let mut group = Vec::new();
for line in lines {
count += line.len();
if count >= 4000 {
translated.push(tokio::spawn(translate(
group,
input_lang.clone(),
output_lang.clone(),
)));
group = Vec::new();
count = line.len();
}
group.push(line);
}
translated.push(tokio::spawn(translate(group, input_lang, output_lang)));
for now in translated {
let result = now.await??;
for line in result.output_text {
print_one_line(&output_file, &format!("{}", line[0]))?;
}
}
}
3 => {
loop {
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
tokio::spawn(translate_buf(
output_file.clone(),
input,
input_lang.clone(),
output_lang.clone(),
));
}
}
_ => {}
}
Ok(())
}
async fn translate_buf(
output_file: Option<String>,
text: String,
input_lang: String,
output_lang: String,
) -> Result<(), std::io::Error> {
let result = translate_one_line(text, input_lang, output_lang).await;
match result {
Ok(result) => {
print_one_line(&output_file, &format!("{}", result))?;
}
Err(e) => {
print_one_line(&output_file, &format!("{}", e))?;
}
}
Ok(())
}
fn print_one_line(output_file: &Option<String>, line: &String) -> Result<(), std::io::Error> {
match output_file {
Some(output_file) => {
let mut file = std::fs::OpenOptions::new()
.create(true)
.write(true)
.append(true)
.open(output_file)?;
file.write_all(line.as_bytes())?;
file.write_all(EOL.as_bytes())?;
}
None => println!("{}", line),
};
Ok(())
}