summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-01-24 16:38:34 +0100
committerLaurenz <laurmaedje@gmail.com>2022-01-24 16:44:52 +0100
commitdb158719d67fdef1d2c76300fb232cf2d4bfb35d (patch)
tree3704d2c3b37521e1ecae75c3246fd5573537b378 /src
parent36cae88799722fe873b578114d24201db8903d67 (diff)
Simplify CLI
Diffstat (limited to 'src')
-rw-r--r--src/layout/incremental.rs2
-rw-r--r--src/main.rs106
2 files changed, 56 insertions, 52 deletions
diff --git a/src/layout/incremental.rs b/src/layout/incremental.rs
index 4c046051..f737a3ef 100644
--- a/src/layout/incremental.rs
+++ b/src/layout/incremental.rs
@@ -150,6 +150,7 @@ impl LayoutCache {
entries.retain(|f| f.hits() as f64 / f.age() as f64 > threshold);
}
}
+ #[cfg(feature = "rand")]
EvictionPolicy::Random => {
// Fraction of items that should be kept.
let threshold = self.max_size as f64 / len as f64;
@@ -340,6 +341,7 @@ pub enum EvictionPolicy {
/// Evict the least frequently used item.
LeastFrequentlyUsed,
/// Evict randomly.
+ #[cfg(feature = "rand")]
Random,
/// Use the pattern verdicts.
Patterns,
diff --git a/src/main.rs b/src/main.rs
index fa8b6103..daeff033 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,7 +3,6 @@ use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process;
-use anyhow::Context as _;
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::term::{self, termcolor, Config, Styles};
use same_file::is_same_file;
@@ -15,20 +14,34 @@ use typst::loading::FsLoader;
use typst::source::SourceStore;
use typst::Context;
+const HELP: &'static str = "\
+typst creates PDF files from .typ files
+
+USAGE:
+ typst [OPTIONS] <input.typ> [output.pdf]
+
+OPTIONS:
+ -h, --help Print this help
+
+ARGS:
+ <input.typ> Path input Typst file
+ [output.pdf] Path to output PDF
+";
+
fn main() {
- if let Err(error) = try_main() {
- print_error(error).unwrap();
+ let args = parse_args();
+ let ok = args.is_ok();
+ if let Err(msg) = args.and_then(try_main) {
+ print_error(&msg).unwrap();
+ if !ok {
+ println!("\nfor more information, try --help");
+ }
process::exit(1);
}
}
/// The main compiler logic.
-fn try_main() -> anyhow::Result<()> {
- let args = Args::from_env().unwrap_or_else(|_| {
- print_usage().unwrap();
- process::exit(2);
- });
-
+fn try_main(args: Args) -> Result<(), String> {
// Create a loader for fonts and files.
let mut loader = FsLoader::new();
@@ -51,24 +64,27 @@ fn try_main() -> anyhow::Result<()> {
// Ensure that the source file is not overwritten.
if is_same_file(&args.input, &args.output).unwrap_or(false) {
- anyhow::bail!("source and destination files are the same");
+ Err("source and destination files are the same")?;
}
// Load the source file.
- let id = ctx.sources.load(&args.input).context("source file not found")?;
+ let id = ctx
+ .sources
+ .load(&args.input)
+ .map_err(|_| "failed to load source file")?;
// Typeset.
match ctx.typeset(id) {
// Export the PDF.
Ok(frames) => {
let buffer = export::pdf(&ctx, &frames);
- fs::write(&args.output, buffer).context("failed to write PDF file")?;
+ fs::write(&args.output, buffer).map_err(|_| "failed to write PDF file")?;
}
// Print diagnostics.
Err(errors) => {
print_diagnostics(&ctx.sources, *errors)
- .context("failed to print diagnostics")?;
+ .map_err(|_| "failed to print diagnostics")?;
}
}
@@ -80,55 +96,41 @@ struct Args {
output: PathBuf,
}
-impl Args {
- fn from_env() -> Result<Self, anyhow::Error> {
- let mut parser = pico_args::Arguments::from_env();
-
- // Parse free-standing arguments.
- let input = parser.free_from_str::<PathBuf>()?;
- let output = match parser.opt_free_from_str()? {
- Some(output) => output,
- None => {
- let name = input.file_name().context("source path is not a file")?;
- Path::new(name).with_extension("pdf")
- }
- };
-
- // Don't allow excess arguments.
- if !parser.finish().is_empty() {
- anyhow::bail!("too many arguments");
- }
-
- Ok(Self { input, output })
+/// Parse command line arguments.
+fn parse_args() -> Result<Args, String> {
+ let mut args = pico_args::Arguments::from_env();
+ if args.contains(["-h", "--help"]) {
+ print!("{}", HELP);
+ std::process::exit(0);
}
-}
-/// Print a usage message.
-fn print_usage() -> io::Result<()> {
- let mut w = StandardStream::stderr(ColorChoice::Always);
- let styles = Styles::default();
+ let input = args.free_from_str::<PathBuf>().map_err(|_| "missing input file")?;
+ let output = match args.opt_free_from_str().ok().flatten() {
+ Some(output) => output,
+ None => {
+ let name = input.file_name().ok_or("source path does not point to a file")?;
+ Path::new(name).with_extension("pdf")
+ }
+ };
- w.set_color(&styles.header_help)?;
- write!(w, "usage")?;
+ // Don't allow excess arguments.
+ if !args.finish().is_empty() {
+ Err("too many arguments")?;
+ }
- w.set_color(&styles.header_message)?;
- writeln!(w, ": typst <input.typ> [output.pdf]")
+ Ok(Args { input, output })
}
-/// Print an error outside of a source file.
-fn print_error(error: anyhow::Error) -> io::Result<()> {
+/// Print an application-level error (independent from a source file).
+fn print_error(msg: &str) -> io::Result<()> {
let mut w = StandardStream::stderr(ColorChoice::Always);
let styles = Styles::default();
- for (i, cause) in error.chain().enumerate() {
- w.set_color(&styles.header_error)?;
- write!(w, "{}", if i == 0 { "error" } else { "cause" })?;
-
- w.set_color(&styles.header_message)?;
- writeln!(w, ": {}", cause)?;
- }
+ w.set_color(&styles.header_error)?;
+ write!(w, "error")?;
- w.reset()
+ w.reset()?;
+ writeln!(w, ": {msg}.")
}
/// Print diagnostics messages to the terminal.