Skip to content

Commit 1c04f40

Browse files
committed
add detail in CompletionItem
1 parent 7e7aa63 commit 1c04f40

File tree

3 files changed

+82
-31
lines changed

3 files changed

+82
-31
lines changed

src/basecode_lsp/backend.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl LanguageServer for Backend {
7777
params.text_document.text.clone(),
7878
);
7979

80-
self.add_words(params.text_document.text.clone()).await;
80+
self.add_words(params.text_document.text.clone(), params.text_document.uri.to_string()).await;
8181
self.maybe_update_tmux().await;
8282
}
8383

@@ -103,7 +103,7 @@ impl LanguageServer for Backend {
103103
}
104104
}
105105
for content_change in params.content_changes.iter() {
106-
self.add_words(content_change.text.clone()).await;
106+
self.add_words(content_change.text.clone(), params.text_document.uri.to_string()).await;
107107
}
108108
self.maybe_update_tmux().await;
109109
}
@@ -119,16 +119,18 @@ impl LanguageServer for Backend {
119119
let trie_lock = self.trie.lock().await;
120120
let words = trie_lock.suggest_completions(&prefix);
121121
let suffixes = get_possible_current_word(&current_line, position.character as i32);
122-
words_to_completion_items(words, &suffixes, &mut completions, CompletionItemKind::TEXT);
122+
words_uri_pair_to_completion_items(words, &suffixes, &mut completions, CompletionItemKind::TEXT);
123123

124124
let tmux_words = self.prepare_tmux_words().await;
125-
words_to_completion_items(tmux_words, &suffixes, &mut completions, CompletionItemKind::REFERENCE);
125+
let source = "tmux".to_string();
126+
words_to_completion_items(tmux_words, source, &suffixes, &mut completions, CompletionItemKind::REFERENCE);
126127

127128
if self.lsp_args.command_source {
128129
let mut command_words = get_command_completions();
129130
command_words.sort();
130131
command_words.dedup();
131-
words_to_completion_items(command_words, &suffixes, &mut completions, CompletionItemKind::KEYWORD);
132+
let source = "command".to_string();
133+
words_to_completion_items(command_words, source, &suffixes, &mut completions, CompletionItemKind::KEYWORD);
132134
}
133135

134136
let file_uri = params.text_document_position.text_document.uri.to_string();
@@ -156,12 +158,12 @@ impl Backend {
156158
};
157159
}
158160

159-
async fn add_words(&self, content: String) {
161+
async fn add_words(&self, content: String, uri: String) {
160162
let mut trie_lock = self.trie.lock().await;
161163
for token in content.split_whitespace() {
162164
let words = process_token(token, self.lsp_args.min_word_len);
163165
for w in words {
164-
trie_lock.insert(&w);
166+
trie_lock.insert(&w, &uri);
165167
}
166168
}
167169
}

src/basecode_lsp/trie.rs

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::cmp::max;
55
pub struct TrieNode {
66
children: HashMap<char, TrieNode>,
77
word_count: i32,
8+
uri: String,
89
}
910

1011
#[derive(Debug)]
@@ -19,12 +20,15 @@ impl Trie {
1920
}
2021
}
2122

