diff --git a/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.tsx b/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.tsx index 4b40e0c0d00d..73169d9c6e93 100644 --- a/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.tsx +++ b/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.tsx @@ -131,13 +131,58 @@ function CodeMirrorWhereClause(): JSX.Element { function myCompletions(context: CompletionContext): CompletionResult | null { const word = context.matchBefore(/\w*/); if (word?.from === word?.to && !context.explicit) return null; + + // Get the query context at the cursor position + const queryContext = getQueryContextAtCursor(query, cursorPos.ch); + + // Define autocomplete options based on the context + let options: { + label: string; + type: string; + info?: string; + apply?: string; + detail?: string; + }[] = []; + + if (queryContext.isInKey) { + options = [ + { label: 'status', type: 'keyword' }, + { label: 'service', type: 'keyword' }, + // Add more key options here + ]; + } else if (queryContext.isInOperator) { + options = [ + { label: '=', type: 'operator' }, + { label: '!=', type: 'operator' }, + // Add more operator options here + ]; + } else if (queryContext.isInValue) { + options = [ + { label: 'error', type: 'value' }, + { label: 'frontend', type: 'value' }, + // Add more value options here + ]; + } else if (queryContext.isInFunction) { + options = [ + { label: 'HAS', type: 'function' }, + { label: 'HASANY', type: 'function' }, + // Add more function options here + ]; + } else if (queryContext.isInConjunction) { + options = [ + { label: 'AND', type: 'conjunction' }, + { label: 'OR', type: 'conjunction' }, + ]; + } else if (queryContext.isInParenthesis) { + options = [ + { label: '(', type: 'parenthesis' }, + { label: ')', type: 'parenthesis' }, + ]; + } + return { from: word?.from ?? 0, - options: [ - { label: 'match', type: 'keyword' }, - { label: 'hello', type: 'variable', info: '(World)' }, - { label: 'magic', type: 'text', apply: '⠁⭒*.✩.*⭒⠁', detail: 'macro' }, - ], + options, }; } diff --git a/frontend/src/utils/antlrQueryUtils.ts b/frontend/src/utils/antlrQueryUtils.ts index a23282b7f45c..ae6000ff2aa9 100644 --- a/frontend/src/utils/antlrQueryUtils.ts +++ b/frontend/src/utils/antlrQueryUtils.ts @@ -262,6 +262,22 @@ export function getQueryContextAtCursor( // If still no token (empty query or all whitespace), return default context if (!currentToken) { + // Handle transitions based on spaces and current state + if (query.trim() === '') { + return { + tokenType: -1, + text: '', + start: cursorIndex, + stop: cursorIndex, + currentToken: '', + isInValue: false, + isInKey: true, // Default to key context when input is empty + isInOperator: false, + isInFunction: false, + isInConjunction: false, + isInParenthesis: false, + }; + } return { tokenType: -1, text: '', @@ -324,6 +340,68 @@ export function getQueryContextAtCursor( FilterQueryLexer.HASNONE, ].includes(currentToken.type); + // Handle transitions based on spaces and current state + if (isInKey && query[currentToken.stop + 1] === ' ') { + return { + tokenType: currentToken.type, + text: currentToken.text, + start: currentToken.start, + stop: currentToken.stop, + currentToken: currentToken.text, + isInValue: false, + isInKey: false, + isInOperator: true, + isInFunction: false, + isInConjunction: false, + isInParenthesis: false, + }; + } + if (isInOperator && query[currentToken.stop + 1] === ' ') { + return { + tokenType: currentToken.type, + text: currentToken.text, + start: currentToken.start, + stop: currentToken.stop, + currentToken: currentToken.text, + isInValue: true, + isInKey: false, + isInOperator: false, + isInFunction: false, + isInConjunction: false, + isInParenthesis: false, + }; + } + if (isInValue && query[currentToken.stop + 1] === ' ') { + return { + tokenType: currentToken.type, + text: currentToken.text, + start: currentToken.start, + stop: currentToken.stop, + currentToken: currentToken.text, + isInValue: false, + isInKey: false, + isInOperator: false, + isInFunction: false, + isInConjunction: true, + isInParenthesis: false, + }; + } + if (isInConjunction && query[currentToken.stop + 1] === ' ') { + return { + tokenType: currentToken.type, + text: currentToken.text, + start: currentToken.start, + stop: currentToken.stop, + currentToken: currentToken.text, + isInValue: false, + isInKey: true, + isInOperator: false, + isInFunction: false, + isInConjunction: false, + isInParenthesis: false, + }; + } + return { tokenType: currentToken.type, text: currentToken.text,