-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
efea7ac
commit 21b24e9
Showing
8 changed files
with
295 additions
and
77 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
no-format = true | ||
formatter = "/home/kat/.nix-profile/bin/clang-format" | ||
deterministic = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,121 +1,62 @@ | ||
use std::fs::File; | ||
use std::io::{stdout, Write}; | ||
use std::path::{Path, PathBuf}; | ||
use std::path::PathBuf; | ||
|
||
use clap::Parser; | ||
use eyre::{Context, Result}; | ||
|
||
use crate::banner::Banner; | ||
use crate::bundler::Bundler; | ||
use crate::consts::{CRATE_DESCRIPTION, LONG_VERSION, SHORT_VERSION}; | ||
use crate::config::Config; | ||
use crate::display::display_path; | ||
use crate::formatter::Formatter; | ||
use crate::pipeline::Pipeline; | ||
use crate::quotes::Quotes; | ||
use crate::source::Sources; | ||
|
||
#[derive(Debug, Clone, Parser)] | ||
#[command( | ||
version = SHORT_VERSION, | ||
long_version = LONG_VERSION, | ||
about = CRATE_DESCRIPTION, | ||
long_about = None | ||
)] | ||
pub struct GlobalArgs { | ||
#[arg( | ||
long, | ||
help = "Don't pass the resulting bundle through the formatter.", | ||
default_value_t = false | ||
)] | ||
pub no_format: bool, | ||
|
||
#[arg( | ||
long, | ||
help = "Code formatter executable.", | ||
long_help = "Code formatter. Must format the code from stdin and write it to stdout.", | ||
default_value = "clang-format", | ||
value_name = "exe" | ||
)] | ||
pub formatter: PathBuf, | ||
|
||
#[arg( | ||
long = "deterministic", | ||
help = "Output a deterministic bundle.", | ||
default_value_t = false | ||
)] | ||
pub deterministic: bool, | ||
|
||
#[arg( | ||
short = 'o', | ||
long = "output", | ||
help = "Specify where to write the resulting bundle.", | ||
default_value = "-", | ||
value_name = "path" | ||
)] | ||
pub output_file: PathBuf, | ||
|
||
#[arg(help = "Path to the entry source file.", value_name = "path")] | ||
pub entry: PathBuf, | ||
} | ||
|
||
pub fn run() -> Result<()> { | ||
let args = GlobalArgs::parse(); | ||
trace!("args = {args:#?}"); | ||
let config = Config::new()?; | ||
trace!("config = {config:#?}"); | ||
|
||
let sources = Sources::new(args.entry)?; | ||
let sources = Sources::new(config.entry)?; | ||
|
||
let mut pipeline = Pipeline { | ||
bundler: Bundler {}, | ||
banner: Banner { | ||
quotes: Quotes {}, | ||
deterministic: args.deterministic, | ||
deterministic: config.deterministic, | ||
}, | ||
formatter: some_if(!args.no_format, || Formatter { | ||
exe: args.formatter, | ||
formatter: (!config.no_format).then(|| Formatter { | ||
exe: config.formatter, | ||
}), | ||
}; | ||
|
||
let bundle = pipeline.process(&sources)?; | ||
|
||
write_bundle(bundle, &args.output_file).with_context(|| { | ||
format!( | ||
"failed to write bundle to `{}`", | ||
display_path(&args.output_file) | ||
) | ||
write_bundle(bundle, config.output_file.as_ref()).with_context(|| { | ||
if let Some(path) = config.output_file.as_ref() { | ||
format!("failed to write bundle to `{}`", display_path(path)) | ||
} else { | ||
format!("failed to write bundle to stdout") | ||
} | ||
})?; | ||
|
||
Ok(()) | ||
} | ||
|
||
fn write_bundle(bundle: String, path: &Path) -> Result<()> { | ||
let mut writer: Box<dyn Write> = if path_is_stdio(path) { | ||
Box::new(stdout().lock()) | ||
} else { | ||
fn write_bundle(bundle: String, path: Option<&PathBuf>) -> Result<()> { | ||
let mut writer: Box<dyn Write> = if let Some(path) = path { | ||
Box::new( | ||
File::options() | ||
.write(true) | ||
.truncate(true) | ||
.create(true) | ||
.open(path)?, | ||
) | ||
} else { | ||
Box::new(stdout().lock()) | ||
}; | ||
|
||
writer.write_all(bundle.as_bytes())?; | ||
writer.flush()?; | ||
Ok(()) | ||
} | ||
|
||
fn path_is_stdio(path: &Path) -> bool { | ||
path.as_os_str().as_encoded_bytes().eq(b"-") | ||
} | ||
|
||
fn some_if<T, F>(cond: bool, f: F) -> Option<T> | ||
where | ||
F: FnOnce() -> T, | ||
{ | ||
if cond { | ||
Some(f()) | ||
} else { | ||
None | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use std::path::{Path, PathBuf}; | ||
|
||
use clap::parser::ValueSource; | ||
use clap::{CommandFactory, Parser}; | ||
use eyre::Result; | ||
|
||
use crate::consts::{CRATE_DESCRIPTION, LONG_VERSION, SHORT_VERSION}; | ||
|
||
use super::Config; | ||
|
||
#[derive(Debug, Clone, Parser)] | ||
#[command( | ||
version = SHORT_VERSION, | ||
long_version = LONG_VERSION, | ||
about = CRATE_DESCRIPTION, | ||
long_about = None | ||
)] | ||
pub struct Args { | ||
#[arg(long, help = "Don't pass the resulting bundle through the formatter.")] | ||
no_format: bool, | ||
|
||
#[arg( | ||
long, | ||
help = "Code formatter executable.", | ||
long_help = "Code formatter. Must format the code from stdin and write it to stdout.", | ||
value_name = "exe", | ||
default_value = "clang-format" | ||
)] | ||
formatter: PathBuf, | ||
|
||
#[arg(long = "deterministic", help = "Output a deterministic bundle.")] | ||
deterministic: bool, | ||
|
||
#[arg( | ||
short = 'o', | ||
long = "output", | ||
help = "Specify where to write the resulting bundle.", | ||
value_name = "path", | ||
default_value = "-" | ||
)] | ||
output_file: PathBuf, | ||
|
||
#[arg(help = "Path to the entry source file.", value_name = "path")] | ||
entry: PathBuf, | ||
} | ||
|
||
impl Args { | ||
pub fn merge(config: &mut Config) -> Result<()> { | ||
let matches = Args::command().get_matches(); | ||
|
||
// SAFETY: The following `unwrap`s are safe because the these arguments have default values. | ||
|
||
if matches.contains_id("no_format") { | ||
config.no_format = matches.get_flag("no_format"); | ||
} | ||
|
||
if matches.value_source("formatter").unwrap() != ValueSource::DefaultValue { | ||
config.formatter = matches.get_one::<PathBuf>("formatter").unwrap().to_owned(); | ||
} | ||
|
||
if matches.contains_id("deterministic") { | ||
config.deterministic = matches.get_flag("deterministic"); | ||
} | ||
|
||
if matches.value_source("output_file").unwrap() != ValueSource::DefaultValue { | ||
let output_file = matches.get_one::<PathBuf>("output_file").unwrap(); | ||
config.output_file = path_is_stdio(output_file).then(|| output_file.to_owned()); | ||
} | ||
|
||
if let Some(x) = matches.get_one::<PathBuf>("entry").cloned() { | ||
config.entry = x; | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
fn path_is_stdio(path: &Path) -> bool { | ||
path.as_os_str().as_encoded_bytes().eq(b"-") | ||
} |
Oops, something went wrong.