From 797f101b83db14a12598290594319115d8e45c5e Mon Sep 17 00:00:00 2001 From: mkslanc Date: Mon, 3 Jul 2023 17:36:27 +0400 Subject: [PATCH 1/4] feat: Update text completer, add token filter property --- src/autocomplete/text_completer.js | 25 ++++++++++++++++++++++--- src/mode/javascript.js | 1 + 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/autocomplete/text_completer.js b/src/autocomplete/text_completer.js index 59791376dc4..bdcf37df703 100644 --- a/src/autocomplete/text_completer.js +++ b/src/autocomplete/text_completer.js @@ -36,14 +36,33 @@ function wordDistance(doc, pos) { return wordScores; } +function completionsFromMode(session, pos) { + var completerTokens = session.$mode.$completerTokens; + var lines = JSON.parse(JSON.stringify(session.bgTokenizer.lines)); + + lines[pos.row] = lines[pos.row].filter(el => el.start !== pos.column - el.value.length); + + var wordList = lines.flat() + .filter(el => el && completerTokens.includes(el.type)) + .map(el => el.value); + + return [...new Set(wordList)]; +} + exports.getCompletions = function (editor, session, pos, prefix, callback) { - var wordScore = wordDistance(session, pos); - var wordList = Object.keys(wordScore); + var wordList; + if (session.$mode.$completerTokens) { + wordList = completionsFromMode(session, pos); + } else { + var wordScore = wordDistance(session, pos); + wordList = Object.keys(wordScore); + } + callback(null, wordList.map(function (word) { return { caption: word, value: word, - score: wordScore[word], + score: wordScore ? wordScore[word] : 0, meta: "local" }; })); diff --git a/src/mode/javascript.js b/src/mode/javascript.js index 8f3ba56da7c..4b2a320113e 100644 --- a/src/mode/javascript.js +++ b/src/mode/javascript.js @@ -25,6 +25,7 @@ oop.inherits(Mode, TextMode); this.$pairQuotesAfter = { "`": /\w/ }; + this.$completerTokens = ["identifier", "entity.name.function"]; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); From 2450d7228ff92abb8edb70911cd1c97f9a1dc613 Mon Sep 17 00:00:00 2001 From: mkslanc Date: Tue, 4 Jul 2023 14:38:53 +0400 Subject: [PATCH 2/4] improve `completionsFromMode` function --- src/autocomplete/text_completer.js | 34 +++++++++++++++++------------- src/mode/javascript.js | 2 +- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/autocomplete/text_completer.js b/src/autocomplete/text_completer.js index bdcf37df703..583182da51f 100644 --- a/src/autocomplete/text_completer.js +++ b/src/autocomplete/text_completer.js @@ -1,6 +1,7 @@ var Range = require("../range").Range; var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/; +var identifierRe = /[a-zA-Z\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*/; function getWordIndex(doc, pos) { var textBefore = doc.getTextRange(Range.fromPoints({ @@ -38,31 +39,34 @@ function wordDistance(doc, pos) { function completionsFromMode(session, pos) { var completerTokens = session.$mode.$completerTokens; - var lines = JSON.parse(JSON.stringify(session.bgTokenizer.lines)); - - lines[pos.row] = lines[pos.row].filter(el => el.start !== pos.column - el.value.length); + var lines = session.bgTokenizer.lines; + var exclude = lines[pos.row].find(el => el.start === pos.column - el.value.length); + var wordScores = Object.create(null); - var wordList = lines.flat() - .filter(el => el && completerTokens.includes(el.type)) - .map(el => el.value); + lines = lines.flat(); + var linesLength = lines.length; + for (var i = 0; i < linesLength; i++) { + var token = lines[i]; + if (!token || exclude && token.value === exclude.value) { + continue; + } + if (completerTokens.includes(token.type) && identifierRe.test(token.value)) { + wordScores[token.value] = 0; + } + } - return [...new Set(wordList)]; + return wordScores; } exports.getCompletions = function (editor, session, pos, prefix, callback) { - var wordList; - if (session.$mode.$completerTokens) { - wordList = completionsFromMode(session, pos); - } else { - var wordScore = wordDistance(session, pos); - wordList = Object.keys(wordScore); - } + var wordScore = session.$mode.$completerTokens ? completionsFromMode(session, pos) : wordDistance(session, pos); + var wordList = Object.keys(wordScore); callback(null, wordList.map(function (word) { return { caption: word, value: word, - score: wordScore ? wordScore[word] : 0, + score: wordScore[word], meta: "local" }; })); diff --git a/src/mode/javascript.js b/src/mode/javascript.js index 4b2a320113e..7db7a892cc9 100644 --- a/src/mode/javascript.js +++ b/src/mode/javascript.js @@ -25,7 +25,7 @@ oop.inherits(Mode, TextMode); this.$pairQuotesAfter = { "`": /\w/ }; - this.$completerTokens = ["identifier", "entity.name.function"]; + this.$completerTokens = ["identifier", "entity.name.function", "storage.type", "variable.parameter"]; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); From ed90389a6da38ab4613834ce12a0b638b0332421 Mon Sep 17 00:00:00 2001 From: mkslanc Date: Wed, 12 Jul 2023 17:56:06 +0400 Subject: [PATCH 3/4] feat: filter comment and strings completions option --- ace.d.ts | 1 + src/autocomplete/text_completer.js | 17 +++++++++-------- src/autocomplete_test.js | 27 +++++++++++++++++++++++++-- src/ext/language_tools.js | 3 +++ src/ext/options.js | 3 +++ src/mode/javascript.js | 1 - 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/ace.d.ts b/ace.d.ts index 81ab5adb784..c1dfce7d6a0 100644 --- a/ace.d.ts +++ b/ace.d.ts @@ -234,6 +234,7 @@ export namespace Ace { relativeLineNumbers: boolean; enableMultiselect: boolean; enableKeyboardAccessibility: boolean; + filterStringsCompletions: boolean; } export interface SearchOptions { diff --git a/src/autocomplete/text_completer.js b/src/autocomplete/text_completer.js index 583182da51f..8084043752e 100644 --- a/src/autocomplete/text_completer.js +++ b/src/autocomplete/text_completer.js @@ -37,20 +37,20 @@ function wordDistance(doc, pos) { return wordScores; } -function completionsFromMode(session, pos) { - var completerTokens = session.$mode.$completerTokens; +function filterStringsFromCompletions(session, pos) { + var filterRegExp = /string|comment|^comment\.doc.*/; var lines = session.bgTokenizer.lines; - var exclude = lines[pos.row].find(el => el.start === pos.column - el.value.length); + var exclude = lines[pos.row] && lines[pos.row].find(el => el.start === pos.column - el.value.length); var wordScores = Object.create(null); - lines = lines.flat(); - var linesLength = lines.length; + var flatLines = lines.flat(); + var linesLength = flatLines.length; for (var i = 0; i < linesLength; i++) { - var token = lines[i]; + var token = flatLines[i]; if (!token || exclude && token.value === exclude.value) { continue; } - if (completerTokens.includes(token.type) && identifierRe.test(token.value)) { + if (!filterRegExp.test(token.type) && identifierRe.test(token.value)) { wordScores[token.value] = 0; } } @@ -59,7 +59,8 @@ function completionsFromMode(session, pos) { } exports.getCompletions = function (editor, session, pos, prefix, callback) { - var wordScore = session.$mode.$completerTokens ? completionsFromMode(session, pos) : wordDistance(session, pos); + var wordScore = editor.$filterStringsCompletions ? filterStringsFromCompletions(session, pos) : wordDistance( + session, pos); var wordList = Object.keys(wordScore); callback(null, wordList.map(function (word) { diff --git a/src/autocomplete_test.js b/src/autocomplete_test.js index 34a1e479e00..3b8ff27335a 100644 --- a/src/autocomplete_test.js +++ b/src/autocomplete_test.js @@ -12,9 +12,11 @@ var user = require("./test/user"); var Range = require("./range").Range; require("./ext/language_tools"); var Autocomplete = require("./autocomplete").Autocomplete; +var textCompleter = require("./autocomplete/text_completer"); +var JavaScriptMode = require("./mode/javascript").Mode; var editor; -function initEditor(value) { +function initEditor(value, mode) { if (editor) { editor.destroy(); editor.container.remove(); @@ -24,7 +26,8 @@ function initEditor(value) { value: value, maxLines: 10, enableBasicAutocompletion: true, - enableLiveAutocompletion: true + enableLiveAutocompletion: true, + mode: mode }); document.body.appendChild(editor.container); editor.focus(); @@ -162,6 +165,26 @@ module.exports = { done(); }); }, + "test: filter strings and comments from local completions list": function (done) { + var editor = initEditor("//comment here\n /**\n * doc comment\n**/'string'\nsomeIdentifier\n", new JavaScriptMode()); + editor.completers = [textCompleter]; + editor.moveCursorTo(3, 0); + editor.renderer.$loop._flush(); + + sendKey("o"); + var popup = editor.completer.popup; + afterRenderCheck(popup, function () { + assert.equal(popup.data.length, 3); + editor.setOption("filterStringsCompletions", true); + editor.onCommandKey(null, 0, 13); + sendKey(" "); + sendKey("o"); + afterRenderCheck(popup, function () { + assert.equal(popup.data.length, 1); //only identifier left + done(); + }); + }); + }, "test: different completers tooltips": function (done) { var editor = initEditor(""); var firstDoc = "First"; diff --git a/src/ext/language_tools.js b/src/ext/language_tools.js index 0f6b9941b5e..d5384f366c5 100644 --- a/src/ext/language_tools.js +++ b/src/ext/language_tools.js @@ -221,5 +221,8 @@ require("../config").defineOptions(Editor.prototype, "editor", { } }, value: false + }, + filterStringsCompletions: { + initialValue: false } }); diff --git a/src/ext/options.js b/src/ext/options.js index f82b82dcc5e..75c774c9a44 100644 --- a/src/ext/options.js +++ b/src/ext/options.js @@ -192,6 +192,9 @@ var optionGroups = { "Live Autocompletion": { path: "enableLiveAutocompletion" }, + "Filter Comments and String Completions": { + path: "filterStringsCompletions" + }, "Custom scrollbar": { path: "customScrollbar" }, diff --git a/src/mode/javascript.js b/src/mode/javascript.js index 7db7a892cc9..8f3ba56da7c 100644 --- a/src/mode/javascript.js +++ b/src/mode/javascript.js @@ -25,7 +25,6 @@ oop.inherits(Mode, TextMode); this.$pairQuotesAfter = { "`": /\w/ }; - this.$completerTokens = ["identifier", "entity.name.function", "storage.type", "variable.parameter"]; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); From dca29c18cff1441867610ed367fe5614d9bcab8c Mon Sep 17 00:00:00 2001 From: mkslanc Date: Mon, 23 Oct 2023 18:06:53 +0400 Subject: [PATCH 4/4] better function name --- src/autocomplete/text_completer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/autocomplete/text_completer.js b/src/autocomplete/text_completer.js index 8084043752e..a090974db82 100644 --- a/src/autocomplete/text_completer.js +++ b/src/autocomplete/text_completer.js @@ -37,7 +37,7 @@ function wordDistance(doc, pos) { return wordScores; } -function filterStringsFromCompletions(session, pos) { +function getWordScoresForFilteredStrings(session, pos) { var filterRegExp = /string|comment|^comment\.doc.*/; var lines = session.bgTokenizer.lines; var exclude = lines[pos.row] && lines[pos.row].find(el => el.start === pos.column - el.value.length); @@ -59,7 +59,7 @@ function filterStringsFromCompletions(session, pos) { } exports.getCompletions = function (editor, session, pos, prefix, callback) { - var wordScore = editor.$filterStringsCompletions ? filterStringsFromCompletions(session, pos) : wordDistance( + var wordScore = editor.$filterStringsCompletions ? getWordScoresForFilteredStrings(session, pos) : wordDistance( session, pos); var wordList = Object.keys(wordScore);