diff --git a/src/platform/packages/private/kbn-esql-editor/src/custom_editor_commands.test.ts b/src/platform/packages/private/kbn-esql-editor/src/custom_editor_commands.test.ts index e0418e1e1d0f7..c6d93b69a2eee 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/custom_editor_commands.test.ts +++ b/src/platform/packages/private/kbn-esql-editor/src/custom_editor_commands.test.ts @@ -151,10 +151,11 @@ describe('Custom Editor Commands', () => { it('should call toggleVisor function when command is executed', () => { const mockOnQuerySubmit = jest.fn(); const mockToggleVisor = jest.fn(); + const mockOnPrettifyQuery = jest.fn(); - addEditorKeyBindings(mockEditor, mockOnQuerySubmit, mockToggleVisor); + addEditorKeyBindings(mockEditor, mockOnQuerySubmit, mockToggleVisor, mockOnPrettifyQuery); - expect(mockEditor.addCommand).toHaveBeenCalledTimes(2); + expect(mockEditor.addCommand).toHaveBeenCalledTimes(3); const cmdKCall = (mockEditor.addCommand as jest.Mock).mock.calls.find( // eslint-disable-next-line no-bitwise @@ -172,8 +173,9 @@ describe('Custom Editor Commands', () => { it('should call onQuerySubmit when CMD+Enter is pressed', () => { const mockOnQuerySubmit = jest.fn(); const mockToggleVisor = jest.fn(); + const mockOnPrettifyQuery = jest.fn(); - addEditorKeyBindings(mockEditor, mockOnQuerySubmit, mockToggleVisor); + addEditorKeyBindings(mockEditor, mockOnQuerySubmit, mockToggleVisor, mockOnPrettifyQuery); const cmdEnterCall = (mockEditor.addCommand as jest.Mock).mock.calls.find( // eslint-disable-next-line no-bitwise @@ -187,5 +189,25 @@ describe('Custom Editor Commands', () => { expect(mockOnQuerySubmit).toHaveBeenCalledWith('manual'); }); + + it('should call onPrettifyQuery when CMD+I is pressed', () => { + const mockOnQuerySubmit = jest.fn(); + const mockToggleVisor = jest.fn(); + const mockOnPrettifyQuery = jest.fn(); + + addEditorKeyBindings(mockEditor, mockOnQuerySubmit, mockToggleVisor, mockOnPrettifyQuery); + + const cmdICall = (mockEditor.addCommand as jest.Mock).mock.calls.find( + // eslint-disable-next-line no-bitwise + ([keyMod]) => keyMod === (monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI) + ); + expect(cmdICall).toBeDefined(); + + const cmdIHandler = cmdICall[1]; + + cmdIHandler(); + + expect(mockOnPrettifyQuery).toHaveBeenCalledTimes(1); + }); }); }); diff --git a/src/platform/packages/private/kbn-esql-editor/src/custom_editor_commands.ts b/src/platform/packages/private/kbn-esql-editor/src/custom_editor_commands.ts index 37d0e95a4067c..1f680c791934c 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/custom_editor_commands.ts +++ b/src/platform/packages/private/kbn-esql-editor/src/custom_editor_commands.ts @@ -160,8 +160,9 @@ export const registerCustomCommands = (deps: MonacoCommandDependencies): monaco. export const addEditorKeyBindings = ( editor: monaco.editor.IStandaloneCodeEditor, - onQuerySubmit: (source: any) => void, - toggleVisor: () => void + onQuerySubmit: (source: QuerySource) => void, + toggleVisor: () => void, + onPrettifyQuery: () => void ) => { // Add editor key bindings editor.addCommand( @@ -175,6 +176,14 @@ export const addEditorKeyBindings = ( monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK, () => toggleVisor() ); + + editor.addCommand( + // eslint-disable-next-line no-bitwise + monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI, + () => { + onPrettifyQuery(); + } + ); }; export const addTabKeybindingRules = () => { diff --git a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/index.tsx b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/index.tsx index edf16977c1399..f80e9ea213ce8 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/index.tsx +++ b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/index.tsx @@ -50,7 +50,7 @@ interface EditorFooterProps { detectedTimestamp?: string; onErrorClick: (error: MonacoMessage) => void; onUpdateAndSubmitQuery: (newQuery: string, querySource: QuerySource) => void; - updateQuery: (qs: string) => void; + onPrettifyQuery: () => void; isHistoryOpen: boolean; setIsHistoryOpen: (status: boolean) => void; isLanguageComponentOpen: boolean; @@ -77,7 +77,7 @@ export const EditorFooter = memo(function EditorFooter({ detectedTimestamp, onErrorClick, onUpdateAndSubmitQuery, - updateQuery, + onPrettifyQuery, hideRunQueryText, editorIsInline, isSpaceReduced, @@ -139,7 +139,7 @@ export const EditorFooter = memo(function EditorFooter({ gap: 12px; `} > - +

diff --git a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/keyboard_shortcuts.tsx b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/keyboard_shortcuts.tsx index 9ad22d8b72fed..d61cbd2748e81 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/keyboard_shortcuts.tsx +++ b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/keyboard_shortcuts.tsx @@ -58,6 +58,16 @@ const listItems = [ defaultMessage: 'Open quick search', }), }, + { + title: ( + <> + {COMMAND_KEY} I + + ), + description: i18n.translate('esqlEditor.query.prettifyKeyboardShortcutsLabel', { + defaultMessage: 'Prettify query', + }), + }, ]; export function KeyboardShortcuts() { diff --git a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/query_wrap_component.tsx b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/query_wrap_component.tsx index fc3a9f8a499e7..82af5454c1161 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/query_wrap_component.tsx +++ b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/query_wrap_component.tsx @@ -10,15 +10,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFlexItem, EuiToolTip, EuiButtonIcon } from '@elastic/eui'; -import { prettifyQuery } from '@kbn/esql-utils'; -export function QueryWrapComponent({ - code, - updateQuery, -}: { - code: string; - updateQuery: (qs: string) => void; -}) { +export function QueryWrapComponent({ onPrettifyQuery }: { onPrettifyQuery: () => void }) { return ( { - const updatedCode = prettifyQuery(code); - if (code !== updatedCode) { - updateQuery(updatedCode); - } - }} + onClick={onPrettifyQuery} /> diff --git a/src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx b/src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx index fb1f826dcc3cc..eaacfdba9e3a8 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx +++ b/src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx @@ -33,6 +33,7 @@ import { getInferenceEndpoints, getEditorExtensions, fixESQLQueryWithVariables, + prettifyQuery, } from '@kbn/esql-utils'; import type { CodeEditorProps } from '@kbn/code-editor'; import { CodeEditor } from '@kbn/code-editor'; @@ -258,6 +259,16 @@ const ESQLEditorInternal = function ESQLEditor({ [onQuerySubmit, onQueryUpdate, telemetryService] ); + const onPrettifyQuery = useCallback(() => { + const qs = editorRef.current?.getValue(); + if (qs) { + const prettyCode = prettifyQuery(qs); + if (qs !== prettyCode) { + onQueryUpdate(prettyCode); + } + } + }, [onQueryUpdate]); + const onCommentLine = useCallback(() => { const currentSelection = editorRef?.current?.getSelection(); const startLineNumber = currentSelection?.startLineNumber; @@ -1103,7 +1114,7 @@ const ESQLEditorInternal = function ESQLEditor({ }); // Add editor key bindings - addEditorKeyBindings(editor, onQuerySubmit, toggleVisor); + addEditorKeyBindings(editor, onQuerySubmit, toggleVisor, onPrettifyQuery); // Store disposables for cleanup const currentEditor = editorRef.current; @@ -1214,7 +1225,7 @@ const ESQLEditorInternal = function ESQLEditor({ code={code} onErrorClick={onErrorClick} onUpdateAndSubmitQuery={onUpdateAndSubmitQuery} - updateQuery={onQueryUpdate} + onPrettifyQuery={onPrettifyQuery} detectedTimestamp={detectedTimestamp} hideRunQueryText={hideRunQueryText} editorIsInline={editorIsInline}