CLI: open flag (#480)

This commit is contained in:
Sébastien d'Herbais de Thun 2023-04-04 14:12:19 +02:00 committed by GitHub
parent 2c735294cd
commit 2d1598e51d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 18 deletions

16
Cargo.lock generated
View File

@ -952,12 +952,27 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "open"
version = "4.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "075c5203b3a2b698bc72c6c10b1f6263182135751d5013ea66e8a4b3d0562a43"
dependencies = [
"pathdiff",
]
[[package]]
name = "paste"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "pathdiff"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]]
name = "pdf-writer"
version = "0.6.0"
@ -1539,6 +1554,7 @@ dependencies = [
"memmap2",
"notify",
"once_cell",
"open",
"same-file",
"siphasher",
"typst",

View File

@ -27,6 +27,7 @@ same-file = "1"
siphasher = "0.3"
walkdir = "2"
clap = { version = "4.2.1", features = ["derive"] }
open = "4.0.1"
[features]
default = ["embed-fonts"]

View File

@ -57,7 +57,7 @@ enum Command {
/// Watches the input file and recompiles on changes
#[command(visible_alias = "w")]
Watch(WatchCommand),
Watch(CompileCommand),
/// List all discovered fonts in system and custom font paths
Fonts(FontsCommand),
@ -71,22 +71,16 @@ pub struct CompileCommand {
/// Path to output PDF file
output: Option<PathBuf>,
}
/// Watches the input file and recompiles on changes
#[derive(Debug, Clone, Parser)]
pub struct WatchCommand {
/// Path to input Typst file
input: PathBuf,
/// Path to output PDF file
output: Option<PathBuf>,
/// Opens the output file after compilation using the default PDF viewer
#[arg(long = "open")]
open: Option<Option<String>>,
}
/// List all discovered fonts in system and custom font paths
#[derive(Debug, Clone, Parser)]
pub struct FontsCommand {
/// Add additional directories to search for fonts
/// Also list style variants of each font family
#[arg(long)]
variants: bool,
}
@ -107,6 +101,9 @@ struct CompileSettings {
/// The paths to search for fonts.
font_paths: Vec<PathBuf>,
/// The open command to use.
open: Option<Option<String>>,
}
impl CompileSettings {
@ -117,13 +114,13 @@ impl CompileSettings {
watch: bool,
root: Option<PathBuf>,
font_paths: Vec<PathBuf>,
open: Option<Option<String>>,
) -> Self {
let output = match output {
Some(path) => path,
None => input.with_extension("pdf"),
};
Self { input, output, watch, root, font_paths }
Self { input, output, watch, root, font_paths, open }
}
/// Create a new compile settings from the CLI arguments and a compile command.
@ -131,12 +128,13 @@ impl CompileSettings {
/// # Panics
/// Panics if the command is not a compile or watch command.
pub fn with_arguments(args: CliArguments) -> Self {
let (input, output, watch) = match args.command {
Command::Compile(command) => (command.input, command.output, false),
Command::Watch(command) => (command.input, command.output, true),
let watch = matches!(args.command, Command::Watch(_));
let CompileCommand { input, output, open } = match args.command {
Command::Compile(command) => command,
Command::Watch(command) => command,
_ => unreachable!(),
};
Self::new(input, output, watch, args.root, args.font_paths)
Self::new(input, output, watch, args.root, args.font_paths, open)
}
}
@ -195,7 +193,7 @@ fn print_error(msg: &str) -> io::Result<()> {
}
/// Execute a compilation command.
fn compile(command: CompileSettings) -> StrResult<()> {
fn compile(mut command: CompileSettings) -> StrResult<()> {
let root = if let Some(root) = &command.root {
root.clone()
} else if let Some(dir) = command
@ -215,6 +213,14 @@ fn compile(command: CompileSettings) -> StrResult<()> {
// Perform initial compilation.
let failed = compile_once(&mut world, &command)?;
// open the file if requested, this must be done on the first **successful** compilation
if !failed {
if let Some(open) = command.open.take() {
open_file(open.as_deref(), &command.output)?;
}
}
if !command.watch {
// Return with non-zero exit code in case of error.
if failed {
@ -258,6 +264,11 @@ fn compile(command: CompileSettings) -> StrResult<()> {
if recompile {
compile_once(&mut world, &command)?;
comemo::evict(30);
// open the file if requested, this must be done on the first **successful** compilation
if let Some(open) = command.open.take() {
open_file(open.as_deref(), &command.output)?;
}
}
}
}
@ -381,6 +392,23 @@ fn print_diagnostics(
Ok(())
}
/// Opens the given file using:
/// - The default file viewer if `open` is `None`.
/// - The given viewer provided by `open` if it is `Some`.
fn open_file(open: Option<&str>, path: &Path) -> StrResult<()> {
if let Some(app) = open {
open::with(path, app).map_err(|err| {
format!("failed to open `{}` with `{}`, reason: {}", path.display(), app, err)
})?;
} else {
open::that(path).map_err(|err| {
format!("failed to open `{}`, reason: {}", path.display(), err)
})?;
}
Ok(())
}
/// Execute a font listing command.
fn fonts(command: FontsSettings) -> StrResult<()> {
let mut searcher = FontSearcher::new();