difftreelog
fix workaround ugly generate command
in: master
1 file changed
cmds/jrsonnet/src/main.rsdiffbeforeafterboth1use std::{2 fs::{create_dir_all, File},3 io::{Read, Write},4 path::PathBuf,5};67use clap::{AppSettings, IntoApp, Parser};8use clap_complete::Shell;9use jrsonnet_cli::{ConfigureState, GcOpts, GeneralOpts, InputOpts, ManifestOpts, OutputOpts};10use jrsonnet_evaluator::{error::LocError, State};1112#[cfg(feature = "mimalloc")]13#[global_allocator]14static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;1516#[derive(Parser)]17enum SubOpts {18 /// Generate completions for specified shell19 Generate {20 /// Target shell name21 shell: Shell,22 },23}2425#[derive(Parser)]26#[clap(next_help_heading = "DEBUG")]27struct DebugOpts {28 /// Required OS stack size.29 /// This shouldn't be changed unless jrsonnet is failing with stack overflow error.30 #[clap(long, name = "size")]31 pub os_stack: Option<usize>,32}3334#[derive(Parser)]35#[clap(36 global_setting = AppSettings::DeriveDisplayOrder,37 // args_conflicts_with_subcommands = true,38)]39struct Opts {40 #[clap(subcommand)]41 sub: Option<SubOpts>,4243 #[clap(flatten)]44 input: InputOpts,45 #[clap(flatten)]46 general: GeneralOpts,47 #[clap(flatten)]48 manifest: ManifestOpts,49 #[clap(flatten)]50 output: OutputOpts,51 #[clap(flatten)]52 debug: DebugOpts,53 #[clap(flatten)]54 gc: GcOpts,55}5657fn main() {58 let opts: Opts = Opts::parse();5960 if let Some(sub) = opts.sub {61 match sub {62 SubOpts::Generate { shell } => {63 use clap_complete::generate;64 let app = &mut Opts::command();65 let buf = &mut std::io::stdout();66 generate(shell, app, "jrsonnet", buf);67 std::process::exit(0)68 }69 }70 }7172 let success = if let Some(size) = opts.debug.os_stack {73 std::thread::Builder::new()74 .stack_size(size * 1024 * 1024)75 .spawn(|| main_catch(opts))76 .expect("new thread spawned")77 .join()78 .expect("thread finished successfully")79 } else {80 main_catch(opts)81 };82 if !success {83 std::process::exit(1);84 }85}8687#[derive(thiserror::Error, Debug)]88enum Error {89 // Handled differently90 #[error("evaluation error")]91 Evaluation(jrsonnet_evaluator::error::LocError),92 #[error("io error")]93 Io(#[from] std::io::Error),94 #[error("input is not utf8 encoded")]95 Utf8(#[from] std::str::Utf8Error),96}97impl From<LocError> for Error {98 fn from(e: LocError) -> Self {99 Self::Evaluation(e)100 }101}102103fn main_catch(opts: Opts) -> bool {104 let _printer = opts.gc.stats_printer();105 let s = State::default();106 if let Err(e) = main_real(&s, opts) {107 if let Error::Evaluation(e) = e {108 eprintln!("{}", s.stringify_err(&e));109 } else {110 eprintln!("{}", e);111 }112 return false;113 }114 true115}116117fn main_real(s: &State, opts: Opts) -> Result<(), Error> {118 opts.general.configure(s)?;119 opts.manifest.configure(s)?;120121 let val = if opts.input.exec {122 s.evaluate_snippet("<cmdline>".to_owned(), (&opts.input.input as &str).into())?123 } else if opts.input.input == "-" {124 let mut input = Vec::new();125 std::io::stdin().read_to_end(&mut input)?;126 let input_str = std::str::from_utf8(&input)?.into();127 s.evaluate_snippet("<stdin>".to_owned(), input_str)?128 } else {129 s.import(s.resolve_file(&PathBuf::new(), &opts.input.input)?)?130 };131132 let val = s.with_tla(val)?;133134 if let Some(multi) = opts.output.multi {135 if opts.output.create_output_dirs {136 let mut dir = multi.clone();137 dir.pop();138 create_dir_all(dir)?;139 }140 for (file, data) in s.manifest_multi(val)?.iter() {141 let mut path = multi.clone();142 path.push(file as &str);143 if opts.output.create_output_dirs {144 let mut dir = path.clone();145 dir.pop();146 create_dir_all(dir)?;147 }148 println!("{}", path.to_str().expect("path"));149 let mut file = File::create(path)?;150 writeln!(file, "{}", data)?;151 }152 } else if let Some(path) = opts.output.output_file {153 if opts.output.create_output_dirs {154 let mut dir = path.clone();155 dir.pop();156 create_dir_all(dir)?;157 }158 let mut file = File::create(path)?;159 writeln!(file, "{}", s.manifest(val)?)?;160 } else {161 let output = s.manifest(val)?;162 if !output.is_empty() {163 println!("{}", output);164 }165 }166167 Ok(())168}