diff options
Diffstat (limited to 'support/texlab/src/features/execute_command.rs')
-rw-r--r-- | support/texlab/src/features/execute_command.rs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/support/texlab/src/features/execute_command.rs b/support/texlab/src/features/execute_command.rs new file mode 100644 index 0000000000..b1b89d4f50 --- /dev/null +++ b/support/texlab/src/features/execute_command.rs @@ -0,0 +1,103 @@ +use std::{path::PathBuf, process::Stdio, sync::Arc}; + +use anyhow::Result; +use lsp_types::{TextDocumentIdentifier, Url}; + +use crate::Workspace; + +pub fn execute_command( + workspace: &Workspace, + name: &str, + args: Vec<serde_json::Value>, +) -> Result<()> { + match name { + "texlab.cleanAuxiliary" => { + let params = args + .into_iter() + .next() + .ok_or_else(|| anyhow::anyhow!("texlab.cleanAuxiliary requires one argument"))?; + + clean_output_files(workspace, CleanOptions::Auxiliary, params)?; + } + "texlab.cleanArtifacts" => { + let params = args + .into_iter() + .next() + .ok_or_else(|| anyhow::anyhow!("texlab.cleanArtifacts requires one argument"))?; + + clean_output_files(workspace, CleanOptions::Artifacts, params)?; + } + _ => anyhow::bail!("Unknown command: {}", name), + } + + Ok(()) +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +enum CleanOptions { + Auxiliary, + Artifacts, +} + +fn clean_output_files( + workspace: &Workspace, + options: CleanOptions, + params: serde_json::Value, +) -> Result<()> { + let params: TextDocumentIdentifier = serde_json::from_value(params)?; + + let uri = workspace + .find_parent(¶ms.uri) + .map(|document| document.uri) + .unwrap_or_else(|| Arc::new(params.uri)); + + if let Some(cx) = BuildContext::find(workspace, &uri) { + let flag = match options { + CleanOptions::Auxiliary => "-c", + CleanOptions::Artifacts => "-C", + }; + + std::process::Command::new("latexmk") + .arg(format!("-outdir={}", cx.output_dir.to_string_lossy())) + .arg(flag) + .arg(cx.input_file) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status()?; + } + + Ok(()) +} + +struct BuildContext { + input_file: PathBuf, + output_dir: PathBuf, +} + +impl BuildContext { + pub fn find(workspace: &Workspace, uri: &Url) -> Option<Self> { + if uri.scheme() != "file" { + return None; + } + + let input_file = uri.to_file_path().ok()?; + let options = &workspace.environment.options; + let current_dir = &workspace.environment.current_directory; + let output_dir = match ( + options.root_directory.as_ref(), + options.aux_directory.as_ref(), + ) { + (_, Some(aux_dir)) => current_dir.join(aux_dir), + (Some(root_dir), None) => current_dir.join(root_dir), + (None, None) => input_file.parent()?.to_path_buf(), + }; + + log::info!("Output = {:#?}", output_dir); + + Some(Self { + input_file, + output_dir, + }) + } +} |