22-
pub fn insert(&mut self, word: &str) {
23+
pub fn insert(&mut self, word: &str, uri: &str) {
2324
let mut node = &mut self.root;
2425
for char in word.chars() {
2526
node = node.children.entry(char).or_default();
2627
}
2728
node.word_count += 1;
29+
if node.uri.is_empty() {
30+
node.uri = uri.to_string();
31+
}
2832
}
2933

3034
pub fn remove(&mut self, word: &str) {
@@ -49,7 +53,7 @@ impl Trie {
4953
false
5054
}
5155

52-
pub fn suggest_completions(&self, prefix: &str) -> Vec<String> {
56+
pub fn suggest_completions(&self, prefix: &str) -> Vec<(String, String)> {
5357
let mut completions = Vec::new();
5458
let p: Vec<char> = prefix.chars().collect();
5559
self.suggest_completions_helper(&self.root, &p, 0, &mut completions);
@@ -61,7 +65,7 @@ impl Trie {
6165
node: &TrieNode,
6266
prefix: &Vec<char>,
6367
index: usize,
64-
completions: &mut Vec<String>,
68+
completions: &mut Vec<(String, String)>,
6569
) {
6670
if index == prefix.len() {
6771
let mut current = prefix.clone();
@@ -74,9 +78,13 @@ impl Trie {
7478
}
7579
}
7680

77-
fn collect_words(node: &TrieNode, word: &mut Vec<char>, completions: &mut Vec<String>) {
78-
if node.word_count > 0 {
79-
completions.push(word.iter().collect());
81+
fn collect_words(
82+
node: &TrieNode,
83+
word: &mut Vec<char>,
84+
completions: &mut Vec<(String, String)>,
85+
) {
86+
if node.word_count > 0 && !node.uri.is_empty() {
87+
completions.push((word.iter().collect(), node.uri.to_string()));
8088
}
8189

8290
for (&char, child) in node.children.iter() {
@@ -107,9 +115,9 @@ mod tests {
107115
fn test_insert_and_contains() {
108116
let mut trie = Trie::new();
109117

110-
trie.insert("apple");
111-
trie.insert("application");
112-
trie.insert("banana");
118+
trie.insert("apple", "file://");
119+
trie.insert("application", "file://");
120+
trie.insert("banana", "file://");
113121

114122
assert!(trie_contains(&trie, "apple"));
115123
assert!(trie_contains(&trie, "application"));
@@ -122,9 +130,9 @@ mod tests {
122130
fn test_remove() {
123131
let mut trie = Trie::new();
124132

125-
trie.insert("apple");
126-
trie.insert("application");
127-
trie.insert("banana");
133+
trie.insert("apple", "file://");
134+
trie.insert("application", "file://");
135+
trie.insert("banana", "file://");
128136

129137
assert!(trie_contains(&trie, "apple"));
130138
trie.remove("apple");
@@ -138,33 +146,52 @@ mod tests {
138146
fn test_suggest_completions() {
139147
let mut trie = Trie::new();
140148

141-
trie.insert("apple");
142-
trie.insert("application");
143-
trie.insert("banana");
144-
trie.insert("bat");
145-
trie.insert("bear");
149+
trie.insert("apple", "file://");
150+
trie.insert("application", "file://");
151+
trie.insert("banana", "file://");
152+
trie.insert("bat", "file://");
153+
trie.insert("bear", "file://");
146154

147155
let mut completions = trie.suggest_completions("ap");
148156
completions.sort();
149-
assert_eq!(completions, vec!["apple", "application"]);
157+
assert_eq!(
158+
completions,
159+
vec![
160+
("apple".to_string(), "file://".to_string()),
161+
("application".to_string(), "file://".to_string())
162+
]
163+
);
150164

151165
let mut completions = trie.suggest_completions("ba");
152166
completions.sort();
153-
assert_eq!(completions, vec!["banana", "bat"]);
167+
assert_eq!(
168+
completions,
169+
vec![
170+
("banana".to_string(), "file://".to_string()),
171+
("bat".to_string(), "file://".to_string())
172+
]
173+
);
154174

155175
let mut completions = trie.suggest_completions("b");
156176
completions.sort();
157-
assert_eq!(completions, vec!["banana", "bat", "bear"]);
177+
assert_eq!(
178+
completions,
179+
vec![
180+
("banana".to_string(), "file://".to_string()),
181+
("bat".to_string(), "file://".to_string()),
182+
("bear".to_string(), "file://".to_string())
183+
]
184+
);
158185

159186
let completions = trie.suggest_completions("nonexistent");
160-
assert_eq!(completions, Vec::<String>::new());
187+
assert_eq!(completions, Vec::<(String, String)>::new());
161188
}
162189

163190
#[test]
164191
fn test_remove_nonexistent() {
165192
let mut trie = Trie::new();
166193

167-
trie.insert("apple");
194+
trie.insert("apple", "file://");
168195
trie.remove("nonexistent");
169196
assert!(trie_contains(&trie, "apple"));
170197
}
@@ -173,8 +200,8 @@ mod tests {
173200
fn test_remove_multiple() {
174201
let mut trie = Trie::new();
175202

176-
trie.insert("apple");
177-
trie.insert("apple");
203+
trie.insert("apple", "file://");
204+
trie.insert("apple", "file://");
178205
assert!(trie_contains(&trie, "apple"));
179206

180207
trie.remove("apple");

src/basecode_lsp/util.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,29 @@ pub fn get_possible_current_word(current_line: &str, character: i32) -> Vec<Stri
7171
possible
7272
}
7373

74+
pub fn words_uri_pair_to_completion_items(
75+
words: Vec<(String, String)>,
76+
suffixes: &Vec<String>,
77+
completions: &mut Vec<CompletionItem>,
78+
kind: CompletionItemKind,
79+
) {
80+
let items: Vec<CompletionItem> = words
81+
.iter()
82+
.filter(|&item| !suffixes.contains(&item.0))
83+
.map(|item| CompletionItem {
84+
label: item.0.to_string(),
85+
kind: Some(kind),
86+
sort_text: Some(item.0.to_string()),
87+
detail: Some(item.1.to_string()),
88+
..CompletionItem::default()
89+
})
90+
.collect();
91+
completions.extend(items);
92+
}
93+
7494
pub fn words_to_completion_items(
7595
words: Vec<String>,
96+
source: String,
7697
suffixes: &Vec<String>,
7798
completions: &mut Vec<CompletionItem>,
7899
kind: CompletionItemKind,
@@ -84,6 +105,7 @@ pub fn words_to_completion_items(
84105
label: word.clone(),
85106
kind: Some(kind),
86107
sort_text: Some(word.clone()),
108+
detail: Some(source.to_string()),
87109
..CompletionItem::default()
88110
})
89111
.collect();

0 commit comments

Comments
 (0)