diff options
| author | Laurenz <laurmaedje@gmail.com> | 2024-11-09 11:38:13 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2024-11-13 10:21:40 +0100 |
| commit | c526f031ccd41ad10736ef382a824087877accc4 (patch) | |
| tree | 1730ac62d738f5dc274cd9adb3b0f5824bb56fc4 | |
| parent | 6f294eac567bd15510cf5e766c0f7cacec60f7a3 (diff) | |
Fix `#cite` autocompletion
| -rw-r--r-- | crates/typst-ide/src/complete.rs | 21 | ||||
| -rw-r--r-- | crates/typst-ide/src/lib.rs | 19 |
2 files changed, 38 insertions, 2 deletions
diff --git a/crates/typst-ide/src/complete.rs b/crates/typst-ide/src/complete.rs index 699ce573..f7a404d7 100644 --- a/crates/typst-ide/src/complete.rs +++ b/crates/typst-ide/src/complete.rs @@ -1050,7 +1050,7 @@ impl<'a> CompletionContext<'a> { /// A small window of context before the cursor. fn before_window(&self, size: usize) -> &str { - Scanner::new(self.before).from(self.cursor.saturating_sub(size)) + Scanner::new(self.before).get(self.cursor.saturating_sub(size)..self.cursor) } /// Add a prefix and suffix to all applications. @@ -1455,4 +1455,23 @@ mod tests { fn test_autocomplete_before_window_char_boundary() { test("😀😀 #text(font: \"\")", -2); } + + /// Ensure that autocompletion for `#cite(|)` completes bibligraphy labels, + /// but no other labels. + #[test] + fn test_autocomplete_cite_function() { + // First compile a working file to get a document. + let mut world = TestWorld::new("#bibliography(\"works.bib\") <bib>") + .with_asset_by_name("works.bib"); + let doc = typst::compile(&world).output.ok(); + + // Then, add the invalid `#cite` call. Had the document been invalid + // initially, we would have no populated document to autocomplete with. + let end = world.main.len_bytes(); + world.main.edit(end..end, " #cite()"); + + test_with_world_and_doc(&world, doc.as_ref(), -1) + .must_include(["netwok", "glacier-melt", "supplement"]) + .must_exclude(["bib"]); + } } diff --git a/crates/typst-ide/src/lib.rs b/crates/typst-ide/src/lib.rs index 3a192b56..90fc125e 100644 --- a/crates/typst-ide/src/lib.rs +++ b/crates/typst-ide/src/lib.rs @@ -97,6 +97,8 @@ fn summarize_font_family<'a>(variants: impl Iterator<Item = &'a FontInfo>) -> Ec #[cfg(test)] mod tests { + use std::collections::HashMap; + use typst::diag::{FileError, FileResult}; use typst::foundations::{Bytes, Datetime, Smart}; use typst::layout::{Abs, Margin, PageElem}; @@ -108,6 +110,7 @@ mod tests { /// A world for IDE testing. pub struct TestWorld { pub main: Source, + assets: HashMap<FileId, Bytes>, base: &'static TestBase, } @@ -120,10 +123,21 @@ mod tests { let main = Source::new(Self::main_id(), text.into()); Self { main, + assets: HashMap::new(), base: singleton!(TestBase, TestBase::default()), } } + /// Add an additional file to the test world. + #[track_caller] + pub fn with_asset_by_name(mut self, filename: &str) -> Self { + let id = FileId::new(None, VirtualPath::new(filename)); + let data = typst_dev_assets::get_by_name(filename).unwrap(); + let bytes = Bytes::from_static(data); + self.assets.insert(id, bytes); + self + } + /// The ID of the main file in a `TestWorld`. pub fn main_id() -> FileId { *singleton!(FileId, FileId::new(None, VirtualPath::new("main.typ"))) @@ -152,7 +166,10 @@ mod tests { } fn file(&self, id: FileId) -> FileResult<Bytes> { - Err(FileError::NotFound(id.vpath().as_rootless_path().into())) + match self.assets.get(&id) { + Some(bytes) => Ok(bytes.clone()), + None => Err(FileError::NotFound(id.vpath().as_rootless_path().into())), + } } fn font(&self, index: usize) -> Option<Font> { |
