mod bin_finder;
mod dociter;
mod error;
mod jq_pipe;
mod opts;
mod output;
mod pager;
mod reader;
mod short_display;
mod toml_pp;
mod tomly;
use crate::dociter::DocumentIterator;
use crate::jq_pipe::{toml_to_jq, toml_to_json_to_stdout};
use crate::output::output_to_stdout;
use crate::reader::MultiFileRead;
use crate::short_display::ShortDisplayExt;
use crate::tomly::{create_toml_doc_from_json, parse_toml_document, print_toml};
use atty::Stream;
use clap::Parser;
use opts::TomlOpts;
use std::error::Error;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use std::process::ExitCode;
const LICENSE_FOOTER: &'static str = r#"
Licensed under MIT.
Copyright (c) 2022-present, the authors of tomq.
"#;
#[derive(Parser)]
#[clap(
author,
version,
about,
after_help = LICENSE_FOOTER,
after_long_help = LICENSE_FOOTER
)]
struct Opts {
#[clap(flatten)]
opts: TomlOpts,
#[clap(index = 2)]
file: Option<PathBuf>,
#[clap(long = "input-file", conflicts_with = "file")]
in_file: Option<PathBuf>,
#[clap(long = "input-files", multiple = true, conflicts_with_all(&["in-file", "file"]))]
in_files: Vec<PathBuf>,
}
fn main() -> Result<ExitCode, Box<dyn Error>> {
let opts: Opts = Opts::parse();
let sops = TomlOpts {
pretty_print: opts.opts.pretty_print || atty::is(Stream::Stdout) || opts.opts.bat,
..opts.opts.clone()
};
let status = if !opts.in_files.is_empty() {
let separator = &format!("\n\n{}\n\n", opts.opts.multi_doc_separator);
let sops = TomlOpts {
single_doc: false,
..sops.clone()
};
let mut reader = MultiFileRead::new(opts.in_files.clone(), separator.clone())?;
let names = opts
.in_files
.iter()
.map(|f| f.to_string_lossy().to_string())
.collect::<Vec<String>>();
let names = names.short_display(5);
read_and_output(BufReader::new(&mut reader), sops)
.map_err(|e| format!("Failed while handling files `{names:?}`: {}.", e))?
} else {
match opts.file.or(opts.in_file) {
Some(file) => read_and_output(BufReader::new(File::open(&file)?), sops)
.map_err(|e| format!("Failed while handling files `{}`: {}", file.display(), e))?,
None => {
if !atty::is(Stream::Stdin) {
read_and_output(std::io::stdin().lock(), sops)?
} else {
use clap::CommandFactory;
Opts::command().print_long_help()?;
-1
}
}
}
};
Ok(ExitCode::from(status as u8))
}
fn read_and_output<R: BufRead>(reader: R, opts: TomlOpts) -> Result<i32, Box<dyn Error>> {
if opts.toml_it {
if opts.jq_filter.as_ref().filter(|q| !q.is_empty()).is_none() {
let toml = create_toml_doc_from_json(
reader,
opts.skip_invalid,
opts.null_to_empty_doc,
opts.fallback_key,
);
print_toml(
toml,
opts.pretty_print,
&opts.root_key,
&opts.multi_doc_separator,
opts.bat,
)?;
Ok(0)
} else {
let toml = create_toml_doc_from_json(
reader,
opts.skip_invalid,
opts.null_to_empty_doc,
opts.fallback_key.clone(),
);
Ok(toml_to_jq(toml, opts)?)
}
} else {
let toml = parse_toml_document(reader, &opts);
if opts.jq_filter.as_ref().filter(|q| !q.is_empty()).is_none() {
Ok(toml_to_json_to_stdout(toml, opts)?)
} else {
Ok(toml_to_jq(toml, opts)?)
}
}
}
#[cfg(test)]
mod tests {}