mirror of
https://github.com/latex-lsp/texlab.git
synced 2025-08-04 02:39:21 +00:00
parent
5657aed565
commit
6edb7d4aa7
5 changed files with 158 additions and 5 deletions
21
docs/custom_commands.md
Normal file
21
docs/custom_commands.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Custom Commands
|
||||
|
||||
The server provides the following commands through the `workspace/executeCommand` request:
|
||||
|
||||
## texlab.cleanAuxiliary
|
||||
|
||||
Removes the auxiliary files produced by compiling the specified LaTeX document.
|
||||
At the moment, this command simply calls `latexmk -c` with the currently configured output directory.
|
||||
|
||||
Parameters:
|
||||
|
||||
- `document`: `TextDocumentIdentifier` (_Required_)
|
||||
|
||||
## texlab.cleanArtifacts
|
||||
|
||||
Removes the auxiliary files and the artifacts produced by compiling the specified LaTeX document.
|
||||
At the moment, this command simply calls `latexmk -C` with the currently configured output directory.
|
||||
|
||||
Parameters:
|
||||
|
||||
- `document`: `TextDocumentIdentifier` (_Required_)
|
|
@ -3,6 +3,7 @@ mod build;
|
|||
mod completion;
|
||||
mod cursor;
|
||||
mod definition;
|
||||
mod execute_command;
|
||||
mod folding;
|
||||
mod formatting;
|
||||
mod forward_search;
|
||||
|
@ -25,6 +26,7 @@ pub use self::completion::{complete, CompletionItemData, COMPLETION_LIMIT};
|
|||
pub use self::{
|
||||
build::{BuildEngine, BuildParams, BuildResult, BuildStatus},
|
||||
definition::goto_definition,
|
||||
execute_command::execute_command,
|
||||
folding::find_foldings,
|
||||
formatting::format_source_code,
|
||||
forward_search::{execute_forward_search, ForwardSearchResult, ForwardSearchStatus},
|
||||
|
|
103
src/features/execute_command.rs
Normal file
103
src/features/execute_command.rs
Normal file
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
|
@ -17,10 +17,11 @@ use crate::{
|
|||
dispatch::{NotificationDispatcher, RequestDispatcher},
|
||||
distro::Distribution,
|
||||
features::{
|
||||
find_all_references, find_document_highlights, find_document_links, find_document_symbols,
|
||||
find_foldings, find_hover, find_workspace_symbols, format_source_code, goto_definition,
|
||||
prepare_rename_all, rename_all, BuildEngine, BuildParams, BuildResult, BuildStatus,
|
||||
FeatureRequest, ForwardSearchResult, ForwardSearchStatus,
|
||||
execute_command, find_all_references, find_document_highlights, find_document_links,
|
||||
find_document_symbols, find_foldings, find_hover, find_workspace_symbols,
|
||||
format_source_code, goto_definition, prepare_rename_all, rename_all, BuildEngine,
|
||||
BuildParams, BuildResult, BuildStatus, FeatureRequest, ForwardSearchResult,
|
||||
ForwardSearchStatus,
|
||||
},
|
||||
req_queue::{IncomingData, ReqQueue},
|
||||
ClientCapabilitiesExt, DocumentLanguage, Environment, LineIndex, LineIndexExt, Options,
|
||||
|
@ -127,6 +128,13 @@ impl Server {
|
|||
})),
|
||||
document_highlight_provider: Some(OneOf::Left(true)),
|
||||
document_formatting_provider: Some(OneOf::Left(true)),
|
||||
execute_command_provider: Some(ExecuteCommandOptions {
|
||||
commands: vec![
|
||||
"texlab.cleanAuxiliary".into(),
|
||||
"texlab.cleanArtifacts".into(),
|
||||
],
|
||||
..Default::default()
|
||||
}),
|
||||
..ServerCapabilities::default()
|
||||
}
|
||||
}
|
||||
|
@ -668,6 +676,24 @@ impl Server {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_command(&self, id: RequestId, params: ExecuteCommandParams) -> Result<()> {
|
||||
self.spawn(move |server| {
|
||||
let result = execute_command(&server.workspace, ¶ms.command, params.arguments);
|
||||
let response = match result {
|
||||
Ok(()) => lsp_server::Response::new_ok(id, ()),
|
||||
Err(why) => lsp_server::Response::new_err(
|
||||
id,
|
||||
lsp_server::ErrorCode::InternalError as i32,
|
||||
why.to_string(),
|
||||
),
|
||||
};
|
||||
|
||||
server.connection.sender.send(response.into()).unwrap();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn semantic_tokens_range(
|
||||
&self,
|
||||
_id: RequestId,
|
||||
|
@ -765,6 +791,7 @@ impl Server {
|
|||
.on::<ForwardSearchRequest, _>(|id, params| {
|
||||
self.forward_search(id, params)
|
||||
})?
|
||||
.on::<ExecuteCommand,_>(|id, params| self.execute_command(id, params))?
|
||||
.on::<SemanticTokensRangeRequest, _>(|id, params| {
|
||||
self.semantic_tokens_range(id, params)
|
||||
})?
|
||||
|
|
|
@ -137,7 +137,7 @@ impl Workspace {
|
|||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn find_parent(&self, uri: &Url) -> Option<Document> {
|
||||
pub fn find_parent(&self, uri: &Url) -> Option<Document> {
|
||||
self.slice(uri)
|
||||
.documents_by_uri
|
||||
.values()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue