2121
2222public class Euclide.Completion.Parser : GLib .Object {
2323 private class WordOccurrences {
24- public int occurrences;
24+ private int occurrences;
2525
2626 public WordOccurrences () {
2727 occurrences = 1 ;
@@ -53,13 +53,17 @@ public class Euclide.Completion.Parser : GLib.Object {
5353 return uc == null || DELIMITERS . index_of_char (uc) > - 1 ;
5454 }
5555
56+ // Custom function required so that the tail_map iterator returns all words that have
57+ // the target word as a prefix
5658 public static int compare_words (string word_a , string word_b ) {
59+ // Only compare the first n characters
5760 var scomp = Posix . strncmp (word_a, word_b, word_a. length);
61+ // If same prefix then order by word length
5862 if (scomp == 0 && word_b. length > word_a. length) {
5963 return - 1 ;
6064 }
6165
62- return scomp ;
66+ return 1 ;
6367 }
6468
6569 private Gee . TreeMap<string, WordOccurrences > ? current_tree = null ;
@@ -75,7 +79,6 @@ public class Euclide.Completion.Parser : GLib.Object {
7579 bool pre_existing = true ;
7680
7781 if (! text_view_words. has_key (view)) {
78- // text_view_words.@set (view, new Scratch.Plugins.PrefixTree ());
7982 var new_treemap = new Gee .TreeMap<string, WordOccurrences > (compare_words, null );
8083 new_treemap. set_data< bool > (COMPLETED , false );
8184 new_treemap. set_data< Gee . LinkedList<string> > (WORDS_TO_REMOVE , new Gee .LinkedList<string> ());
@@ -101,7 +104,6 @@ public class Euclide.Completion.Parser : GLib.Object {
101104 }
102105
103106 public void initial_parse_buffer_text (string buffer_text ) {
104- warning (" initial parse buffer - length %u " , buffer_text. length);
105107 parsing_cancelled = false ;
106108 clear ();
107109 if (buffer_text. length > 0 ) {
@@ -111,7 +113,7 @@ public class Euclide.Completion.Parser : GLib.Object {
111113 set_initial_parsing_completed (true );
112114 }
113115
114- warning (" initial parsing %s " , get_initial_parsing_completed () ? " completed" : " INCOMPLETE" );
116+ debug (" initial parsing %s " , get_initial_parsing_completed () ? " completed" : " INCOMPLETE" );
115117 }
116118
117119 // Returns true if text was completely parsed
@@ -125,7 +127,6 @@ public class Euclide.Completion.Parser : GLib.Object {
125127 return ! parsing_cancelled;
126128 }
127129
128- // Returns whether text was completely parsed
129130 public bool parse_text_and_remove (string text ) {
130131 if (text. length < MINIMUM_WORD_LENGTH ) {
131132 return false ;
@@ -148,8 +149,6 @@ public class Euclide.Completion.Parser : GLib.Object {
148149 out string word_before ,
149150 out string word_after
150151 ) {
151-
152- // warning ("get words before and after pos %i", offset);
153152 var pos = offset;
154153 word_before = " " ;
155154 word_after = " " ;
@@ -162,8 +161,6 @@ public class Euclide.Completion.Parser : GLib.Object {
162161 if (forward_word_end (text, ref pos, true ) && pos >= offset) {
163162 word_after = text. slice (offset, pos);
164163 }
165-
166- // warning ("got word before %s, word after %s", word_before, word_after);
167164 }
168165
169166 public string get_word_immediately_before (string text , int end_pos ) {
@@ -191,11 +188,9 @@ public class Euclide.Completion.Parser : GLib.Object {
191188 var start = pos;
192189 forward_word_end (text, ref pos);
193190 word = text. slice (start, pos). strip ();
194- // warning ("found %s", word);
195191 return true ;
196192 }
197193
198- // warning ("Next word not found");
199194 return false ;
200195 }
201196
@@ -205,7 +200,6 @@ public class Euclide.Completion.Parser : GLib.Object {
205200 // Offset is in bytes NOT unichars!
206201 private bool forward_word_start (string text , ref int offset , bool immediate = false ) {
207202 if (offset >= text. length - MINIMUM_WORD_LENGTH ) {
208- // warning ("offset too large");
209203 return false ;
210204 }
211205
@@ -215,25 +209,21 @@ public class Euclide.Completion.Parser : GLib.Object {
215209
216210 // Skip delimiters before word
217211 do {
218- // warning ("forward word end while IS delimiter - pos %i", offset);
219212 found = text. get_next_char (ref offset, out uc);
220213 delimiters++ ;
221214 } while (found && is_delimiter (uc));
222215
223216 if (immediate && delimiters > 0 ) {
224- // warning ("Found preceding delimiters - not immediate");
225217 return false ;
226218 }
227219
228220 if (! found) {
229221 // Unable to find next non-delimiter in text - must be end of text
230- // warning (" no more word starts");
231222 return false ;
232223 }
233224
234225 // Skip back
235226 text. get_prev_char (ref offset, out uc);
236- // warning ("word start after skip back offset %i", offset);
237227 return true ;
238228 }
239229
@@ -243,7 +233,6 @@ public class Euclide.Completion.Parser : GLib.Object {
243233 // Offset is in bytes NOT unichars!
244234 private bool forward_word_end (string text , ref int offset , bool immediate = false ) {
245235 if (offset >= text. length) {
246- // warning ("offset too large");
247236 return false ;
248237 }
249238
@@ -253,7 +242,6 @@ public class Euclide.Completion.Parser : GLib.Object {
253242
254243 // Skip delimiters before word
255244 do {
256- // warning ("forward word end while IS delimiter - pos %i", offset);
257245 found = text. get_next_char (ref offset, out uc);
258246 delimiters++ ;
259247 } while (found && is_delimiter (uc));
@@ -264,24 +252,20 @@ public class Euclide.Completion.Parser : GLib.Object {
264252 }
265253
266254 if (! found) { // Reached end of text without finding target
267- // warning ("No more word ends");
268255 return false ;
269256 }
270257
271258 // Skip chars in word
272259 do {
273- // warning ("forward word end while IS char - pos %i", offset);
274260 found = text. get_next_char (ref offset, out uc);
275261 } while (found && ! is_delimiter (uc));
276262
277263 if (! found) { // Reached end of text without finding target
278- // warning ("End of text is word end - pos %i", offset);
279264 return true ;
280265 }
281266
282267 // Pointing after first delimiter after word end - back up if not text end
283268 text. get_prev_char (ref offset, out uc);
284- // warning ("word end after skip back offset %i", offset);
285269 return true ;
286270 }
287271
@@ -291,32 +275,29 @@ public class Euclide.Completion.Parser : GLib.Object {
291275 unichar? uc = null ;
292276 bool found = false ;
293277 int delimiters = - 1 ;
278+
294279 // Skip delimiters before start point
295280 do {
296- // warning ("backward word start while IS delimiter - pos %i", offset);
297281 found = text. get_prev_char (ref offset, out uc);
298282 delimiters++ ;
299283 } while (found && is_delimiter (uc));
300284
301285 if (immediate && delimiters > 0 ) {
302- // warning ("Found preceding delimiters - not immediate");
303286 return false ;
304287 }
305288
306289 if (! found) {
307290 // Unable to find next non-delimiter before
308- // warning (" no more word starts");
309291 return false ;
310292 }
311293
312294 // Skip chars before in word
313295 do {
314- // warning ("forward word end while IS char - pos %i", offset);
315296 found = text. get_prev_char (ref offset, out uc);
316297 } while (found && ! is_delimiter (uc));
317298
318- if (! found) { // Reached start of text without finding target - must be word start
319- // warning ("Start of text is word start - pos %i", offset);
299+ if (! found) {
300+ // Reached start of text without finding target - must be word start
320301 return true ;
321302 }
322303
@@ -335,28 +316,20 @@ public class Euclide.Completion.Parser : GLib.Object {
335316 parsing_cancelled = false ;
336317 }
337318
338- private Gee .SortedMap<string, WordOccurrences > get_submap_for_prefix (string prefix ) {
339- return current_tree. tail_map (prefix);
340- }
341-
342319 Gee . SortedMap<string, WordOccurrences > sub_map;
343320 public bool match (string prefix ) requires (current_tree != null ) {
344- current_tree. map_iterator (). foreach ((word, occurrences) = > {
345- warning (" current tree: %s (%i )" , word, occurrences. occurrences);
346- return Source . CONTINUE ;
347- });
348- sub_map = get_submap_for_prefix (prefix);
349-
321+ // Keep sub map so do not need to reconstruct in get_completions_for_prefix.
322+ sub_map = current_tree. tail_map (prefix);
350323 bool found = false ;
351324 sub_map. map_iterator (). foreach ((word, occurrences) = > {
352325 if (word. has_prefix (prefix)) {
353- // if (occurrences.occurs ()) {
326+ if (occurrences. occurs ()) {
354327 found = true ;
355- return false ; // At least one match
356- // }
328+ return Source . REMOVE ; // At least one match
329+ }
357330 }
358331
359- return true ; // Continue iterations
332+ return Source . CONTINUE ;
360333 });
361334
362335 return found;
@@ -367,36 +340,37 @@ public class Euclide.Completion.Parser : GLib.Object {
367340 var completions = new List<string> ();
368341 var list = new List<string> ();
369342 var prefix_length = prefix. length;
370- assert (sub_map != null );
343+ // Sub map should always have been constructed in `match ()` function before coming here
344+ assert (sub_map != null );
371345 var count = 0 ;
372346 sub_map. map_iterator (). @foreach ((word, occurrences) = > {
373- // warning ("sub_map: %s (%i)", word, occurrences.occurrences);
347+ // Submap (tail_map) sometimes contains unexpected word *before* prefix_length
348+ // Possibly a bug in Gee? It also contains words that do not start with prefix,
349+ // but required words will be contiguous.
374350 if (word. has_prefix (prefix)) {
375- var completion = word. slice (prefix_length, word. length);
376- // warning ("completion is: %s", completion);
377351 if (occurrences. occurs ()) {
352+ var completion = word. slice (prefix_length, word. length);
378353 completions. prepend (completion);
379354 }
380355
381356 count++ ;
382- return true ;
357+ return Source . CONTINUE ;
383358 }
384359
385360 return count == 0 ; // Ignore words before prefix
386361 });
387362
363+ sub_map = null ;
388364 return (owned )completions;
389365 }
390366
391367 // Only call if known that @word is a single word
392368 public void add_word (string word_to_add ) requires (current_tree != null ) {
393369 if (is_valid_word (word_to_add)) {
394370 if (current_tree. has_key (word_to_add)) {
395- // warning ("found word %s", word_to_add);
396371 var word_occurrences = current_tree. @get (word_to_add);
397372 word_occurrences. increment ();
398373 } else {
399- warning (" inserting new word %s " , word_to_add);
400374 current_tree. @set (word_to_add, new WordOccurrences ());
401375 }
402376 }
@@ -412,10 +386,8 @@ public class Euclide.Completion.Parser : GLib.Object {
412386 var word_occurrences = current_tree. @get (word_to_remove);
413387 word_occurrences. decrement ();
414388 if (! word_occurrences. occurs ()) {
415- warning (" %s does not occur - schedule remove" , word_to_remove);
416389 var words_to_remove = get_words_to_remove ();
417390 words_to_remove. add (word_to_remove);
418- warning (" words to remove length %i " , words_to_remove. size);
419391 schedule_reaping ();
420392 }
421393 }
@@ -428,7 +400,6 @@ public class Euclide.Completion.Parser : GLib.Object {
428400
429401 private bool reaping_cancelled = false ;
430402 private void cancel_reaping () {
431- warning (" cancel reaping" );
432403 if (reaper_timeout_id > 0 ) {
433404 Source . remove (reaper_timeout_id);
434405 }
@@ -448,16 +419,13 @@ public class Euclide.Completion.Parser : GLib.Object {
448419 } else {
449420 reaper_timeout_id = 0 ;
450421 var words_to_remove = get_words_to_remove ();
451- warning (" reaping %i words" , words_to_remove. size);
452422 words_to_remove. foreach ((word) = > {
453423 if (reaping_cancelled) {
454- warning (" reaping cancelled!" );
455424 return false ;
456425 }
457426
458427 var occurrences = current_tree. @get (word);
459428 if (occurrences != null && ! occurrences. occurs ()) {
460- warning (" Reaping %s " , word);
461429 current_tree. unset (word);
462430 }
463431
0 commit comments