cli: Allow setting an output directory

This allows setting an output directory with a new `--output-path` argument.

The following command writes the output file to `build/test.pdf`. If the `build`
directory does not exist yet, it is created.

```sh
typst compile -fpdf --output-path build test.typ
```

The following also writes the output file to `build/test.pdf`.

```sh
typst compile -fpdf --output-path build src/test.typ
```

When an absolute path to an output file is specified the `--output-path`
argument is ignored:

```sh
typst compile -fpdf --output-path build test.typ /tmp/test.pdf
```
This commit is contained in:
Johannes Neyer 2025-02-18 14:41:27 +01:00
parent a543ee9445
commit 47e9597aec
2 changed files with 18 additions and 1 deletions

View File

@ -224,6 +224,10 @@ pub struct CompileArgs {
#[arg(long = "format", short = 'f')] #[arg(long = "format", short = 'f')]
pub format: Option<OutputFormat>, pub format: Option<OutputFormat>,
/// Directory to write output to.
#[clap(long = "output-path", env = "TYPST_OUTPUT_PATH", value_name = "DIR")]
pub output_path: Option<PathBuf>,
/// World arguments. /// World arguments.
#[clap(flatten)] #[clap(flatten)]
pub world: WorldArgs, pub world: WorldArgs,

View File

@ -112,7 +112,7 @@ impl CompileConfig {
OutputFormat::Pdf OutputFormat::Pdf
}; };
let output = args.output.clone().unwrap_or_else(|| { let mut output = args.output.clone().unwrap_or_else(|| {
let Input::Path(path) = &input else { let Input::Path(path) = &input else {
panic!("output must be specified when input is from stdin, as guarded by the CLI"); panic!("output must be specified when input is from stdin, as guarded by the CLI");
}; };
@ -126,6 +126,19 @@ impl CompileConfig {
)) ))
}); });
if let (Some(output_path), Output::Path(output_file_name)) =
(args.output_path.as_ref(), &mut output)
{
if !output_file_name.is_absolute() {
if !output_path.exists() {
fs::create_dir_all(output_path)
.expect("could not create output path: {err}");
}
*output_file_name =
output_path.join(&output_file_name.file_name().unwrap());
}
}
let pages = args.pages.as_ref().map(|export_ranges| { let pages = args.pages.as_ref().map(|export_ranges| {
PageRanges::new(export_ranges.iter().map(|r| r.0.clone()).collect()) PageRanges::new(export_ranges.iter().map(|r| r.0.clone()).collect())
}); });