diff options
author | Norbert Preining <norbert@preining.info> | 2023-03-13 03:04:43 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-03-13 03:04:43 +0000 |
commit | e3c18c7072eebabaa706008b7fa42c73ec2ff83e (patch) | |
tree | bdd26a908e2baa0a97a38169346e53b9e6e51944 /support/texlab/src/features/workspace_command/clean.rs | |
parent | b3d8df92a44aa1df24a0869d728b45b0baeaa54c (diff) |
CTAN sync 202303130304
Diffstat (limited to 'support/texlab/src/features/workspace_command/clean.rs')
-rw-r--r-- | support/texlab/src/features/workspace_command/clean.rs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/support/texlab/src/features/workspace_command/clean.rs b/support/texlab/src/features/workspace_command/clean.rs new file mode 100644 index 0000000000..cea22fc687 --- /dev/null +++ b/support/texlab/src/features/workspace_command/clean.rs @@ -0,0 +1,95 @@ +use std::process::Stdio; + +use anyhow::Result; +use lsp_types::{TextDocumentIdentifier, Url}; +use thiserror::Error; + +use crate::{db::Workspace, normalize_uri, Db}; + +#[derive(Debug, Error)] +pub enum CleanError { + #[error("document '{0}' not found")] + DocumentNotFound(Url), + + #[error("document '{0}' is not a local file")] + NoLocalFile(Url), + + #[error("document was not provided as an argument")] + MissingArg, + + #[error("invalid argument: {0}")] + InvalidArg(serde_json::Error), + + #[error("failed to spawn process: {0}")] + Spawn(std::io::Error), +} + +#[derive(Debug)] +pub struct CleanCommand { + executable: String, + args: Vec<String>, +} + +impl CleanCommand { + pub fn new(db: &dyn Db, options: CleanOptions, args: Vec<serde_json::Value>) -> Result<Self> { + let params: TextDocumentIdentifier = + serde_json::from_value(args.into_iter().next().ok_or(CleanError::MissingArg)?) + .map_err(CleanError::InvalidArg)?; + + let mut uri = params.uri; + normalize_uri(&mut uri); + + let workspace = Workspace::get(db); + + let document = workspace + .lookup_uri(db, &uri) + .ok_or_else(|| CleanError::DocumentNotFound(uri.clone()))?; + + let working_dir = workspace.working_dir(db, document.directory(db)); + + let output_dir = workspace + .output_dir(db, working_dir) + .path(db) + .as_deref() + .ok_or_else(|| CleanError::NoLocalFile(uri.clone()))?; + + let path = document + .location(db) + .path(db) + .as_deref() + .ok_or_else(|| CleanError::NoLocalFile(uri.clone()))?; + + let flag = match options { + CleanOptions::Auxiliary => "-c", + CleanOptions::Artifacts => "-C", + }; + + let executable = "latexmk".to_string(); + let args = vec![ + format!("-outdir={}", output_dir.display()), + flag.to_string(), + path.display().to_string(), + ]; + + Ok(Self { executable, args }) + } + + pub fn run(self) -> Result<()> { + log::debug!("Cleaning output files: {} {:?}", self.executable, self.args); + std::process::Command::new(self.executable) + .args(self.args) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .map_err(move |msg| anyhow::Error::new(CleanError::Spawn(msg)))?; + + Ok(()) + } +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub enum CleanOptions { + Auxiliary, + Artifacts, +} |