mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) In formula autocompletions, fix suggestions after an opening parenthesis.
Summary: Previously, a change was made to include the opening parenthesis into the "identifier regex", so that backend received the function call name for cases like 'T.lookupOne(B' (to autocomplete columns of table T that start with "B"). Unfortunately, that interferes with common cases like 'SUM($B', since instead of sending '$B', it is now including the function name. To properly fix the common case, we need to exclude the function name from the call, but for lookups we need to include it. ACE's methods aren't flexible enough to override this logic cleanly, so some monkey-patching was needed. Test Plan: Added a test case Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3874
This commit is contained in:
parent
8bedaedab6
commit
3513c1e8d2
@ -17,6 +17,7 @@ export function setupAceEditorCompletions(editor: ace.Editor, options: ICompleti
|
|||||||
// use a suggestion, a change of behavior that doesn't seem particularly desirable and
|
// use a suggestion, a change of behavior that doesn't seem particularly desirable and
|
||||||
// which also breaks several existing tests.
|
// which also breaks several existing tests.
|
||||||
const {Autocomplete} = ace.acequire('ace/autocomplete'); // lives in brace/ext/language_tools
|
const {Autocomplete} = ace.acequire('ace/autocomplete'); // lives in brace/ext/language_tools
|
||||||
|
|
||||||
const completer = new Autocomplete();
|
const completer = new Autocomplete();
|
||||||
completer.autoSelect = false;
|
completer.autoSelect = false;
|
||||||
(editor as any).completer = completer;
|
(editor as any).completer = completer;
|
||||||
@ -83,18 +84,30 @@ function initCustomCompleter() {
|
|||||||
if (_initialized) { return; }
|
if (_initialized) { return; }
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
|
||||||
|
// The default regex just matches identifiers. We expand it to include periods (to capture
|
||||||
|
// attributes) and "$", for Grist column names. In addition, we autocomplete lookup formulas
|
||||||
|
// with the function name, to give suggestions for lookup keyword arguments.
|
||||||
|
const prefixMatchRegex = /\w+\.(?:lookupRecords|lookupOne)\([\w.$\u00A2-\uFFFF]*$|[\w.$\u00A2-\uFFFF]+$/;
|
||||||
|
|
||||||
|
// Monkey-patch getCompletionPrefix. This is based on the source code in
|
||||||
|
// node_modules/brace/ext/language_tools.js, simplified to do the one thing we want here (since
|
||||||
|
// the original method's generality doesn't help us here).
|
||||||
|
const util = ace.acequire('ace/autocomplete/util'); // lives in brace/ext/language_tools
|
||||||
|
util.getCompletionPrefix = function getCompletionPrefix(this: any, editor: ace.Editor) {
|
||||||
|
const pos = editor.getCursorPosition();
|
||||||
|
const line = editor.session.getLine(pos.row);
|
||||||
|
const match = line.slice(0, pos.column).match(prefixMatchRegex);
|
||||||
|
return match ? match[0] : "";
|
||||||
|
};
|
||||||
|
|
||||||
// Add some autocompletion with partial access to document
|
// Add some autocompletion with partial access to document
|
||||||
const aceLanguageTools = ace.acequire('ace/ext/language_tools');
|
const aceLanguageTools = ace.acequire('ace/ext/language_tools');
|
||||||
aceLanguageTools.setCompleters([]);
|
aceLanguageTools.setCompleters([]);
|
||||||
aceLanguageTools.addCompleter({
|
aceLanguageTools.addCompleter({
|
||||||
// Default regexp stops at periods, which doesn't let autocomplete
|
|
||||||
// work on members. So we expand it to include periods.
|
|
||||||
// We also include $, which grist uses for column names,
|
|
||||||
// and '(' for the start of a function call, which may provide completions for arguments.
|
|
||||||
identifierRegexps: [/[a-zA-Z_0-9.$\u00A2-\uFFFF(]/],
|
|
||||||
|
|
||||||
// For autocompletion we ship text to the sandbox and run standard completion there.
|
// For autocompletion we ship text to the sandbox and run standard completion there.
|
||||||
async getCompletions(editor: ace.Editor, session: ace.IEditSession, pos: number, prefix: string, callback: any) {
|
async getCompletions(
|
||||||
|
editor: ace.Editor, session: ace.IEditSession, pos: ace.Position, prefix: string, callback: any
|
||||||
|
) {
|
||||||
const options = completionOptions.get(editor);
|
const options = completionOptions.get(editor);
|
||||||
if (!options || prefix.length === 0) { callback(null, []); return; }
|
if (!options || prefix.length === 0) { callback(null, []); return; }
|
||||||
const suggestions = await options.getSuggestions(prefix);
|
const suggestions = await options.getSuggestions(prefix);
|
||||||
|
Loading…
Reference in New Issue
Block a user