From 2f829f9da00f673dee661b67a4a753348e0239d6 Mon Sep 17 00:00:00 2001 From: Myriad-Dreamin Date: Tue, 12 Dec 2023 14:35:50 +0800 Subject: [PATCH] Let lsp be aware of the pinned file --- editors/vscode/package.json | 18 ++++++++++++++++-- editors/vscode/src/extension.ts | 27 +++++++++++++++++++++++++++ src/config.rs | 2 ++ src/server/command.rs | 24 ++++++++++++++---------- src/server/document.rs | 7 +++++++ src/server/hover.rs | 5 +++-- src/server/lsp.rs | 25 ++++++++++++++++++------- src/server/mod.rs | 4 ++++ 8 files changed, 91 insertions(+), 21 deletions(-) diff --git a/editors/vscode/package.json b/editors/vscode/package.json index 7b52eced..8f92a31f 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -28,12 +28,16 @@ "enum": [ "never", "onSave", - "onType" + "onPinnedMainSave", + "onType", + "onPinnedMainType" ], "enumDescriptions": [ "Never export PDFs, you will manually run typst.", "Export PDFs when you save a file.", - "Export PDFs as you type in a file." + "Export PDFs when you save the pinned file.", + "Export PDFs as you type in a file.", + "Export PDFs as you type in the pinned file." ] }, "typst-lsp.rootPath": { @@ -274,6 +278,16 @@ "title": "Export the currently open file as PDF", "category": "Typst" }, + { + "command": "typst-lsp.pinMainToCurrent", + "title": "Pin the main file to the currently openning document", + "category": "Typst" + }, + { + "command": "typst-lsp.unpinMain", + "title": "Unpin the main file", + "category": "Typst" + }, { "command": "typst-lsp.showPdf", "title": "Show the compiled PDF of the currently opened typst file", diff --git a/editors/vscode/src/extension.ts b/editors/vscode/src/extension.ts index d68f1d66..4eba94dd 100644 --- a/editors/vscode/src/extension.ts +++ b/editors/vscode/src/extension.ts @@ -47,6 +47,12 @@ async function startClient(context: ExtensionContext): Promise { context.subscriptions.push( commands.registerCommand("typst-lsp.exportCurrentPdf", commandExportCurrentPdf) ); + context.subscriptions.push( + commands.registerCommand("typst-lsp.pinMainToCurrent", () => commandPinMain(true)) + ); + context.subscriptions.push( + commands.registerCommand("typst-lsp.unpinMain", () => commandPinMain(false)) + ); context.subscriptions.push(commands.registerCommand("typst-lsp.showPdf", commandShowPdf)); context.subscriptions.push(commands.registerCommand("typst-lsp.clearCache", commandClearCache)); @@ -127,6 +133,27 @@ async function commandExportCurrentPdf(): Promise { }); } +async function commandPinMain(isPin: boolean): Promise { + if (!isPin) { + await client?.sendRequest("workspace/executeCommand", { + command: "typst-lsp.doPinMain", + arguments: ["detached"], + }); + } + + const activeEditor = window.activeTextEditor; + if (activeEditor === undefined) { + return; + } + + const uri = activeEditor.document.uri.toString(); + + await client?.sendRequest("workspace/executeCommand", { + command: "typst-lsp.doPinMain", + arguments: [uri], + }); +} + /** * Implements the functionality for the 'Show PDF' button shown in the editor title * if a `.typ` file is opened. diff --git a/src/config.rs b/src/config.rs index 6f62570d..b2eb9ade 100644 --- a/src/config.rs +++ b/src/config.rs @@ -37,7 +37,9 @@ pub enum ExportPdfMode { Never, #[default] OnSave, + OnPinnedMainSave, OnType, + OnPinnedMainType, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Deserialize)] diff --git a/src/server/command.rs b/src/server/command.rs index 9eede9c7..442ec2f4 100644 --- a/src/server/command.rs +++ b/src/server/command.rs @@ -4,7 +4,7 @@ use tower_lsp::{ jsonrpc::{Error, Result}, lsp_types::Url, }; -use tracing::error; +use tracing::{error, info}; use super::TypstServer; @@ -97,14 +97,18 @@ impl TypstServer { ) }; - self.config - .write() - .await - .update_main_file(file_uri) - .await - .map_err(|err| { - error!(%err, "could not set main file"); - jsonrpc::Error::internal_error() - }) + let update_result = self.config.write().await.update_main_file(file_uri).await; + + update_result.map_err(|err| { + error!(%err, "could not set main file"); + jsonrpc::Error::internal_error() + })?; + + info!( + "main file pinned: {main_url:?}", + main_url = self.main_url().await + ); + + Ok(()) } } diff --git a/src/server/document.rs b/src/server/document.rs index 26815352..527c2640 100644 --- a/src/server/document.rs +++ b/src/server/document.rs @@ -10,6 +10,13 @@ impl TypstServer { let config = self.config.read().await; match config.export_pdf { ExportPdfMode::OnType => self.run_diagnostics_and_export(uri).await?, + ExportPdfMode::OnPinnedMainType => { + if let Some(main_uri) = self.main_url().await { + self.run_diagnostics_and_export(&main_uri).await? + } else { + self.run_diagnostics(uri).await? + } + } _ => self.run_diagnostics(uri).await?, } diff --git a/src/server/hover.rs b/src/server/hover.rs index a60e3973..5d49359f 100644 --- a/src/server/hover.rs +++ b/src/server/hover.rs @@ -17,11 +17,12 @@ impl TypstServer { let doc = self.document.lock().await.clone(); + let fid = self.workspace().read().await.full_id(uri)?; let result = self - .thread_with_world(uri) + .thread_with_world(self.main_url().await.as_ref().unwrap_or(uri)) .await? .run(move |world| { - let source = world.main(); + let source = world.source(fid.into()).ok()?; let typst_offset = lsp_to_typst::position_to_offset(position, position_encoding, &source); diff --git a/src/server/lsp.rs b/src/server/lsp.rs index 4b937630..768bbcab 100644 --- a/src/server/lsp.rs +++ b/src/server/lsp.rs @@ -294,11 +294,18 @@ impl LanguageServer for TypstServer { let config = self.config.read().await; - if config.export_pdf == ExportPdfMode::OnSave { - if let Err(err) = self.run_diagnostics_and_export(&uri).await { - error!(%err, %uri, "could not handle source save"); - }; - } + let uri = match config.export_pdf { + ExportPdfMode::OnPinnedMainSave => Some(self.main_url().await.unwrap_or(uri)), + ExportPdfMode::OnSave => Some(uri), + _ => None, + }; + let Some(uri) = uri else { + return; + }; + + if let Err(err) = self.run_diagnostics_and_export(&uri).await { + error!(%err, %uri, "could not handle source save"); + }; } #[tracing::instrument(skip(self))] @@ -400,15 +407,19 @@ impl LanguageServer for TypstServer { let position_encoding = self.const_config().position_encoding; let doc = { self.document.lock().await.clone() }; + let fid = self.workspace().read().await.full_id(&uri).map_err(|err| { + error!(%err, %uri, "error getting completion"); + jsonrpc::Error::internal_error() + })?; let completions = self - .thread_with_world(&uri) + .thread_with_world(self.main_url().await.as_ref().unwrap_or(&uri)) .await .map_err(|err| { error!(%err, %uri, "error getting completion"); jsonrpc::Error::internal_error() })? .run(move |world| { - let source = world.main(); + let source = world.source(fid.into()).ok()?; let typst_offset = lsp_to_typst::position_to_offset(position, position_encoding, &source); diff --git a/src/server/mod.rs b/src/server/mod.rs index 18b4aab4..11a51f87 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -78,6 +78,10 @@ impl TypstServer { .expect("workspace should be initialized") } + pub async fn main_url(&self) -> Option { + self.config.read().await.main_file.clone() + } + pub fn typst_global_scopes(&self) -> typst::foundations::Scopes { typst::foundations::Scopes::new(Some(&TYPST_STDLIB)) }