{"version":3,"sources":["browser/monaco-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,mBAAmB,EAAkB,eAAe,EAAC,MAAM,yBAAyB,CAAC;AAC7F,OAAO,EAAC,mBAAmB,EAAC,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAC,qBAAqB,EAAE,0BAA0B,EAAC,MAAM,2BAA2B,CAAC;AAC5F,OAAO,EAAC,yBAAyB,EAAC,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAC,iBAAiB,EAAC,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAC,sBAAsB,EAAC,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAC,aAAa,EAAC,MAAM,2CAA2C,CAAC;AAExE,OAAO,EAAC,YAAY,EAAC,MAAM,0CAA0C,CAAC;AAEtE,yBAAiB,cAAc,CAAC;IAEvB,MAAM,cAAc,qBAMzB,CAAC;IAEI,MAAM,gBAAgB,mCAAmC,CAAC;IAE1D,MAAM,eAAe,aAK1B,CAAC;CACJ;AAGD,qBACa,2BAA4B,YAAW,mBAAmB;IAGrE,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;IAGhE,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAGpD,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,yBAAyB,CAAC;IAGlD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAGxD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;IAG1D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,sBAAsB,CAAC;IAG5D,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC,iBAAiB,CAAC;IAGjF,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAG3C,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IAEvC,gBAAgB,IAAI,IAAI;IAKxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8CG;IACH,SAAS,CAAC,sBAAsB,IAAI,IAAI;IA8DxC,SAAS,CAAC,6BAA6B,IAAI,IAAI;IAU/C,SAAS,CAAC,uBAAuB,IAAI,0BAA0B;IAa/D,SAAS,CAAC,2BAA2B,IAAI,0BAA0B;IAMnE,SAAS,CAAC,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAQ1D,SAAS,CAAC,mBAAmB,IAAI,0BAA0B;IAM3D,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAUlD,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAWhE,SAAS,CAAC,uBAAuB,CAAC,SAAS,EAAE,OAAO,GAAG,0BAA0B;IAMjF,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI;IAmB1E,SAAS,CAAC,4BAA4B,IAAI,0BAA0B;IAMpE,SAAS,CAAC,oCAAoC,IAAI,0BAA0B;IAM5E,SAAS,CAAC,eAAe,IAAI;QAAE,MAAM,CAAC,EAAE,YAAY,CAAC;QAAC,MAAM,CAAC,EAAE,YAAY,CAAA;KAAE;cAK7D,YAAY,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;cAMlD,0BAA0B,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,YAAY,CAAC;QAAC,MAAM,CAAC,EAAE,YAAY,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAUrH","file":"../../src/browser/monaco-command.d.ts","sourcesContent":["import {inject, injectable, optional} from 'inversify';\r\nimport {CommandContribution, CommandHandler, CommandRegistry} from '@tartjs/core/lib/common';\r\nimport {MonacoEditorService} from './monaco-editor-service';\r\nimport {CommonCommands} from '@tartjs/core';\r\nimport {MonacoCommandRegistry, MonacoEditorCommandHandler} from './monaco-command-registry';\r\nimport {ProtocolToMonacoConverter} from './protocol-to-monaco-converter';\r\nimport {QuickInputService} from '@tartjs/core/lib/common/quick-pick-service';\r\nimport {MonacoTextModelService} from './monaco-text-model-service';\r\nimport {ApplicationShell} from '@tartjs/core/lib/browser';\r\nimport {MonacoEditor} from './monaco-editor';\r\nimport {Location, Position} from 'vscode-languageserver-types';\r\nimport {nls} from '@tartjs/core/lib/common/nls';\r\nimport {EditorManager} from '@tartjs/editor/lib/browser/editor-manager';\r\nimport {EditorCommands} from '@tartjs/editor/lib/browser/editor-command';\r\nimport {EditorWidget} from '@tartjs/editor/lib/browser/editor-widget';\r\n\r\nexport namespace MonacoCommands {\r\n\r\n  export const COMMON_ACTIONS = new Map<string, string>([\r\n    ['undo', CommonCommands.UNDO.id],\r\n    ['redo', CommonCommands.REDO.id],\r\n    ['editor.action.selectAll', CommonCommands.SELECT_ALL.id],\r\n    ['actions.find', CommonCommands.FIND.id],\r\n    ['editor.action.startFindReplaceAction', CommonCommands.REPLACE.id]\r\n  ]);\r\n\r\n  export const GO_TO_DEFINITION = 'editor.action.revealDefinition';\r\n\r\n  export const EXCLUDE_ACTIONS = new Set([\r\n    'editor.action.quickCommand',\r\n    'editor.action.clipboardCutAction',\r\n    'editor.action.clipboardCopyAction',\r\n    'editor.action.clipboardPasteAction'\r\n  ]);\r\n}\r\n\r\n\r\n@injectable()\r\nexport class MonacoEditorCommandHandlers implements CommandContribution {\r\n\r\n  @inject(MonacoCommandRegistry)\r\n  protected readonly monacoCommandRegistry: MonacoCommandRegistry;\r\n\r\n  @inject(CommandRegistry)\r\n  protected readonly commandRegistry: CommandRegistry;\r\n\r\n  @inject(ProtocolToMonacoConverter)\r\n  protected readonly p2m: ProtocolToMonacoConverter;\r\n\r\n  @inject(QuickInputService) @optional()\r\n  protected readonly quickInputService: QuickInputService;\r\n\r\n  @inject(MonacoEditorService)\r\n  protected readonly codeEditorService: MonacoEditorService;\r\n\r\n  @inject(MonacoTextModelService)\r\n  protected readonly textModelService: MonacoTextModelService;\r\n\r\n  @inject(monaco.contextKeyService.ContextKeyService)\r\n  protected readonly contextKeyService: monaco.contextKeyService.ContextKeyService;\r\n\r\n  @inject(ApplicationShell)\r\n  protected readonly shell: ApplicationShell;\r\n\r\n  @inject(EditorManager)\r\n  protected editorManager: EditorManager;\r\n\r\n  registerCommands(): void {\r\n    this.registerMonacoCommands();\r\n    this.registerEditorCommandHandlers();\r\n  }\r\n\r\n  /**\r\n   * Register commands from Monaco to Wm registry.\r\n   *\r\n   * Monaco has different kind of commands which should be handled differently by Wm.\r\n   *\r\n   * ### Editor Actions\r\n   *\r\n   * They should be registered with a label to be visible in the quick command palette.\r\n   *\r\n   * Such actions should be enabled only if the current editor is available and\r\n   * it supports such action in the current context.\r\n   *\r\n   * ### Editor Commands\r\n   *\r\n   * Such actions should be enabled only if the current editor is available.\r\n   *\r\n   * `actions.find` and `editor.action.startFindReplaceAction` are registered as handlers for `find` and `replace`.\r\n   * If handlers are not enabled then the core should prevent the default browser behavior.\r\n   * Other Wm extensions can register alternative implementations using custom enablement.\r\n   *\r\n   * ### Global Commands\r\n   *\r\n   * These commands are not necessary dependent on the current editor and enabled always.\r\n   * But they depend on services which are global in VS Code, but bound to the editor in Monaco,\r\n   * i.e. `ICodeEditorService` or `IContextKeyService`. We should take care of providing Wm implementations for such services.\r\n   *\r\n   * #### Global Native or Editor Commands\r\n   *\r\n   * Namely: `undo`, `redo` and `editor.action.selectAll`. They depend on `ICodeEditorService`.\r\n   * They will try to delegate to the current editor and if it is not available delegate to the browser.\r\n   * They are registered as handlers for corresponding core commands always.\r\n   * Other Wm extensions can provide alternative implementations by introducing a dependency to `@wm/monaco` extension.\r\n   *\r\n   * #### Global Language Commands\r\n   *\r\n   * Like `_executeCodeActionProvider`, they depend on `ICodeEditorService` and `ITextModelService`.\r\n   *\r\n   * #### Global Context Commands\r\n   *\r\n   * It is `setContext`. It depends on `IContextKeyService`.\r\n   *\r\n   * #### Global Editor Commands\r\n   *\r\n   * Like `openReferenceToSide` and `openReference`, they depend on `IListService`.\r\n   * We treat all commands which don't match any other category of global commands as global editor commands\r\n   * and execute them using the instantiation service of the current editor.\r\n   */\r\n  protected registerMonacoCommands(): void {\r\n    const editorRegistry = monaco.editorExtensions.EditorExtensionsRegistry;\r\n    const editorActions = new Map(editorRegistry.getEditorActions().map(({id, label}) => [id, label]));\r\n\r\n    const {codeEditorService, textModelService, contextKeyService} = this;\r\n    const [, globalInstantiationService] = monaco.services.StaticServices.init({\r\n      codeEditorService,\r\n      textModelService,\r\n      contextKeyService\r\n    });\r\n    const monacoCommands = monaco.commands.CommandsRegistry.getCommands();\r\n    for (const id of monacoCommands.keys()) {\r\n      if (MonacoCommands.EXCLUDE_ACTIONS.has(id)) {\r\n        continue;\r\n      }\r\n      const handler: CommandHandler = {\r\n        execute: (...args) => {\r\n          /*\r\n           * We check monaco focused code editor first since they can contain inline like the debug console and embedded editors like in the peek reference.\r\n           * If there is not such then we check last focused editor tracked by us.\r\n           */\r\n          const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();\r\n          if (editorActions.has(id)) {\r\n            const action = editor && editor.getAction(id);\r\n            if (!action) {\r\n              return;\r\n            }\r\n            return action.run();\r\n          }\r\n          const editorCommand = !!editorRegistry.getEditorCommand(id) ||\r\n              !(id.startsWith('_execute') || id === 'setContext' || MonacoCommands.COMMON_ACTIONS.has(id));\r\n          const instantiationService = editorCommand ? editor && editor['_instantiationService'] : globalInstantiationService;\r\n          if (!instantiationService) {\r\n            return;\r\n          }\r\n          return instantiationService.invokeFunction(\r\n              monacoCommands.get(id)!.handler,\r\n              ...args\r\n          );\r\n        },\r\n        isEnabled: () => {\r\n          const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();\r\n\r\n          if (editorActions.has(id)) {\r\n            const action = editor && editor.getAction(id);\r\n            return !!action && action.isSupported();\r\n          }\r\n          if (!!editorRegistry.getEditorCommand(id)) {\r\n            return !!editor;\r\n          }\r\n          return true;\r\n        }\r\n      };\r\n      const label = editorActions.get(id);\r\n      this.commandRegistry.registerCommand({id, label}, handler);\r\n      const coreCommand = MonacoCommands.COMMON_ACTIONS.get(id);\r\n      if (coreCommand) {\r\n        this.commandRegistry.registerHandler(coreCommand, handler);\r\n      }\r\n    }\r\n  }\r\n\r\n  protected registerEditorCommandHandlers(): void {\r\n    this.monacoCommandRegistry.registerHandler(EditorCommands.SHOW_REFERENCES.id, this.newShowReferenceHandler());\r\n    this.monacoCommandRegistry.registerHandler(EditorCommands.CONFIG_INDENTATION.id, this.newConfigIndentationHandler());\r\n    this.monacoCommandRegistry.registerHandler(EditorCommands.CONFIG_EOL.id, this.newConfigEolHandler());\r\n    this.monacoCommandRegistry.registerHandler(EditorCommands.INDENT_USING_SPACES.id, this.newConfigTabSizeHandler(true));\r\n    this.monacoCommandRegistry.registerHandler(EditorCommands.INDENT_USING_TABS.id, this.newConfigTabSizeHandler(false));\r\n    this.monacoCommandRegistry.registerHandler(EditorCommands.REVERT_EDITOR.id, this.newRevertActiveEditorHandler());\r\n    this.monacoCommandRegistry.registerHandler(EditorCommands.REVERT_AND_CLOSE.id, this.newRevertAndCloseActiveEditorHandler());\r\n  }\r\n\r\n  protected newShowReferenceHandler(): MonacoEditorCommandHandler {\r\n    return {\r\n      execute: (editor: MonacoEditor, uri: string, position: Position, locations: Location[]) => {\r\n        editor.commandService.executeCommand(\r\n            'editor.action.showReferences',\r\n            monaco.Uri.parse(uri),\r\n            this.p2m.asPosition(position),\r\n            locations.map(l => this.p2m.asLocation(l as Location))\r\n        );\r\n      }\r\n    };\r\n  }\r\n\r\n  protected newConfigIndentationHandler(): MonacoEditorCommandHandler {\r\n    return {\r\n      execute: editor => this.configureIndentation(editor)\r\n    };\r\n  }\r\n\r\n  protected configureIndentation(editor: MonacoEditor): void {\r\n    const items = [true, false].map(useSpaces => ({\r\n      label: nls.localize(`vscode/indentation/indentUsing${useSpaces ? 'Spaces' : 'Tabs'}`, `Indent Using ${useSpaces ? 'Spaces' : 'Tabs'}`),\r\n      execute: () => this.configureTabSize(editor, useSpaces)\r\n    }));\r\n    this.quickInputService?.showQuickPick(items, {placeholder: nls.localizeByDefault('Select Action')});\r\n  }\r\n\r\n  protected newConfigEolHandler(): MonacoEditorCommandHandler {\r\n    return {\r\n      execute: editor => this.configureEol(editor)\r\n    };\r\n  }\r\n\r\n  protected configureEol(editor: MonacoEditor): void {\r\n    const items = ['LF', 'CRLF'].map(lineEnding =>\r\n        ({\r\n          label: lineEnding,\r\n          execute: () => this.setEol(editor, lineEnding)\r\n        })\r\n    );\r\n    this.quickInputService?.showQuickPick(items, {placeholder: nls.localizeByDefault('Select End of Line Sequence')});\r\n  }\r\n\r\n  protected setEol(editor: MonacoEditor, lineEnding: string): void {\r\n    const model = editor.document && editor.document.textEditorModel;\r\n    if (model) {\r\n      if (lineEnding === 'CRLF' || lineEnding === '\\r\\n') {\r\n        model.pushEOL(monaco.editor.EndOfLineSequence.CRLF);\r\n      } else {\r\n        model.pushEOL(monaco.editor.EndOfLineSequence.LF);\r\n      }\r\n    }\r\n  }\r\n\r\n  protected newConfigTabSizeHandler(useSpaces: boolean): MonacoEditorCommandHandler {\r\n    return {\r\n      execute: editor => this.configureTabSize(editor, useSpaces)\r\n    };\r\n  }\r\n\r\n  protected configureTabSize(editor: MonacoEditor, useSpaces: boolean): void {\r\n    const model = editor.document && editor.document.textEditorModel;\r\n    if (model) {\r\n      const {tabSize} = model.getOptions();\r\n      const sizes = Array.from(Array(8), (_, x) => x + 1);\r\n      const tabSizeOptions = sizes.map(size =>\r\n          ({\r\n            label: size === tabSize ? size + '   ' + nls.localizeByDefault('Configured Tab Size') : size.toString(),\r\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n            execute: () => model.updateOptions({\r\n              tabSize: size || tabSize,\r\n              insertSpaces: useSpaces\r\n            })\r\n          })\r\n      );\r\n      this.quickInputService?.showQuickPick(tabSizeOptions, {placeholder: nls.localizeByDefault('Select Tab Size for Current File')});\r\n    }\r\n  }\r\n\r\n  protected newRevertActiveEditorHandler(): MonacoEditorCommandHandler {\r\n    return {\r\n      execute: () => this.revertEditor(this.getActiveEditor().editor),\r\n    };\r\n  }\r\n\r\n  protected newRevertAndCloseActiveEditorHandler(): MonacoEditorCommandHandler {\r\n    return {\r\n      execute: async () => this.revertAndCloseActiveEditor(this.getActiveEditor())\r\n    };\r\n  }\r\n\r\n  protected getActiveEditor(): { widget?: EditorWidget, editor?: MonacoEditor } {\r\n    const widget = this.editorManager.currentEditor;\r\n    return {widget, editor: widget && MonacoEditor.getCurrent(this.editorManager)};\r\n  }\r\n\r\n  protected async revertEditor(editor?: MonacoEditor): Promise<void> {\r\n    if (editor) {\r\n      return editor.document.revert();\r\n    }\r\n  }\r\n\r\n  protected async revertAndCloseActiveEditor(current: { widget?: EditorWidget, editor?: MonacoEditor }): Promise<void> {\r\n    if (current.editor && current.widget) {\r\n      try {\r\n        await this.revertEditor(current.editor);\r\n        current.widget.close();\r\n      } catch (error) {\r\n        await this.shell.closeWidget(current.widget.id, {save: false});\r\n      }\r\n    }\r\n  }\r\n}\r\n"]}