{"version":3,"file":"monaco-completion-provider.cjs","sources":["../../../../../src/components/monaco-query-field/monaco-completion-provider/monaco-completion-provider.ts"],"sourcesContent":["// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/index.ts\nimport { type TimeRange } from '@grafana/data';\nimport type { Monaco, monacoTypes } from '@grafana/ui';\n\nimport { type CompletionType, getCompletions } from './completions';\nimport { type DataProvider } from './data_provider';\nimport { getSituation } from './situation';\nimport { NeverCaseError } from './util';\n\nexport type TriggerType = 'partial' | 'full';\n\nexport type MonacoQueryFieldLocalState = {\n  isManualTriggerRequested: boolean;\n};\n\nconst TRIGGER_CHARACTERS = ['{', ',', '[', '(', '=', '~', ' ', '\"'];\nconst MIN_WORD_LENGTH_FOR_FULL_COMPLETIONS = 3;\n\nexport function getSuggestOptions(): monacoTypes.editor.ISuggestOptions {\n  return {\n    // monaco-editor sometimes provides suggestions automatically, i am not\n    // sure based on what, seems to be by analyzing the words already\n    // written.\n    // to try it out:\n    // - enter `go_goroutines{job~`\n    // - have the cursor at the end of the string\n    // - press ctrl-enter\n    // - you will get two suggestions\n    // those were not provided by grafana, they are offered automatically.\n    // i want to remove those. the only way i found is:\n    // - every suggestion-item has a `kind` attribute,\n    //   that controls the icon to the left of the suggestion.\n    // - items auto-generated by monaco have `kind` set to `text`.\n    // - we make sure grafana-provided suggestions do not have `kind` set to `text`.\n    // - and then we tell monaco not to show suggestions of kind `text`\n    showWords: false,\n  };\n}\n\nfunction getMonacoCompletionItemKind(type: CompletionType, monaco: Monaco): monacoTypes.languages.CompletionItemKind {\n  switch (type) {\n    case 'DURATION':\n      return monaco.languages.CompletionItemKind.Unit;\n    case 'FUNCTION':\n      return monaco.languages.CompletionItemKind.Variable;\n    case 'HISTORY':\n      return monaco.languages.CompletionItemKind.Snippet;\n    case 'LABEL_NAME':\n      return monaco.languages.CompletionItemKind.Enum;\n    case 'LABEL_VALUE':\n      return monaco.languages.CompletionItemKind.EnumMember;\n    case 'METRIC_NAME':\n      return monaco.languages.CompletionItemKind.Constructor;\n    default:\n      throw new NeverCaseError(type);\n  }\n}\n\nfunction getTriggerType(\n  word: monacoTypes.editor.IWordAtPosition | null,\n  model: monacoTypes.editor.ITextModel,\n  position: monacoTypes.Position,\n  state: MonacoQueryFieldLocalState\n): TriggerType {\n  // Manual trigger (Ctrl+Space) - always full completions\n  if (state.isManualTriggerRequested) {\n    return 'full';\n  }\n\n  const charBeforeCursor = model.getValueInRange({\n    startLineNumber: position.lineNumber,\n    endLineNumber: position.lineNumber,\n    startColumn: Math.max(1, position.column - 1),\n    endColumn: position.column,\n  });\n\n  if (TRIGGER_CHARACTERS.includes(charBeforeCursor)) {\n    return 'full';\n  }\n\n  // For typed words of sufficient length, use full completions\n  if (word && word.word.length >= MIN_WORD_LENGTH_FOR_FULL_COMPLETIONS) {\n    return 'full';\n  }\n\n  return 'partial';\n}\n\nexport function getCompletionProvider(\n  monaco: Monaco,\n  dataProvider: DataProvider,\n  timeRange: TimeRange\n): { provider: monacoTypes.languages.CompletionItemProvider; state: MonacoQueryFieldLocalState } {\n  const state: MonacoQueryFieldLocalState = {\n    isManualTriggerRequested: false,\n  };\n\n  const provideCompletionItems = (\n    model: monacoTypes.editor.ITextModel,\n    position: monacoTypes.Position\n  ): monacoTypes.languages.ProviderResult<monacoTypes.languages.CompletionList> => {\n    const word = model.getWordAtPosition(position);\n    const range =\n      word != null\n        ? monaco.Range.lift({\n            startLineNumber: position.lineNumber,\n            endLineNumber: position.lineNumber,\n            startColumn: word.startColumn,\n            endColumn: word.endColumn,\n          })\n        : monaco.Range.fromPositions(position);\n\n    // Set input range for data provider\n    dataProvider.monacoSettings.setInputInRange(model.getValueInRange(range));\n\n    // Get adjusted position for cursor/selection handling\n    const adjustedPosition = getAdjustedPosition(position);\n    const offset = model.getOffsetAt(adjustedPosition);\n    const situation = getSituation(model.getValue(), offset);\n\n    // Early exit if no situation detected\n    if (situation === null) {\n      return Promise.resolve({ suggestions: [], incomplete: false });\n    }\n\n    const triggerType: TriggerType = getTriggerType(word, model, position, state);\n\n    return getCompletions(situation, dataProvider, timeRange, word?.word, triggerType).then((items) => {\n      // Monaco by-default alphabetically orders the items.\n      // We use a number-as-string sortkey to maintain our custom order\n      const maxIndexDigits = items.length > 0 ? items.length.toString().length : 1;\n      const suggestions: monacoTypes.languages.CompletionItem[] = items.map((item, index) => ({\n        kind: getMonacoCompletionItemKind(item.type, monaco),\n        label: item.label,\n        insertText: item.insertText,\n        insertTextRules: item.insertTextRules,\n        detail: item.detail,\n        documentation: item.documentation,\n        sortText: index.toString().padStart(maxIndexDigits, '0'), // to force the order we have\n        range,\n        command: item.triggerOnInsert\n          ? {\n              id: 'editor.action.triggerSuggest',\n              title: '',\n            }\n          : undefined,\n      }));\n\n      return { suggestions };\n    });\n  };\n\n  // Helper function to handle position adjustment for selection\n  function getAdjustedPosition(position: monacoTypes.Position): { column: number; lineNumber: number } {\n    let adjustedColumn = position.column;\n\n    // Check to see if the browser supports window.getSelection()\n    if (window.getSelection) {\n      const selectedText = window.getSelection()?.toString();\n      // If the user has selected text, adjust the cursor position to be at the start of the selection\n      if (selectedText && selectedText.length > 0) {\n        adjustedColumn = Math.max(1, adjustedColumn - selectedText.length);\n      }\n    }\n\n    return {\n      column: adjustedColumn,\n      lineNumber: position.lineNumber,\n    };\n  }\n\n  return {\n    provider: {\n      triggerCharacters: TRIGGER_CHARACTERS,\n      provideCompletionItems,\n    },\n    state,\n  };\n}\n"],"names":["NeverCaseError","situation","getSituation","getCompletions"],"mappings":"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"}