Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework word completion: 3 new parser functions #1526

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 18 additions & 25 deletions plugins/word-completion/completion-provider.vala
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,9 @@ public class Scratch.Plugins.CompletionProvider : Gtk.SourceCompletionProvider,
}

public bool match (Gtk.SourceCompletionContext context) {
Gtk.TextIter start, end;
buffer.get_iter_at_offset (out end, buffer.cursor_position);
start = end.copy ();
Euclide.Completion.Parser.back_to_word_start (ref start);
string text = buffer.get_text (start, end, true);
Gtk.TextIter iter;
buffer.get_iter_at_offset (out iter, buffer.cursor_position);
string text = parser.get_word_immediately_before (iter);

return parser.match (text);
}
Expand Down Expand Up @@ -94,21 +92,10 @@ public class Scratch.Plugins.CompletionProvider : Gtk.SourceCompletionProvider,
return 0;
}

public bool get_start_iter (Gtk.SourceCompletionContext context,
Gtk.SourceCompletionProposal proposal,
out Gtk.TextIter iter) {
var mark = buffer.get_insert ();
Gtk.TextIter cursor_iter;
buffer.get_iter_at_mark (out cursor_iter, mark);

iter = cursor_iter;
Euclide.Completion.Parser.back_to_word_start (ref iter);
return true;
}


private bool get_proposals (out GLib.List<Gtk.SourceCompletionItem>? props, bool no_minimum) {
string to_find = "";
string completion = "";
bool have_selection = true;
Gtk.TextBuffer temp_buffer = buffer;
props = null;

Expand All @@ -118,12 +105,10 @@ public class Scratch.Plugins.CompletionProvider : Gtk.SourceCompletionProvider,
to_find = temp_buffer.get_text (start, end, true);

if (to_find.length == 0) {
temp_buffer.get_iter_at_offset (out end, buffer.cursor_position);

start = end;
Euclide.Completion.Parser.back_to_word_start (ref start);

to_find = buffer.get_text (start, end, false);
have_selection = false;
Gtk.TextIter iter;
temp_buffer.get_iter_at_offset (out iter, buffer.cursor_position);
to_find = parser.get_word_immediately_before (iter);
}

buffer.move_mark_by_name (COMPLETION_END_MARK_NAME, end);
Expand All @@ -135,9 +120,17 @@ public class Scratch.Plugins.CompletionProvider : Gtk.SourceCompletionProvider,
List<string> prop_word_list;
if (parser.get_for_word (to_find, out prop_word_list)) {
foreach (var word in prop_word_list) {
// If there is a selection the start mark is at start of completion
// otherwise it is at the cursor position but we want to replace from
// the start of the word
if (have_selection) {
completion = word;
} else {
completion = word.substring (to_find.length);
}
var item = new Gtk.SourceCompletionItem ();
item.label = word;
item.text = word;
item.text = completion;
props.append (item);
}

Expand Down
62 changes: 57 additions & 5 deletions plugins/word-completion/engine.vala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

public class Euclide.Completion.Parser : GLib.Object {
public const int MINIMUM_WORD_LENGTH = 1;
public const int MAXIMUM_WORD_LENGTH = 50;

public const int MAX_TOKENS = 1000000;

private Scratch.Plugins.PrefixTree prefix_tree;
Expand All @@ -29,11 +31,6 @@ public class Euclide.Completion.Parser : GLib.Object {
return DELIMITERS.index_of_char (c) >= 0;
}

public static void back_to_word_start (ref Gtk.TextIter iter) {
iter.backward_find_char (is_delimiter, null);
iter.forward_char ();
}

public Gee.HashMap<Gtk.TextView,Scratch.Plugins.PrefixTree> text_view_words;
public bool parsing_cancelled = false;

Expand Down Expand Up @@ -98,4 +95,59 @@ public class Euclide.Completion.Parser : GLib.Object {
}
return true;
}

public string get_word_immediately_before (Gtk.TextIter iter) {
int end_pos;
var text = get_sentence_at_iter (iter, out end_pos);
var pos = end_pos;
unichar uc;
text.get_prev_char (ref pos, out uc);
if (is_delimiter (uc)) {
return "";
}

pos = (end_pos - MAXIMUM_WORD_LENGTH - 1).clamp (0, end_pos);
if (pos >= end_pos) {
critical ("pos after end_pos");
return "";
}

var sliced_text = text.slice (pos, end_pos);
var words = sliced_text.split_set (DELIMITERS);
var previous_word = words[words.length - 1]; // Maybe ""
return previous_word;
}

public string get_word_immediately_after (Gtk.TextIter iter) {
int start_pos;
var text = get_sentence_at_iter (iter, out start_pos);
var pos = start_pos;
unichar uc;
text.get_next_char (ref pos, out uc);
if (is_delimiter (uc)) {
return "";
}

// Find end of search range
pos = (start_pos + MAXIMUM_WORD_LENGTH + 1).clamp (start_pos, text.length);
if (start_pos >= pos) {
critical ("start pos after pos");
return "";
}

// Find first word in range
var words = text.slice (start_pos, pos).split_set (DELIMITERS, 2);
var next_word = words[0]; // Maybe ""
return next_word;
}

private string get_sentence_at_iter (Gtk.TextIter iter, out int iter_sentence_offset) {
var start_iter = iter;
var end_iter = iter;
start_iter.backward_sentence_start ();
end_iter.forward_sentence_end ();
var text = start_iter.get_text (end_iter);
iter_sentence_offset = iter.get_offset () - start_iter.get_offset ();
return text;
}
}
5 changes: 1 addition & 4 deletions plugins/word-completion/plugin.vala
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,7 @@ public class Scratch.Plugins.Completion : Peas.ExtensionBase, Peas.Activatable {
Gtk.TextIter cursor_iter;
buffer.get_iter_at_mark (out cursor_iter, mark);

var word_start = cursor_iter;
Euclide.Completion.Parser.back_to_word_start (ref word_start);

string word = buffer.get_text (word_start, cursor_iter, false);
string word = parser.get_word_immediately_before (cursor_iter);
parser.add_word (word);
}

Expand Down
Loading