diff --git a/Cargo.lock b/Cargo.lock index 5de7d4bd6..bdb036ec3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -567,39 +567,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" -[[package]] -name = "comemo" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5705468fa80602ee6a5f9318306e6c428bffd53e43209a78bc05e6e667c6f4" -dependencies = [ - "comemo-macros 0.3.1", - "siphasher 1.0.0", -] - [[package]] name = "comemo" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df6916408a724339aa77b18214233355f3eb04c42eb895e5f8909215bd8a7a91" dependencies = [ - "comemo-macros 0.4.0", + "comemo-macros", "once_cell", "parking_lot", "siphasher 1.0.0", ] -[[package]] -name = "comemo-macros" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54af6ac68ada2d161fa9cc1ab52676228e340866d094d6542107e74b82acc095" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - [[package]] name = "comemo-macros" version = "0.4.0" @@ -2698,7 +2677,7 @@ source = "git+https://github.com/Myriad-Dreamin/typst.ts?rev=2ba02c5ff3e2ab73584 dependencies = [ "base64 0.22.0", "bitvec", - "comemo 0.4.0", + "comemo", "dashmap", "ecow", "fxhash", @@ -3609,7 +3588,7 @@ dependencies = [ "clap_complete_fig", "clap_mangen", "codespan-reporting", - "comemo 0.4.0", + "comemo", "crossbeam-channel", "env_logger", "futures", @@ -3626,7 +3605,7 @@ dependencies = [ "tokio", "tokio-util", "typst", - "typst-assets", + "typst-assets 0.10.0", "typst-pdf", "typst-preview", "typst-ts-compiler", @@ -3639,7 +3618,7 @@ name = "tinymist-query" version = "0.10.2" dependencies = [ "anyhow", - "comemo 0.4.0", + "comemo", "ena", "fxhash", "indexmap 2.2.5", @@ -3897,7 +3876,7 @@ dependencies = [ "bitflags 2.4.2", "chinese-number", "ciborium", - "comemo 0.4.0", + "comemo", "csv", "ecow", "fontdb", @@ -3937,7 +3916,7 @@ dependencies = [ "ttf-parser", "two-face", "typed-arena", - "typst-assets", + "typst-assets 0.10.0", "typst-macros", "typst-syntax", "typst-timing", @@ -3954,12 +3933,17 @@ name = "typst-assets" version = "0.10.0" source = "git+https://github.com/typst/typst-assets?rev=4d1211a#4d1211ab5ba8a02992a7362000e6dd422d44dd68" +[[package]] +name = "typst-assets" +version = "0.11.0-rc1" +source = "git+https://github.com/typst/typst-assets?tag=v0.11.0-rc1#0ef66188759fc7035be57d9608ccb1ecfd3ef796" + [[package]] name = "typst-ide" version = "0.10.0" source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0#e1daef5ab881af01bd86f2dd9700dd759c017387" dependencies = [ - "comemo 0.4.0", + "comemo", "ecow", "if_chain", "log", @@ -3986,7 +3970,7 @@ source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11. dependencies = [ "base64 0.22.0", "bytemuck", - "comemo 0.4.0", + "comemo", "ecow", "image", "miniz_oxide", @@ -3996,7 +3980,7 @@ dependencies = [ "svg2pdf", "ttf-parser", "typst", - "typst-assets", + "typst-assets 0.10.0", "typst-macros", "typst-timing", "unicode-properties", @@ -4006,14 +3990,14 @@ dependencies = [ [[package]] name = "typst-preview" -version = "0.10.8" +version = "0.10.10" dependencies = [ "anyhow", "await-tree", "clap", "clap_complete", "clap_mangen", - "comemo 0.3.1", + "comemo", "elsa", "env_logger", "futures", @@ -4030,6 +4014,7 @@ dependencies = [ "tokio", "tokio-tungstenite", "typst", + "typst-assets 0.11.0-rc1", "typst-ts-compiler", "typst-ts-core", "typst-ts-svg-exporter", @@ -4041,7 +4026,7 @@ name = "typst-syntax" version = "0.10.0" source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0#e1daef5ab881af01bd86f2dd9700dd759c017387" dependencies = [ - "comemo 0.4.0", + "comemo", "ecow", "once_cell", "serde", @@ -4072,7 +4057,7 @@ dependencies = [ "base64 0.22.0", "chrono", "codespan-reporting", - "comemo 0.4.0", + "comemo", "dirs", "dissimilar", "flate2", @@ -4110,7 +4095,7 @@ dependencies = [ "base64-serde", "bitvec", "byteorder", - "comemo 0.4.0", + "comemo", "crossbeam-queue", "dashmap", "ecow", @@ -4144,7 +4129,7 @@ version = "0.4.2-rc8" source = "git+https://github.com/Myriad-Dreamin/typst.ts?rev=2ba02c5ff3e2ab735849d4e96b331bec14c24a00#2ba02c5ff3e2ab735849d4e96b331bec14c24a00" dependencies = [ "base64 0.22.0", - "comemo 0.4.0", + "comemo", "log", "once_cell", "rayon", diff --git a/Cargo.toml b/Cargo.toml index ea1f56267..a1d1307dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ rust-version = "1.74" [workspace] resolver = "2" -members = ["crates/*", "external/typst-preview"] +members = ["crates/*"] [workspace.dependencies] @@ -39,7 +39,7 @@ typst-pdf = "0.10.0" typst-assets = { git = "https://github.com/typst/typst-assets", rev = "4d1211a" } typst-ts-core = { version = "0.4.2-rc7" } typst-ts-compiler = { version = "0.4.2-rc7" } -typst-preview = { path = "external/typst-preview" } +typst-preview = { git = "https://github.com/Enter-tainer/typst-preview", rev = "b7db246d8a61a2f1caf9d3a6aa6b74ac68c3027c" } lsp-server = "0.7.3" lsp-types = { version = "=0.95.0", features = ["proposed"] } @@ -93,6 +93,8 @@ missing_safety_doc = "warn" undocumented_unsafe_blocks = "warn" [patch.crates-io] + + typst = { git = "https://github.com/Myriad-Dreamin/typst.git", branch = "tinymist-v0.11.0" } typst-ide = { git = "https://github.com/Myriad-Dreamin/typst.git", branch = "tinymist-v0.11.0" } typst-pdf = { git = "https://github.com/Myriad-Dreamin/typst.git", branch = "tinymist-v0.11.0" } @@ -110,3 +112,7 @@ typst-ts-compiler = { git = "https://github.com/Myriad-Dreamin/typst.ts", rev = # typst-ts-svg-exporter = { path = "../typst.ts/exporter/svg" } # typst-ts-core = { path = "../typst.ts/core" } # typst-ts-compiler = { path = "../typst.ts/compiler" } + +# https://github.com/rust-lang/cargo/issues/8690 +[patch."https://github.com/Enter-tainer/typst-preview"] +typst-preview = { path = "external/typst-preview" } diff --git a/crates/tinymist/Cargo.toml b/crates/tinymist/Cargo.toml index 856c2c8b2..be2a184b6 100644 --- a/crates/tinymist/Cargo.toml +++ b/crates/tinymist/Cargo.toml @@ -46,15 +46,16 @@ typst-ts-core = { version = "0.4.2-rc6", default-features = false, features = [ ] } codespan-reporting = "0.11" typst-ts-compiler.workspace = true -typst-preview.workspace = true +typst-preview = { workspace = true, optional = true } lsp-server.workspace = true crossbeam-channel.workspace = true lsp-types.workspace = true [features] -default = ["cli"] +default = ["cli", "preview"] cli = ["clap"] +preview = ["typst-preview"] [build-dependencies] anyhow.workspace = true diff --git a/crates/tinymist/src/actor/typst.rs b/crates/tinymist/src/actor/typst.rs index 57656f4c7..6a3e23e73 100644 --- a/crates/tinymist/src/actor/typst.rs +++ b/crates/tinymist/src/actor/typst.rs @@ -3,7 +3,7 @@ use core::fmt; use std::{ path::{Path, PathBuf}, - sync::{Arc, Mutex as SyncMutex}, + sync::Arc, }; use log::{debug, error, info, trace, warn}; @@ -17,14 +17,11 @@ use tinymist_query::{ use tokio::sync::{broadcast, mpsc, oneshot, watch}; use typst::{ diag::{SourceDiagnostic, SourceResult}, - layout::Position, - syntax::{Span, VirtualPath}, + syntax::VirtualPath, util::Deferred, }; -use typst_preview::{ - CompilationHandle, CompilationHandleImpl, CompileHost, CompileStatus, DocToSrcJumpInfo, - EditorServer, Location, MemoryFiles, MemoryFilesShort, SourceFileServer, -}; +#[cfg(feature = "preview")] +use typst_preview::{CompilationHandle, CompilationHandleImpl, CompileStatus}; use typst_ts_compiler::{ service::{ CompileDriver as CompileDriverInner, CompileExporter, CompileMiddleware, Compiler, @@ -34,8 +31,8 @@ use typst_ts_compiler::{ TypstSystemWorld, }; use typst_ts_core::{ - config::CompileOpts, debug_loc::SourceSpanOffset, error::prelude::*, typst::prelude::EcoVec, - Error, ImmutPath, TypstDocument, TypstWorld, + config::CompileOpts, error::prelude::*, typst::prelude::EcoVec, Error, ImmutPath, + TypstDocument, TypstWorld, }; use super::compile::CompileClient as TsCompileClient; @@ -46,6 +43,21 @@ use crate::{ utils, }; +#[cfg(not(feature = "preview"))] +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[serde(tag = "kind", content = "data")] +pub enum CompileStatus { + Compiling, + CompileSuccess, + CompileError, +} + +#[cfg(not(feature = "preview"))] +pub trait CompilationHandle: Send + 'static { + fn status(&self, status: CompileStatus); + fn notify_compile(&self, res: Result, CompileStatus>); +} + type CompileService = CompileActorInner, H>>; type CompileClient = TsCompileClient>; @@ -92,7 +104,8 @@ pub fn create_server( let inner = Deferred::new({ let current_runtime = tokio::runtime::Handle::current(); let handler = CompileHandler { - inner: Arc::new(SyncMutex::new(None)), + #[cfg(feature = "preview")] + inner: Arc::new(Mutex::new(None)), }; let diag_group = diag_group.clone(); @@ -213,21 +226,28 @@ macro_rules! query_world2 { #[derive(Clone)] pub struct CompileHandler { - inner: Arc>>, + #[cfg(feature = "preview")] + inner: Arc>>, } impl CompilationHandle for CompileHandler { - fn status(&self, status: CompileStatus) { - let inner = self.inner.lock().unwrap(); - if let Some(inner) = inner.as_ref() { - inner.status(status); + fn status(&self, _status: CompileStatus) { + #[cfg(feature = "preview")] + { + let inner = self.inner.lock(); + if let Some(inner) = inner.as_ref() { + inner.status(_status); + } } } - fn notify_compile(&self, result: Result, CompileStatus>) { - let inner = self.inner.lock().unwrap(); - if let Some(inner) = inner.as_ref() { - inner.notify_compile(result.clone()); + fn notify_compile(&self, _result: Result, CompileStatus>) { + #[cfg(feature = "preview")] + { + let inner = self.inner.lock(); + if let Some(inner) = inner.as_ref() { + inner.notify_compile(_result.clone()); + } } } } @@ -296,11 +316,13 @@ pub struct Reporter { position_encoding: PositionEncoding, diag_tx: DiagnosticsSender, inner: C, + #[allow(unused)] cb: H, } -impl, H: CompilationHandle> CompileMiddleware - for Reporter +impl, H> CompileMiddleware for Reporter +where + H: CompilationHandle, { type Compiler = C; @@ -316,15 +338,18 @@ impl, H: CompilationHandle> CompileMiddlew &mut self, env: &mut typst_ts_compiler::service::CompileEnv, ) -> SourceResult> { + #[cfg(feature = "preview")] self.cb.status(CompileStatus::Compiling); match self.inner_mut().compile(env) { Ok(doc) => { + #[cfg(feature = "preview")] self.cb.notify_compile(Ok(doc.clone())); self.notify_diagnostics(EcoVec::new()); Ok(doc) } Err(err) => { + #[cfg(feature = "preview")] self.cb.notify_compile(Err(CompileStatus::CompileError)); self.notify_diagnostics(err); @@ -587,91 +612,6 @@ impl CompileActor { } } -impl SourceFileServer for CompileActor { - async fn resolve_source_span( - &mut self, - loc: Location, - ) -> Result, Error> { - let Location::Src(src_loc) = loc; - self.inner().resolve_src_location(src_loc).await - } - - async fn resolve_document_position( - &mut self, - loc: Location, - ) -> Result, Error> { - let Location::Src(src_loc) = loc; - - let path = Path::new(&src_loc.filepath).to_owned(); - let line = src_loc.pos.line; - let column = src_loc.pos.column; - - self.inner() - .resolve_src_to_doc_jump(path, line, column) - .await - } - - async fn resolve_source_location( - &mut self, - s: Span, - offset: Option, - ) -> Result, Error> { - Ok(self - .inner() - .resolve_span_and_offset(s, offset) - .await - .map_err(|err| { - error!("TypstActor: failed to resolve span and offset: {:#}", err); - }) - .ok() - .flatten() - .map(|e| DocToSrcJumpInfo { - filepath: e.filepath, - start: e.start, - end: e.end, - })) - } -} - -impl EditorServer for CompileActor { - async fn update_memory_files( - &mut self, - files: MemoryFiles, - reset_shadow: bool, - ) -> Result<(), Error> { - // todo: is it safe to believe that the path is normalized? - let now = std::time::SystemTime::now(); - let files = FileChangeSet::new_inserts( - files - .files - .into_iter() - .map(|(path, content)| { - let content = content.as_bytes().into(); - // todo: cloning PathBuf -> Arc - (path.into(), Ok((now, content)).into()) - }) - .collect(), - ); - self.inner().add_memory_changes(if reset_shadow { - MemoryEvent::Sync(files) - } else { - MemoryEvent::Update(files) - }); - - Ok(()) - } - - async fn remove_shadow_files(&mut self, files: MemoryFilesShort) -> Result<(), Error> { - // todo: is it safe to believe that the path is normalized? - let files = FileChangeSet::new_removes(files.files.into_iter().map(From::from).collect()); - self.inner().add_memory_changes(MemoryEvent::Update(files)); - - Ok(()) - } -} - -impl CompileHost for CompileActor {} - impl CompileActor { pub fn query(&self, query: CompilerQueryRequest) -> anyhow::Result { use CompilerQueryRequest::*; @@ -760,3 +700,110 @@ impl CompileActor { Ok(fut?) } } + +#[cfg(feature = "preview")] +mod preview_exts { + use std::path::Path; + + use typst::layout::Position; + use typst::syntax::Span; + use typst_preview::{ + CompileHost, DocToSrcJumpInfo, EditorServer, Location, MemoryFiles, MemoryFilesShort, + SourceFileServer, + }; + use typst_ts_compiler::vfs::notify::FileChangeSet; + use typst_ts_compiler::vfs::notify::MemoryEvent; + use typst_ts_core::debug_loc::SourceSpanOffset; + use typst_ts_core::Error; + + use super::CompileActor; + + #[cfg(feature = "preview")] + impl SourceFileServer for CompileActor { + async fn resolve_source_span( + &mut self, + loc: Location, + ) -> Result, Error> { + let Location::Src(src_loc) = loc; + self.inner().resolve_src_location(src_loc).await + } + + async fn resolve_document_position( + &mut self, + loc: Location, + ) -> Result, Error> { + let Location::Src(src_loc) = loc; + + let path = Path::new(&src_loc.filepath).to_owned(); + let line = src_loc.pos.line; + let column = src_loc.pos.column; + + self.inner() + .resolve_src_to_doc_jump(path, line, column) + .await + } + + async fn resolve_source_location( + &mut self, + s: Span, + offset: Option, + ) -> Result, Error> { + Ok(self + .inner() + .resolve_span_and_offset(s, offset) + .await + .map_err(|err| { + log::error!("TypstActor: failed to resolve span and offset: {:#}", err); + }) + .ok() + .flatten() + .map(|e| DocToSrcJumpInfo { + filepath: e.filepath, + start: e.start, + end: e.end, + })) + } + } + + #[cfg(feature = "preview")] + impl EditorServer for CompileActor { + async fn update_memory_files( + &mut self, + files: MemoryFiles, + reset_shadow: bool, + ) -> Result<(), Error> { + // todo: is it safe to believe that the path is normalized? + let now = std::time::SystemTime::now(); + let files = FileChangeSet::new_inserts( + files + .files + .into_iter() + .map(|(path, content)| { + let content = content.as_bytes().into(); + // todo: cloning PathBuf -> Arc + (path.into(), Ok((now, content)).into()) + }) + .collect(), + ); + self.inner().add_memory_changes(if reset_shadow { + MemoryEvent::Sync(files) + } else { + MemoryEvent::Update(files) + }); + + Ok(()) + } + + async fn remove_shadow_files(&mut self, files: MemoryFilesShort) -> Result<(), Error> { + // todo: is it safe to believe that the path is normalized? + let files = + FileChangeSet::new_removes(files.files.into_iter().map(From::from).collect()); + self.inner().add_memory_changes(MemoryEvent::Update(files)); + + Ok(()) + } + } + + #[cfg(feature = "preview")] + impl CompileHost for CompileActor {} +}