mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
CLI: open flag (#480)
This commit is contained in:
parent
2c735294cd
commit
2d1598e51d
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -952,12 +952,27 @@ version = "1.17.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "open"
|
||||||
|
version = "4.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "075c5203b3a2b698bc72c6c10b1f6263182135751d5013ea66e8a4b3d0562a43"
|
||||||
|
dependencies = [
|
||||||
|
"pathdiff",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
|
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathdiff"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pdf-writer"
|
name = "pdf-writer"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@ -1539,6 +1554,7 @@ dependencies = [
|
|||||||
"memmap2",
|
"memmap2",
|
||||||
"notify",
|
"notify",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"open",
|
||||||
"same-file",
|
"same-file",
|
||||||
"siphasher",
|
"siphasher",
|
||||||
"typst",
|
"typst",
|
||||||
|
@ -27,6 +27,7 @@ same-file = "1"
|
|||||||
siphasher = "0.3"
|
siphasher = "0.3"
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
clap = { version = "4.2.1", features = ["derive"] }
|
clap = { version = "4.2.1", features = ["derive"] }
|
||||||
|
open = "4.0.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["embed-fonts"]
|
default = ["embed-fonts"]
|
||||||
|
@ -57,7 +57,7 @@ enum Command {
|
|||||||
|
|
||||||
/// Watches the input file and recompiles on changes
|
/// Watches the input file and recompiles on changes
|
||||||
#[command(visible_alias = "w")]
|
#[command(visible_alias = "w")]
|
||||||
Watch(WatchCommand),
|
Watch(CompileCommand),
|
||||||
|
|
||||||
/// List all discovered fonts in system and custom font paths
|
/// List all discovered fonts in system and custom font paths
|
||||||
Fonts(FontsCommand),
|
Fonts(FontsCommand),
|
||||||
@ -71,22 +71,16 @@ pub struct CompileCommand {
|
|||||||
|
|
||||||
/// Path to output PDF file
|
/// Path to output PDF file
|
||||||
output: Option<PathBuf>,
|
output: Option<PathBuf>,
|
||||||
}
|
|
||||||
|
|
||||||
/// Watches the input file and recompiles on changes
|
/// Opens the output file after compilation using the default PDF viewer
|
||||||
#[derive(Debug, Clone, Parser)]
|
#[arg(long = "open")]
|
||||||
pub struct WatchCommand {
|
open: Option<Option<String>>,
|
||||||
/// Path to input Typst file
|
|
||||||
input: PathBuf,
|
|
||||||
|
|
||||||
/// Path to output PDF file
|
|
||||||
output: Option<PathBuf>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List all discovered fonts in system and custom font paths
|
/// List all discovered fonts in system and custom font paths
|
||||||
#[derive(Debug, Clone, Parser)]
|
#[derive(Debug, Clone, Parser)]
|
||||||
pub struct FontsCommand {
|
pub struct FontsCommand {
|
||||||
/// Add additional directories to search for fonts
|
/// Also list style variants of each font family
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
variants: bool,
|
variants: bool,
|
||||||
}
|
}
|
||||||
@ -107,6 +101,9 @@ struct CompileSettings {
|
|||||||
|
|
||||||
/// The paths to search for fonts.
|
/// The paths to search for fonts.
|
||||||
font_paths: Vec<PathBuf>,
|
font_paths: Vec<PathBuf>,
|
||||||
|
|
||||||
|
/// The open command to use.
|
||||||
|
open: Option<Option<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompileSettings {
|
impl CompileSettings {
|
||||||
@ -117,13 +114,13 @@ impl CompileSettings {
|
|||||||
watch: bool,
|
watch: bool,
|
||||||
root: Option<PathBuf>,
|
root: Option<PathBuf>,
|
||||||
font_paths: Vec<PathBuf>,
|
font_paths: Vec<PathBuf>,
|
||||||
|
open: Option<Option<String>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let output = match output {
|
let output = match output {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => input.with_extension("pdf"),
|
None => input.with_extension("pdf"),
|
||||||
};
|
};
|
||||||
|
Self { input, output, watch, root, font_paths, open }
|
||||||
Self { input, output, watch, root, font_paths }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new compile settings from the CLI arguments and a compile command.
|
/// Create a new compile settings from the CLI arguments and a compile command.
|
||||||
@ -131,12 +128,13 @@ impl CompileSettings {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
/// Panics if the command is not a compile or watch command.
|
/// Panics if the command is not a compile or watch command.
|
||||||
pub fn with_arguments(args: CliArguments) -> Self {
|
pub fn with_arguments(args: CliArguments) -> Self {
|
||||||
let (input, output, watch) = match args.command {
|
let watch = matches!(args.command, Command::Watch(_));
|
||||||
Command::Compile(command) => (command.input, command.output, false),
|
let CompileCommand { input, output, open } = match args.command {
|
||||||
Command::Watch(command) => (command.input, command.output, true),
|
Command::Compile(command) => command,
|
||||||
|
Command::Watch(command) => command,
|
||||||
_ => unreachable!(),
|
_ => 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.
|
/// Execute a compilation command.
|
||||||
fn compile(command: CompileSettings) -> StrResult<()> {
|
fn compile(mut command: CompileSettings) -> StrResult<()> {
|
||||||
let root = if let Some(root) = &command.root {
|
let root = if let Some(root) = &command.root {
|
||||||
root.clone()
|
root.clone()
|
||||||
} else if let Some(dir) = command
|
} else if let Some(dir) = command
|
||||||
@ -215,6 +213,14 @@ fn compile(command: CompileSettings) -> StrResult<()> {
|
|||||||
|
|
||||||
// Perform initial compilation.
|
// Perform initial compilation.
|
||||||
let failed = compile_once(&mut world, &command)?;
|
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 {
|
if !command.watch {
|
||||||
// Return with non-zero exit code in case of error.
|
// Return with non-zero exit code in case of error.
|
||||||
if failed {
|
if failed {
|
||||||
@ -258,6 +264,11 @@ fn compile(command: CompileSettings) -> StrResult<()> {
|
|||||||
if recompile {
|
if recompile {
|
||||||
compile_once(&mut world, &command)?;
|
compile_once(&mut world, &command)?;
|
||||||
comemo::evict(30);
|
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(())
|
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.
|
/// Execute a font listing command.
|
||||||
fn fonts(command: FontsSettings) -> StrResult<()> {
|
fn fonts(command: FontsSettings) -> StrResult<()> {
|
||||||
let mut searcher = FontSearcher::new();
|
let mut searcher = FontSearcher::new();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user