Skip to content

Commit

Permalink
fix: allow completers to trigger on newline characters (#5519)
Browse files Browse the repository at this point in the history
* fix: allow completers to trigger on newline characters
  • Loading branch information
andredcoliveira authored Mar 21, 2024
1 parent f493ab0 commit 6e870fd
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 14 deletions.
1 change: 1 addition & 0 deletions ace.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,7 @@ export namespace Ace {
documentToScreenColumn(row: number, docColumn: number): number;
documentToScreenRow(docRow: number, docColumn: number): number;
getScreenLength(): number;
getPrecedingCharacter(): string;
toJSON(): Object;
destroy(): void;
}
Expand Down
24 changes: 16 additions & 8 deletions src/autocomplete/util.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"use strict";

/**
* @typedef {import("../editor").Editor} Editor
*/

exports.parForEach = function(array, fn, callback) {
var completed = 0;
var arLength = array.length;
Expand Down Expand Up @@ -59,14 +63,18 @@ exports.getCompletionPrefix = function (editor) {
return prefix || this.retrievePrecedingIdentifier(line, pos.column);
};

exports.triggerAutocomplete = function (editor) {
var pos = editor.getCursorPosition();
var line = editor.session.getLine(pos.row);
var column = (pos.column === 0) ? 0 : pos.column - 1;
var previousChar = line[column];
return editor.completers.some((el) => {
if (el.triggerCharacters && Array.isArray(el.triggerCharacters)) {
return el.triggerCharacters.includes(previousChar);
/**
* @param {Editor} editor
* @param {string} [previousChar] if not provided, it falls back to the preceding character in the editor
* @returns {boolean} whether autocomplete should be triggered
*/
exports.triggerAutocomplete = function (editor, previousChar) {
var previousChar = previousChar == null
? editor.session.getPrecedingCharacter()
: previousChar;
return editor.completers.some((completer) => {
if (completer.triggerCharacters && Array.isArray(completer.triggerCharacters)) {
return completer.triggerCharacters.includes(previousChar);
}
});
};
20 changes: 15 additions & 5 deletions src/autocomplete_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ module.exports = {
},
"test: trigger autocomplete for specific characters": function (done) {
var editor = initEditor("document");
var newLineCharacter = editor.session.doc.getNewLineCharacter();

editor.completers = [
{
Expand All @@ -418,18 +419,27 @@ module.exports = {
];
callback(null, completions);
},
triggerCharacters: ["."]
triggerCharacters: [".", newLineCharacter]
}
];

editor.moveCursorTo(0, 8);
sendKey(".");
user.type(".");
var popup = editor.completer.popup;
check(function () {
assert.equal(popup.data.length, 2);
editor.onCommandKey(null, 0, 13);
user.type("Return"); // Accept suggestion
assert.equal(editor.getValue(), "document.all");
done();

user.type(Array(4).fill("Backspace")); // Delete '.all'
user.type("Return"); // Enter new line

check(function() {
assert.equal(popup.data.length, 2);
user.type("Return"); // Accept suggestion
assert.equal(editor.getValue(), `document${newLineCharacter}all`);
done();
});
});

function check(callback) {
Expand Down
14 changes: 14 additions & 0 deletions src/edit_session.js
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,20 @@ class EditSession {
};
}

/**
* @returns {string} the last character preceding the cursor in the editor
*/
getPrecedingCharacter() {
var pos = this.selection.getCursor();

if (pos.column === 0) {
return pos.row === 0 ? "" : this.doc.getNewLineCharacter();
}

var currentLine = this.getLine(pos.row);
return currentLine[pos.column - 1];
}

destroy() {
if (!this.destroyed) {
this.bgTokenizer.setDocument(null);
Expand Down
3 changes: 2 additions & 1 deletion src/ext/language_tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ var showLiveAutocomplete = function(e) {
var editor = e.editor;
var prefix = util.getCompletionPrefix(editor);
// Only autocomplete if there's a prefix that can be matched or previous char is trigger character
var triggerAutocomplete = util.triggerAutocomplete(editor);
var previousChar = e.args;
var triggerAutocomplete = util.triggerAutocomplete(editor, previousChar);
if (prefix && prefix.length >= editor.$liveAutocompletionThreshold || triggerAutocomplete) {
var completer = Autocomplete.for(editor);
// Set a flag for auto shown
Expand Down

0 comments on commit 6e870fd

Please sign in to comment.