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}1use std::{2 env::current_dir,3 fs::{create_dir_all, File},4 io::{Read, Write},5};67use clap::{AppSettings, IntoApp, Parser};8use clap_complete::Shell;9use jrsonnet_cli::{ConfigureState, GcOpts, GeneralOpts, 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(next_help_heading = "INPUT")]36struct InputOpts {37 /// Treat input as code, evaluate them instead of reading file38 #[clap(long, short = 'e')]39 pub exec: bool,4041 /// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself42 pub input: Option<String>,43}4445#[derive(Parser)]46#[clap(47 global_setting = AppSettings::DeriveDisplayOrder,48 args_conflicts_with_subcommands = true,49)]50struct Opts {51 #[clap(subcommand)]52 sub: Option<SubOpts>,5354 #[clap(flatten)]55 input: InputOpts,56 #[clap(flatten)]57 general: GeneralOpts,58 #[clap(flatten)]59 manifest: ManifestOpts,60 #[clap(flatten)]61 output: OutputOpts,62 #[clap(flatten)]63 debug: DebugOpts,64 #[clap(flatten)]65 gc: GcOpts,66}6768fn main() {69 let opts: Opts = Opts::parse();7071 if let Some(sub) = opts.sub {72 match sub {73 SubOpts::Generate { shell } => {74 use clap_complete::generate;75 let app = &mut Opts::command();76 let buf = &mut std::io::stdout();77 generate(shell, app, "jrsonnet", buf);78 std::process::exit(0)79 }80 }81 }8283 let success = if let Some(size) = opts.debug.os_stack {84 std::thread::Builder::new()85 .stack_size(size * 1024 * 1024)86 .spawn(|| main_catch(opts))87 .expect("new thread spawned")88 .join()89 .expect("thread finished successfully")90 } else {91 main_catch(opts)92 };93 if !success {94 std::process::exit(1);95 }96}9798#[derive(thiserror::Error, Debug)]99enum Error {100 // Handled differently101 #[error("evaluation error")]102 Evaluation(jrsonnet_evaluator::error::LocError),103 #[error("io error")]104 Io(#[from] std::io::Error),105 #[error("input is not utf8 encoded")]106 Utf8(#[from] std::str::Utf8Error),107 #[error("missing input argument")]108 MissingInputArgument,109}110impl From<LocError> for Error {111 fn from(e: LocError) -> Self {112 Self::Evaluation(e)113 }114}115116fn main_catch(opts: Opts) -> bool {117 let _printer = opts.gc.stats_printer();118 let s = State::default();119 if let Err(e) = main_real(&s, opts) {120 if let Error::Evaluation(e) = e {121 eprintln!("{}", s.stringify_err(&e));122 } else {123 eprintln!("{}", e);124 }125 return false;126 }127 true128}129130fn main_real(s: &State, opts: Opts) -> Result<(), Error> {131 opts.general.configure(s)?;132 opts.manifest.configure(s)?;133134 let input = opts.input.input.ok_or(Error::MissingInputArgument)?;135 let val = if opts.input.exec {136 s.evaluate_snippet("<cmdline>".to_owned(), (&input as &str).into())?137 } else if input == "-" {138 let mut input = Vec::new();139 std::io::stdin().read_to_end(&mut input)?;140 let input_str = std::str::from_utf8(&input)?.into();141 s.evaluate_snippet("<stdin>".to_owned(), input_str)?142 } else {143 s.import(s.resolve_file(¤t_dir().expect("cwd"), &input)?)?144 };145146 let val = s.with_tla(val)?;147148 if let Some(multi) = opts.output.multi {149 if opts.output.create_output_dirs {150 let mut dir = multi.clone();151 dir.pop();152 create_dir_all(dir)?;153 }154 for (file, data) in s.manifest_multi(val)?.iter() {155 let mut path = multi.clone();156 path.push(file as &str);157 if opts.output.create_output_dirs {158 let mut dir = path.clone();159 dir.pop();160 create_dir_all(dir)?;161 }162 println!("{}", path.to_str().expect("path"));163 let mut file = File::create(path)?;164 writeln!(file, "{}", data)?;165 }166 } else if let Some(path) = opts.output.output_file {167 if opts.output.create_output_dirs {168 let mut dir = path.clone();169 dir.pop();170 create_dir_all(dir)?;171 }172 let mut file = File::create(path)?;173 writeln!(file, "{}", s.manifest(val)?)?;174 } else {175 let output = s.manifest(val)?;176 if !output.is_empty() {177 println!("{}", output);178 }179 }180181 Ok(())182}