mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* loki: switch to a monaco-based query field, step 1 (#46291) * loki: use monaco-logql (#46318) * loki: use monaco-logql * updated monaco-logql * fix all the tests (#46327) * loki: recommend parser (#46362) * loki: recommend parser * additional improvements * more improvements * type and lint fixes * more improvements * trigger autocomplete on focus * rename * loki: more smart features (#46414) * loki: more smart features * loki: updated syntax-highlight version * better explanation (#46443) * better explanation * improved help-text Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> * Fix label * feat(loki-monaco-editor): add monaco-logql as a dependency * feat(loki-monaco-editor): add back range function removed during merge * feat(loki-monaco-editor): sync imports with recent changes * feat(loki-monaco-editor): add missing lang provider functions * feat(loki-monaco-editor): fix imports * feat(loki-monaco-editor): display monaco editor by default Temporarily * Chore: remove commented code * Chore: minor refactor to NeverCaseError * Chore: minor code cleanups * feat(loki-monaco-editor): add history implementation Will see how it behaves and base the history slicing on tangible feedback * feat(loki-monaco-editor): turn completion data provider into a class * Chore: fix missing imports * feat(loki-monaco-editor): refactor data provider methods Move complexity scattered everywhere to the provider * Chore: clean up redundant code * Chore: minor comments cleanup * Chore: simplify override services * Chore: rename callback * feat(loki-monaco-editor): use query hints implementation to parse expression * feat(loki-monaco-editor): improve function name * Chore: remove superfluous variable in favor of destructuring * Chore: remove unused imports * Chore: make method async * feat(loki-monaco-editor): fix deprecations and errors in situation * feat(loki-monaco-editor): comment failing test case * Chore: remove comment from test * Chore: remove duplicated completion item * Chore: fix linting issues * Chore: update language provider test * Chore: update datasource test * feat(loki-monaco-editor): create feature flag * feat(loki-monaco-editor): place the editor under a feature flag * Chore: add completion unit test * Chore: add completion data provider test * Chore: remove unwanted export * Chore: remove unused export * Chore(loki-query-field): destructure all props * chore(loki-completions): remove odd string * fix(loki-completions): remove rate_interval Not supported * fix(loki-completions): remove line filters for after pipe case We shouldn't offer line filters if we are after first pipe. * refactor(loki-datasource): update default parameter * fix(loki-syntax): remove outdated documentation * Update capitalization in pkg/services/featuremgmt/registry.go Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> * refactor(situation): use node types instead of names * Chore: comment line filters pending implementation It's breaking the build due to a linting error. * Chore: update feature flag test after capitalization change * Revert "fix(loki-completions): remove line filters for after pipe case" This reverts commit3d003ca4bc
. * Revert "Chore: comment line filters pending implementation" This reverts commit84bfe76a6a
. Co-authored-by: Gábor Farkas <gabor.farkas@gmail.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Ivana Huckova <ivana.huckova@gmail.com>
113 lines
4.4 KiB
TypeScript
113 lines
4.4 KiB
TypeScript
import type { Monaco, monacoTypes } from '@grafana/ui';
|
|
|
|
import { CompletionDataProvider } from './CompletionDataProvider';
|
|
import { NeverCaseError } from './NeverCaseError';
|
|
import { getCompletions, CompletionType } from './completions';
|
|
import { getSituation } from './situation';
|
|
|
|
// from: monacoTypes.languages.CompletionItemInsertTextRule.InsertAsSnippet
|
|
const INSERT_AS_SNIPPET_ENUM_VALUE = 4;
|
|
|
|
export function getSuggestOptions(): monacoTypes.editor.ISuggestOptions {
|
|
return {
|
|
// monaco-editor sometimes provides suggestions automatically, i am not
|
|
// sure based on what, seems to be by analyzing the words already
|
|
// written.
|
|
// to try it out:
|
|
// - enter `go_goroutines{job~`
|
|
// - have the cursor at the end of the string
|
|
// - press ctrl-enter
|
|
// - you will get two suggestions
|
|
// those were not provided by grafana, they are offered automatically.
|
|
// i want to remove those. the only way i found is:
|
|
// - every suggestion-item has a `kind` attribute,
|
|
// that controls the icon to the left of the suggestion.
|
|
// - items auto-generated by monaco have `kind` set to `text`.
|
|
// - we make sure grafana-provided suggestions do not have `kind` set to `text`.
|
|
// - and then we tell monaco not to show suggestions of kind `text`
|
|
showWords: false,
|
|
};
|
|
}
|
|
|
|
function getMonacoCompletionItemKind(type: CompletionType, monaco: Monaco): monacoTypes.languages.CompletionItemKind {
|
|
switch (type) {
|
|
case 'DURATION':
|
|
return monaco.languages.CompletionItemKind.Unit;
|
|
case 'FUNCTION':
|
|
return monaco.languages.CompletionItemKind.Variable;
|
|
case 'HISTORY':
|
|
return monaco.languages.CompletionItemKind.Snippet;
|
|
case 'LABEL_NAME':
|
|
return monaco.languages.CompletionItemKind.Enum;
|
|
case 'LABEL_VALUE':
|
|
return monaco.languages.CompletionItemKind.EnumMember;
|
|
case 'PATTERN':
|
|
return monaco.languages.CompletionItemKind.Constructor;
|
|
case 'PARSER':
|
|
return monaco.languages.CompletionItemKind.Class;
|
|
case 'LINE_FILTER':
|
|
return monaco.languages.CompletionItemKind.TypeParameter;
|
|
case 'LINE_FORMAT':
|
|
return monaco.languages.CompletionItemKind.Event;
|
|
default:
|
|
throw new NeverCaseError(type);
|
|
}
|
|
}
|
|
export function getCompletionProvider(
|
|
monaco: Monaco,
|
|
dataProvider: CompletionDataProvider
|
|
): monacoTypes.languages.CompletionItemProvider {
|
|
const provideCompletionItems = (
|
|
model: monacoTypes.editor.ITextModel,
|
|
position: monacoTypes.Position
|
|
): monacoTypes.languages.ProviderResult<monacoTypes.languages.CompletionList> => {
|
|
const word = model.getWordAtPosition(position);
|
|
const range =
|
|
word != null
|
|
? monaco.Range.lift({
|
|
startLineNumber: position.lineNumber,
|
|
endLineNumber: position.lineNumber,
|
|
startColumn: word.startColumn,
|
|
endColumn: word.endColumn,
|
|
})
|
|
: monaco.Range.fromPositions(position);
|
|
// documentation says `position` will be "adjusted" in `getOffsetAt`
|
|
// i don't know what that means, to be sure i clone it
|
|
const positionClone = {
|
|
column: position.column,
|
|
lineNumber: position.lineNumber,
|
|
};
|
|
const offset = model.getOffsetAt(positionClone);
|
|
const situation = getSituation(model.getValue(), offset);
|
|
const completionsPromise = situation != null ? getCompletions(situation, dataProvider) : Promise.resolve([]);
|
|
return completionsPromise.then((items) => {
|
|
// monaco by default alphabetically orders the items.
|
|
// to stop it, we use a number-as-string sortkey,
|
|
// so that monaco keeps the order we use
|
|
const maxIndexDigits = items.length.toString().length;
|
|
const suggestions: monacoTypes.languages.CompletionItem[] = items.map((item, index) => ({
|
|
kind: getMonacoCompletionItemKind(item.type, monaco),
|
|
label: item.label,
|
|
insertText: item.insertText,
|
|
insertTextRules: item.isSnippet ? INSERT_AS_SNIPPET_ENUM_VALUE : undefined,
|
|
detail: item.detail,
|
|
documentation: item.documentation,
|
|
sortText: index.toString().padStart(maxIndexDigits, '0'), // to force the order we have
|
|
range,
|
|
command: item.triggerOnInsert
|
|
? {
|
|
id: 'editor.action.triggerSuggest',
|
|
title: '',
|
|
}
|
|
: undefined,
|
|
}));
|
|
return { suggestions };
|
|
});
|
|
};
|
|
|
|
return {
|
|
triggerCharacters: ['{', ',', '[', '(', '=', '~', ' ', '"', '|'],
|
|
provideCompletionItems,
|
|
};
|
|
}
|