summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-11-09 11:38:13 +0100
committerLaurenz <laurmaedje@gmail.com>2024-11-13 10:21:40 +0100
commitc526f031ccd41ad10736ef382a824087877accc4 (patch)
tree1730ac62d738f5dc274cd9adb3b0f5824bb56fc4
parent6f294eac567bd15510cf5e766c0f7cacec60f7a3 (diff)
Fix `#cite` autocompletion
-rw-r--r--crates/typst-ide/src/complete.rs21
-rw-r--r--crates/typst-ide/src/lib.rs19
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> {