Skip to content

Commit

Permalink
fix(CompletionProvider): word capturing (#1003)
Browse files Browse the repository at this point in the history
  • Loading branch information
GeopJr authored Jun 13, 2024
1 parent e7f290f commit b1be2ab
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 61 deletions.
87 changes: 32 additions & 55 deletions src/Dialogs/Composer/Completion/CompletionProvider.vala
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,17 @@ public abstract class Tuba.CompletionProvider: Object, GtkSource.CompletionProvi

public static GLib.ListStore EMPTY = new GLib.ListStore (typeof (Object)); // vala-lint=naming-convention

public string? trigger_char { get; construct; }
public unichar trigger_char { get; set; }
protected bool is_capturing_input { get; set; default = false; }
protected int empty_triggers = 0;

public virtual bool is_trigger (Gtk.TextIter iter, unichar ch) {
if (this.trigger_char == null) {
return this.set_input_capture (true);
} else if (ch.to_string () == this.trigger_char) {
return this.set_input_capture (true);
}
return false;
return this.set_input_capture (ch == this.trigger_char);
}

protected bool set_input_capture (bool state) {
this.is_capturing_input = state;
if (state) {
debug ("Capturing input");
} else {
debug ("Stopped capturing input");
this.empty_triggers = 0;
}
return state;
}
Expand All @@ -33,25 +24,10 @@ public abstract class Tuba.CompletionProvider: Object, GtkSource.CompletionProvi
public virtual void activate (GtkSource.CompletionContext context, GtkSource.CompletionProposal proposal) {
Gtk.TextIter start;
Gtk.TextIter end;
context.get_bounds (out start, out end);

// If it reports that we are not at the end
// of the word or line, move forward
if (!end.ends_word () && !end.ends_line ()) {
// If end is ' ', it's already the
// end of the word. Proceeding will
// capture more than needed
if (end.get_char () != ' ')
// Go forwards until we find a space
// aka get the full string - even if
// it's not considered a word by pango
end.forward_find_char ((e) => e.isspace (), null);
// plus a space since we are appending one below
end.forward_char ();
}
get_whole_word_iters (context, out start, out end);

var buffer = start.get_buffer ();
var new_content = proposal.get_typed_text () + " ";
var new_content = get_formatted_text (proposal) + " ";

buffer.begin_user_action ();
buffer.@delete (ref start, ref end);
Expand All @@ -65,34 +41,20 @@ public abstract class Tuba.CompletionProvider: Object, GtkSource.CompletionProvi
GtkSource.CompletionContext context,
GLib.Cancellable? cancellable
) throws Error {
if (!this.is_capturing_input) {
// If it's not capturing,
// check if the character before the word
// is the trigger
Gtk.TextIter start;
context.get_bounds (out start, null);
if (start.backward_char () && is_trigger (start, start.get_char ()))
return yield populate_async (context, cancellable);

return EMPTY;
}
Gtk.TextIter start;
Gtk.TextIter end;
get_whole_word_iters (context, out start, out end);
is_trigger (start, start.get_char ());
if (!this.is_capturing_input) return EMPTY;

string word = get_whole_word (context);
string word = start.get_text (end);
if (word == "") {
debug ("Empty trigger");
this.empty_triggers++;

if (this.empty_triggers > 1) {
this.set_input_capture (false);
}
this.set_input_capture (false);
return EMPTY;
}

var suggestions = yield this.suggest (word, cancellable);

if (word != get_whole_word (context))
return EMPTY;
return suggestions;
return yield this.suggest (word, cancellable);
}

public abstract void display (
Expand All @@ -109,12 +71,27 @@ public abstract class Tuba.CompletionProvider: Object, GtkSource.CompletionProvi
public string get_whole_word (GtkSource.CompletionContext context) {
Gtk.TextIter start;
Gtk.TextIter end;
context.get_bounds (out start, out end);
get_whole_word_iters (context, out start, out end);

// If end is ':', everything until
// a newline will be treated as a word
if (end.get_char () != ':')
end.forward_word_end ();
return start.get_text (end);
}

public void get_whole_word_iters (GtkSource.CompletionContext context, out Gtk.TextIter start, out Gtk.TextIter end) {
context.get_bounds (out start, out end);

if (start.backward_find_char (word_stop, null) && start.get_char ().isspace ()) {
start.forward_char ();
}

end.backward_char ();
end.forward_find_char (word_stop, null);
}

public virtual bool word_stop (unichar ch) {
return ch.isspace ();
}

public virtual string get_formatted_text (GtkSource.CompletionProposal proposal) {
return this.trigger_char.to_string () + proposal.get_typed_text ();
}
}
14 changes: 10 additions & 4 deletions src/Dialogs/Composer/Completion/EmojiProvider.vala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
public class Tuba.EmojiProvider: Tuba.CompletionProvider {

public EmojiProvider () {
Object (trigger_char: ":");
Object (trigger_char: ':');
}

internal class Proposal: Object, GtkSource.CompletionProposal {
Expand All @@ -19,15 +19,17 @@ public class Tuba.EmojiProvider: Tuba.CompletionProvider {
public override async ListModel suggest (string word, Cancellable? cancellable) throws Error {
var results = new GLib.ListStore (typeof (Object));
var emojis = accounts.active.instance_emojis;

if (emojis == null) return results;

string new_word = word.offset (1).down ();
emojis.@foreach (e => {
if (e.shortcode.index_of (word) != 0)
if (e.shortcode.down ().index_of (new_word) != 0)
return true;

var proposal = new Proposal (e);
results.append (proposal);
return true;

return results.n_items < 4;
});

return results;
Expand Down Expand Up @@ -62,4 +64,8 @@ public class Tuba.EmojiProvider: Tuba.CompletionProvider {
break;
}
}

public override bool word_stop (unichar ch) {
return base.word_stop (ch) || (!ch.isalnum () && ch != this.trigger_char);
}
}
6 changes: 5 additions & 1 deletion src/Dialogs/Composer/Completion/HandleProvider.vala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
public class Tuba.HandleProvider: Tuba.CompletionProvider {

public HandleProvider () {
Object (trigger_char: "@");
Object (trigger_char: '@');
}

internal class Proposal: Object, GtkSource.CompletionProposal {
Expand Down Expand Up @@ -61,4 +61,8 @@ public class Tuba.HandleProvider: Tuba.CompletionProvider {
break;
}
}

public override bool word_stop (unichar ch) {
return base.word_stop (ch) || (!ch.isalnum () && ch != this.trigger_char && ch != '.');
}
}
2 changes: 1 addition & 1 deletion src/Dialogs/Composer/Completion/HashtagProvider.vala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
public class Tuba.HashtagProvider: Tuba.CompletionProvider {

public HashtagProvider () {
Object (trigger_char: "#");
Object (trigger_char: '#');
}

internal class Proposal: Object, GtkSource.CompletionProposal {
Expand Down

0 comments on commit b1be2ab

Please sign in to comment.