Skip to content

Commit

Permalink
feat: add setting to enable autocomplete, fix constants for completion (
Browse files Browse the repository at this point in the history
#765)

* feat: add setting to enable autocomplete, fix constants for completion

* fix: code-review
  • Loading branch information
Raubzeug authored Mar 15, 2024
1 parent c1d3f99 commit 88cfc52
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 98 deletions.
3 changes: 0 additions & 3 deletions src/assets/icons/flask.svg

This file was deleted.

1 change: 0 additions & 1 deletion src/assets/icons/star.svg

This file was deleted.

2 changes: 1 addition & 1 deletion src/containers/AppWithClusters/AppWithClusters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface AppWithClustersProps {

const defaultUserSettings = settings;

defaultUserSettings[1].sections[0].settings.push({
defaultUserSettings[2].sections[0].settings.push({
title: i18n('settings.useClusterBalancerAsBackend.title'),
helpPopoverContent: i18n('settings.useClusterBalancerAsBackend.popover'),
settingKey: USE_CLUSTER_BALANCER_AS_BACKEND_KEY,
Expand Down
12 changes: 3 additions & 9 deletions src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import {useSetting, useQueryModes} from '../../../../utils/hooks';
import {QUERY_ACTIONS} from '../../../../utils/query';
import {parseJson} from '../../../../utils/utils';
import {useEditorOptions} from './helpers';

import {
InitialPaneState,
Expand All @@ -48,14 +49,6 @@ import i18n from '../i18n';

import './QueryEditor.scss';

const EDITOR_OPTIONS = {
automaticLayout: true,
selectOnLineNumbers: true,
minimap: {
enabled: false,
},
};

const CONTEXT_MENU_GROUP_ID = 'navigation';
const RESULT_TYPES = {
EXECUTE: 'execute',
Expand Down Expand Up @@ -93,6 +86,7 @@ interface QueryEditorProps {
}

function QueryEditor(props: QueryEditorProps) {
const editorOptions = useEditorOptions();
const {
path,
setTenantPath: setPath,
Expand Down Expand Up @@ -422,7 +416,7 @@ function QueryEditor(props: QueryEditorProps) {
<MonacoEditor
language="sql"
value={executeQuery.input}
options={EDITOR_OPTIONS}
options={editorOptions}
onChange={onChange}
editorDidMount={editorDidMount}
theme={`vs-${theme}`}
Expand Down
28 changes: 28 additions & 0 deletions src/containers/Tenant/Query/QueryEditor/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type Monaco from 'monaco-editor';
import {ENABLE_AUTOCOMPLETE, useSetting} from '../../../../lib';
import {useMemo} from 'react';

export type EditorOptions = Monaco.editor.IEditorOptions & Monaco.editor.IGlobalEditorOptions;

export const EDITOR_OPTIONS: EditorOptions = {
automaticLayout: true,
selectOnLineNumbers: true,
minimap: {
enabled: false,
},
};

export function useEditorOptions() {
const [enableAutocomplete] = useSetting(ENABLE_AUTOCOMPLETE);

const options = useMemo<EditorOptions>(() => {
const useAutocomplete = Boolean(enableAutocomplete);
return {
quickSuggestions: useAutocomplete,
suggestOnTriggerCharacters: useAutocomplete,
...EDITOR_OPTIONS,
};
}, [enableAutocomplete]);

return options;
}
6 changes: 6 additions & 0 deletions src/containers/UserSettings/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
"page.experiments": "Experiments",
"section.experiments": "Experiments",

"page.editor": "Editor",
"section.dev-setting": "Development settings",

"settings.editor.autocomplete.title": "Enable autocomplete",
"settings.editor.autocomplete.description": "You’re always able to get suggestions by pressing Ctrl+Space.",

"settings.theme.title": "Interface theme",
"settings.theme.option-dark": "Dark",
"settings.theme.option-light": "Light",
Expand Down
27 changes: 22 additions & 5 deletions src/containers/UserSettings/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type {IconProps} from '@gravity-ui/uikit';

import favoriteFilledIcon from '../../assets/icons/star.svg';
import flaskIcon from '../../assets/icons/flask.svg';
import {PencilToSquare, Flask, StarFill} from '@gravity-ui/icons';

import {
INVERTED_DISKS_KEY,
Expand All @@ -11,6 +10,7 @@ import {
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
QUERY_USE_MULTI_SCHEMA_KEY,
BINARY_DATA_IN_PLAIN_TEXT_DISPLAY,
ENABLE_AUTOCOMPLETE,
} from '../../utils/constants';
import {Lang, defaultLang} from '../../utils/i18n';

Expand Down Expand Up @@ -107,6 +107,12 @@ export const queryUseMultiSchemaSetting: SettingProps = {
helpPopoverContent: i18n('settings.queryUseMultiSchema.popover'),
};

export const enableAutocompleteSetting: SettingProps = {
settingKey: ENABLE_AUTOCOMPLETE,
title: i18n('settings.editor.autocomplete.title'),
description: i18n('settings.editor.autocomplete.description'),
};

export const appearanceSection: SettingsSection = {
id: 'appearanceSection',
title: i18n('section.appearance'),
Expand All @@ -117,18 +123,29 @@ export const experimentsSection: SettingsSection = {
title: i18n('section.experiments'),
settings: [useNodesEndpointSetting, useVirtualTables, queryUseMultiSchemaSetting],
};
export const devSettingsSection: SettingsSection = {
id: 'devSettingsSection',
title: i18n('section.dev-setting'),
settings: [enableAutocompleteSetting],
};

export const generalPage: SettingsPage = {
id: 'generalPage',
title: i18n('page.general'),
icon: {data: favoriteFilledIcon, height: 14, width: 14},
icon: {data: StarFill, height: 14, width: 14},
sections: [appearanceSection],
};
export const experimentsPage: SettingsPage = {
id: 'experimentsPage',
title: i18n('page.experiments'),
icon: {data: flaskIcon},
icon: {data: Flask},
sections: [experimentsSection],
};
export const editorPage: SettingsPage = {
id: 'editorPage',
title: i18n('page.editor'),
icon: {data: PencilToSquare},
sections: [devSettingsSection],
};

export const settings: YDBEmbeddedUISettings = [generalPage, experimentsPage];
export const settings: YDBEmbeddedUISettings = [generalPage, editorPage, experimentsPage];
2 changes: 2 additions & 0 deletions src/services/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
USE_CLUSTER_BALANCER_AS_BACKEND_KEY,
BINARY_DATA_IN_PLAIN_TEXT_DISPLAY,
ENABLE_AUTOCOMPLETE,
} from '../utils/constants';
import {QUERY_ACTIONS, QUERY_MODES} from '../utils/query';
import {parseJson} from '../utils/utils';
Expand All @@ -37,6 +38,7 @@ export const DEFAULT_USER_SETTINGS: SettingsObject = {
[PARTITIONS_HIDDEN_COLUMNS_KEY]: [],
[USE_BACKEND_PARAMS_FOR_TABLES_KEY]: false,
[USE_CLUSTER_BALANCER_AS_BACKEND_KEY]: true,
[ENABLE_AUTOCOMPLETE]: false,
};

class SettingsManager {
Expand Down
2 changes: 2 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,5 @@ export const USE_BACKEND_PARAMS_FOR_TABLES_KEY = 'useBackendParamsForTables';
export const QUERY_USE_MULTI_SCHEMA_KEY = 'queryUseMultiSchema';

export const USE_CLUSTER_BALANCER_AS_BACKEND_KEY = 'useClusterBalancerAsBacked';

export const ENABLE_AUTOCOMPLETE = 'enableAutocomplete';
60 changes: 2 additions & 58 deletions src/utils/yqlSuggestions/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,8 @@ export const SimpleFunctions = [
'Unwrap',
'Nothing',
'Callable',
'Pickle',
'StablePickle',
'Unpickle',
'StaticMap',
'StaticZip',
'AggregationFactory',
'AggregateTransformInput',
'AggregateTransformOutput',
'AggregateFlatten',
'ListCreate',
'AsListStrict',
'ListLength',
Expand Down Expand Up @@ -380,10 +373,6 @@ const RawUdfs = {
'UnescapeC',
],

Compress: ['BZip2', 'Brotli', 'Gzip', 'Lzma', 'Snappy', 'Zlib', 'Zstd'],

TryDecompress: ['BZip2', 'Brotli', 'Gzip', 'Lzma', 'Snappy', 'Xz', 'Zlib', 'Zstd'],

Unicode: [
'Find',
'Fold',
Expand Down Expand Up @@ -658,8 +647,6 @@ const RawUdfs = {
'Replace',
],

Protobuf: ['Parse', 'Serialize', 'TryParse'],

Digest: [
'Argon2',
'Blake2B',
Expand Down Expand Up @@ -692,8 +679,6 @@ const RawUdfs = {
'XXH3_128',
],

Decompress: ['BZip2', 'Brotli', 'Gzip', 'Lzma', 'Snappy', 'Xz', 'Zlib', 'Zstd'],

Histogram: [
'CalcLowerBound',
'CalcLowerBoundSafe',
Expand Down Expand Up @@ -724,47 +709,6 @@ export const WindowFunctions = [
'SessionState',
];

export const TableFunction = [
'CONCAT',
'EACH',
'RANGE',
'LIKE',
'REGEXP',
'CONCAT_STRICT',
'RANGE_STRICT',
'FILTER',
'FOLDER',
'WalkFolders',
];
export const TableFunction = [];

export const Pragmas = [
'TablePathPrefix',
'AnsiInForEmptyOrNullableItemsCollections',
'File',
'Folder',
'Library',
'Warning',
'package',
'override_library',
'AutoCommit',
'DqEngine',
'SimpleColumns',
'DisableSimpleColumns',
'CoalesceJoinKeysOnQualifiedAll',
'StrictJoinKeyTypes',
'AnsiRankForNullableKeys',
'AnsiCurrentRow',
'AnsiOrderByLimitInUnionAll',
'OrderedColumns',
'DisableOrderedColumns',
'PositionalUnionAll',
'RegexUseRe2',
'ClassicDivision',
'AllowDotInAlias',
'WarnUnnamedColumns',
'GroupByLimit',
'GroupByCubeLimit',
'config.flags',
'kikimr.IsolationLevel',
'Kikimr.ScanQuery',
];
export const Pragmas = ['TablePathPrefix', 'Warning'];
42 changes: 21 additions & 21 deletions src/utils/yqlSuggestions/yqlSuggestions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import type Monaco from 'monaco-editor';
import {CursorPosition, parseYqlQuery} from '@gravity-ui/websql-autocomplete';

import {
Expand All @@ -17,10 +17,10 @@ import {

export function createProvideSuggestionsFunction(database: string) {
return async (
model: monaco.editor.ITextModel,
monacoCursorPosition: monaco.Position,
_context: monaco.languages.CompletionContext,
_token: monaco.CancellationToken,
model: Monaco.editor.ITextModel,
monacoCursorPosition: Monaco.Position,
_context: Monaco.languages.CompletionContext,
_token: Monaco.CancellationToken,
) => {
const cursorPosition: CursorPosition = {
line: monacoCursorPosition.lineNumber,
Expand All @@ -40,20 +40,20 @@ export function createProvideSuggestionsFunction(database: string) {
}

async function getSuggestions(
model: monaco.editor.ITextModel,
model: Monaco.editor.ITextModel,
cursorPosition: CursorPosition,
rangeToInsertSuggestion: monaco.IRange,
rangeToInsertSuggestion: Monaco.IRange,
database: string,
): Promise<monaco.languages.CompletionItem[]> {
): Promise<Monaco.languages.CompletionItem[]> {
const parseResult = parseYqlQuery(model.getValue(), cursorPosition);
let entitiesSuggestions: monaco.languages.CompletionItem[] = [];
let functionsSuggestions: monaco.languages.CompletionItem[] = [];
let aggregateFunctionsSuggestions: monaco.languages.CompletionItem[] = [];
let windowFunctionsSuggestions: monaco.languages.CompletionItem[] = [];
let tableFunctionsSuggestions: monaco.languages.CompletionItem[] = [];
let udfsSuggestions: monaco.languages.CompletionItem[] = [];
let simpleTypesSuggestions: monaco.languages.CompletionItem[] = [];
let pragmasSuggestions: monaco.languages.CompletionItem[] = [];
let entitiesSuggestions: Monaco.languages.CompletionItem[] = [];
let functionsSuggestions: Monaco.languages.CompletionItem[] = [];
let aggregateFunctionsSuggestions: Monaco.languages.CompletionItem[] = [];
let windowFunctionsSuggestions: Monaco.languages.CompletionItem[] = [];
let tableFunctionsSuggestions: Monaco.languages.CompletionItem[] = [];
let udfsSuggestions: Monaco.languages.CompletionItem[] = [];
let simpleTypesSuggestions: Monaco.languages.CompletionItem[] = [];
let pragmasSuggestions: Monaco.languages.CompletionItem[] = [];

if (parseResult.suggestEntity) {
entitiesSuggestions = await generateEntitiesSuggestion(rangeToInsertSuggestion);
Expand Down Expand Up @@ -100,7 +100,7 @@ async function getSuggestions(
parseResult.suggestKeywords,
);

const suggestions: monaco.languages.CompletionItem[] = [
const suggestions: Monaco.languages.CompletionItem[] = [
...entitiesSuggestions,
...functionsSuggestions,
...windowFunctionsSuggestions,
Expand All @@ -118,12 +118,12 @@ async function getSuggestions(
}

function getRangeToInsertSuggestion(
model: monaco.editor.ITextModel,
cursorPosition: monaco.Position,
): monaco.IRange {
model: Monaco.editor.ITextModel,
cursorPosition: Monaco.Position,
): Monaco.IRange {
const {startColumn: lastWordStartColumn, endColumn: lastWordEndColumn} =
model.getWordUntilPosition(cursorPosition);
// https://github.com/microsoft/monaco-editor/discussions/3639#discussioncomment-5190373 if user already typed "$" sign, it should not be duplicated
// https://github.com/microsoft/Monaco-editor/discussions/3639#discussioncomment-5190373 if user already typed "$" sign, it should not be duplicated
const dollarBeforeLastWordStart =
model.getLineContent(cursorPosition.lineNumber)[lastWordStartColumn - 2] === '$' ? 1 : 0;
return {
Expand Down

0 comments on commit 88cfc52

Please sign in to comment.