ed10a74f7af062721e8e4acd1197f801c24ff2a51d689326ba295888f687cdfb7b0d9ef79e349295f74a5a5acfbd6d6417c51b67568e7a0e0ec1f7bd5b3063 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. import './standalone-tokens.css';
  6. import { Disposable, DisposableStore } from '../../../base/common/lifecycle.js';
  7. import { splitLines } from '../../../base/common/strings.js';
  8. import { FontMeasurements } from '../../browser/config/fontMeasurements.js';
  9. import { ICodeEditorService } from '../../browser/services/codeEditorService.js';
  10. import { DiffNavigator } from '../../browser/widget/diffNavigator.js';
  11. import { ApplyUpdateResult, ConfigurationChangedEvent, EditorOptions } from '../../common/config/editorOptions.js';
  12. import { BareFontInfo, FontInfo } from '../../common/config/fontInfo.js';
  13. import { EditorType } from '../../common/editorCommon.js';
  14. import { FindMatch, TextModelResolvedOptions } from '../../common/model.js';
  15. import * as languages from '../../common/languages.js';
  16. import { ILanguageConfigurationService } from '../../common/languages/languageConfigurationRegistry.js';
  17. import { NullState, nullTokenize } from '../../common/languages/nullTokenize.js';
  18. import { ILanguageService } from '../../common/languages/language.js';
  19. import { IModelService } from '../../common/services/model.js';
  20. import { createWebWorker as actualCreateWebWorker } from '../../browser/services/webWorker.js';
  21. import * as standaloneEnums from '../../common/standalone/standaloneEnums.js';
  22. import { Colorizer } from './colorizer.js';
  23. import { createTextModel, StandaloneDiffEditor, StandaloneEditor } from './standaloneCodeEditor.js';
  24. import { StandaloneKeybindingService, StandaloneServices } from './standaloneServices.js';
  25. import { IStandaloneThemeService } from '../common/standaloneTheme.js';
  26. import { CommandsRegistry } from '../../../platform/commands/common/commands.js';
  27. import { IMarkerService } from '../../../platform/markers/common/markers.js';
  28. import { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js';
  29. import { EditorCommand } from '../../browser/editorExtensions.js';
  30. import { MenuRegistry, MenuId } from '../../../platform/actions/common/actions.js';
  31. import { ContextKeyExpr } from '../../../platform/contextkey/common/contextkey.js';
  32. /**
  33. * Create a new editor under `domElement`.
  34. * `domElement` should be empty (not contain other dom nodes).
  35. * The editor will read the size of `domElement`.
  36. */
  37. export function create(domElement, options, override) {
  38. const instantiationService = StandaloneServices.initialize(override || {});
  39. return instantiationService.createInstance(StandaloneEditor, domElement, options);
  40. }
  41. /**
  42. * Emitted when an editor is created.
  43. * Creating a diff editor might cause this listener to be invoked with the two editors.
  44. * @event
  45. */
  46. export function onDidCreateEditor(listener) {
  47. const codeEditorService = StandaloneServices.get(ICodeEditorService);
  48. return codeEditorService.onCodeEditorAdd((editor) => {
  49. listener(editor);
  50. });
  51. }
  52. /**
  53. * Emitted when an diff editor is created.
  54. * @event
  55. */
  56. export function onDidCreateDiffEditor(listener) {
  57. const codeEditorService = StandaloneServices.get(ICodeEditorService);
  58. return codeEditorService.onDiffEditorAdd((editor) => {
  59. listener(editor);
  60. });
  61. }
  62. /**
  63. * Get all the created editors.
  64. */
  65. export function getEditors() {
  66. const codeEditorService = StandaloneServices.get(ICodeEditorService);
  67. return codeEditorService.listCodeEditors();
  68. }
  69. /**
  70. * Get all the created diff editors.
  71. */
  72. export function getDiffEditors() {
  73. const codeEditorService = StandaloneServices.get(ICodeEditorService);
  74. return codeEditorService.listDiffEditors();
  75. }
  76. /**
  77. * Create a new diff editor under `domElement`.
  78. * `domElement` should be empty (not contain other dom nodes).
  79. * The editor will read the size of `domElement`.
  80. */
  81. export function createDiffEditor(domElement, options, override) {
  82. const instantiationService = StandaloneServices.initialize(override || {});
  83. return instantiationService.createInstance(StandaloneDiffEditor, domElement, options);
  84. }
  85. export function createDiffNavigator(diffEditor, opts) {
  86. return new DiffNavigator(diffEditor, opts);
  87. }
  88. /**
  89. * Add a command.
  90. */
  91. export function addCommand(descriptor) {
  92. if ((typeof descriptor.id !== 'string') || (typeof descriptor.run !== 'function')) {
  93. throw new Error('Invalid command descriptor, `id` and `run` are required properties!');
  94. }
  95. return CommandsRegistry.registerCommand(descriptor.id, descriptor.run);
  96. }
  97. /**
  98. * Add an action to all editors.
  99. */
  100. export function addEditorAction(descriptor) {
  101. if ((typeof descriptor.id !== 'string') || (typeof descriptor.label !== 'string') || (typeof descriptor.run !== 'function')) {
  102. throw new Error('Invalid action descriptor, `id`, `label` and `run` are required properties!');
  103. }
  104. const precondition = ContextKeyExpr.deserialize(descriptor.precondition);
  105. const run = (accessor, ...args) => {
  106. return EditorCommand.runEditorCommand(accessor, args, precondition, (accessor, editor, args) => Promise.resolve(descriptor.run(editor, ...args)));
  107. };
  108. const toDispose = new DisposableStore();
  109. // Register the command
  110. toDispose.add(CommandsRegistry.registerCommand(descriptor.id, run));
  111. // Register the context menu item
  112. if (descriptor.contextMenuGroupId) {
  113. const menuItem = {
  114. command: {
  115. id: descriptor.id,
  116. title: descriptor.label
  117. },
  118. when: precondition,
  119. group: descriptor.contextMenuGroupId,
  120. order: descriptor.contextMenuOrder || 0
  121. };
  122. toDispose.add(MenuRegistry.appendMenuItem(MenuId.EditorContext, menuItem));
  123. }
  124. // Register the keybindings
  125. if (Array.isArray(descriptor.keybindings)) {
  126. const keybindingService = StandaloneServices.get(IKeybindingService);
  127. if (!(keybindingService instanceof StandaloneKeybindingService)) {
  128. console.warn('Cannot add keybinding because the editor is configured with an unrecognized KeybindingService');
  129. }
  130. else {
  131. const keybindingsWhen = ContextKeyExpr.and(precondition, ContextKeyExpr.deserialize(descriptor.keybindingContext));
  132. toDispose.add(keybindingService.addDynamicKeybindings(descriptor.keybindings.map((keybinding) => {
  133. return {
  134. keybinding,
  135. command: descriptor.id,
  136. when: keybindingsWhen
  137. };
  138. })));
  139. }
  140. }
  141. return toDispose;
  142. }
  143. /**
  144. * Add a keybinding rule.
  145. */
  146. export function addKeybindingRule(rule) {
  147. return addKeybindingRules([rule]);
  148. }
  149. /**
  150. * Add keybinding rules.
  151. */
  152. export function addKeybindingRules(rules) {
  153. const keybindingService = StandaloneServices.get(IKeybindingService);
  154. if (!(keybindingService instanceof StandaloneKeybindingService)) {
  155. console.warn('Cannot add keybinding because the editor is configured with an unrecognized KeybindingService');
  156. return Disposable.None;
  157. }
  158. return keybindingService.addDynamicKeybindings(rules.map((rule) => {
  159. return {
  160. keybinding: rule.keybinding,
  161. command: rule.command,
  162. commandArgs: rule.commandArgs,
  163. when: ContextKeyExpr.deserialize(rule.when),
  164. };
  165. }));
  166. }
  167. /**
  168. * Create a new editor model.
  169. * You can specify the language that should be set for this model or let the language be inferred from the `uri`.
  170. */
  171. export function createModel(value, language, uri) {
  172. const languageService = StandaloneServices.get(ILanguageService);
  173. const languageId = languageService.getLanguageIdByMimeType(language) || language;
  174. return createTextModel(StandaloneServices.get(IModelService), languageService, value, languageId, uri);
  175. }
  176. /**
  177. * Change the language for a model.
  178. */
  179. export function setModelLanguage(model, languageId) {
  180. const languageService = StandaloneServices.get(ILanguageService);
  181. const modelService = StandaloneServices.get(IModelService);
  182. modelService.setMode(model, languageService.createById(languageId));
  183. }
  184. /**
  185. * Set the markers for a model.
  186. */
  187. export function setModelMarkers(model, owner, markers) {
  188. if (model) {
  189. const markerService = StandaloneServices.get(IMarkerService);
  190. markerService.changeOne(owner, model.uri, markers);
  191. }
  192. }
  193. /**
  194. * Remove all markers of an owner.
  195. */
  196. export function removeAllMarkers(owner) {
  197. const markerService = StandaloneServices.get(IMarkerService);
  198. markerService.changeAll(owner, []);
  199. }
  200. /**
  201. * Get markers for owner and/or resource
  202. *
  203. * @returns list of markers
  204. */
  205. export function getModelMarkers(filter) {
  206. const markerService = StandaloneServices.get(IMarkerService);
  207. return markerService.read(filter);
  208. }
  209. /**
  210. * Emitted when markers change for a model.
  211. * @event
  212. */
  213. export function onDidChangeMarkers(listener) {
  214. const markerService = StandaloneServices.get(IMarkerService);
  215. return markerService.onMarkerChanged(listener);
  216. }
  217. /**
  218. * Get the model that has `uri` if it exists.
  219. */
  220. export function getModel(uri) {
  221. const modelService = StandaloneServices.get(IModelService);
  222. return modelService.getModel(uri);
  223. }
  224. /**
  225. * Get all the created models.
  226. */
  227. export function getModels() {
  228. const modelService = StandaloneServices.get(IModelService);
  229. return modelService.getModels();
  230. }
  231. /**
  232. * Emitted when a model is created.
  233. * @event
  234. */
  235. export function onDidCreateModel(listener) {
  236. const modelService = StandaloneServices.get(IModelService);
  237. return modelService.onModelAdded(listener);
  238. }
  239. /**
  240. * Emitted right before a model is disposed.
  241. * @event
  242. */
  243. export function onWillDisposeModel(listener) {
  244. const modelService = StandaloneServices.get(IModelService);
  245. return modelService.onModelRemoved(listener);
  246. }
  247. /**
  248. * Emitted when a different language is set to a model.
  249. * @event
  250. */
  251. export function onDidChangeModelLanguage(listener) {
  252. const modelService = StandaloneServices.get(IModelService);
  253. return modelService.onModelLanguageChanged((e) => {
  254. listener({
  255. model: e.model,
  256. oldLanguage: e.oldLanguageId
  257. });
  258. });
  259. }
  260. /**
  261. * Create a new web worker that has model syncing capabilities built in.
  262. * Specify an AMD module to load that will `create` an object that will be proxied.
  263. */
  264. export function createWebWorker(opts) {
  265. return actualCreateWebWorker(StandaloneServices.get(IModelService), StandaloneServices.get(ILanguageConfigurationService), opts);
  266. }
  267. /**
  268. * Colorize the contents of `domNode` using attribute `data-lang`.
  269. */
  270. export function colorizeElement(domNode, options) {
  271. const languageService = StandaloneServices.get(ILanguageService);
  272. const themeService = StandaloneServices.get(IStandaloneThemeService);
  273. themeService.registerEditorContainer(domNode);
  274. return Colorizer.colorizeElement(themeService, languageService, domNode, options);
  275. }
  276. /**
  277. * Colorize `text` using language `languageId`.
  278. */
  279. export function colorize(text, languageId, options) {
  280. const languageService = StandaloneServices.get(ILanguageService);
  281. const themeService = StandaloneServices.get(IStandaloneThemeService);
  282. themeService.registerEditorContainer(document.body);
  283. return Colorizer.colorize(languageService, text, languageId, options);
  284. }
  285. /**
  286. * Colorize a line in a model.
  287. */
  288. export function colorizeModelLine(model, lineNumber, tabSize = 4) {
  289. const themeService = StandaloneServices.get(IStandaloneThemeService);
  290. themeService.registerEditorContainer(document.body);
  291. return Colorizer.colorizeModelLine(model, lineNumber, tabSize);
  292. }
  293. /**
  294. * @internal
  295. */
  296. function getSafeTokenizationSupport(language) {
  297. const tokenizationSupport = languages.TokenizationRegistry.get(language);
  298. if (tokenizationSupport) {
  299. return tokenizationSupport;
  300. }
  301. return {
  302. getInitialState: () => NullState,
  303. tokenize: (line, hasEOL, state) => nullTokenize(language, state)
  304. };
  305. }
  306. /**
  307. * Tokenize `text` using language `languageId`
  308. */
  309. export function tokenize(text, languageId) {
  310. // Needed in order to get the mode registered for subsequent look-ups
  311. languages.TokenizationRegistry.getOrCreate(languageId);
  312. const tokenizationSupport = getSafeTokenizationSupport(languageId);
  313. const lines = splitLines(text);
  314. const result = [];
  315. let state = tokenizationSupport.getInitialState();
  316. for (let i = 0, len = lines.length; i < len; i++) {
  317. const line = lines[i];
  318. const tokenizationResult = tokenizationSupport.tokenize(line, true, state);
  319. result[i] = tokenizationResult.tokens;
  320. state = tokenizationResult.endState;
  321. }
  322. return result;
  323. }
  324. /**
  325. * Define a new theme or update an existing theme.
  326. */
  327. export function defineTheme(themeName, themeData) {
  328. const standaloneThemeService = StandaloneServices.get(IStandaloneThemeService);
  329. standaloneThemeService.defineTheme(themeName, themeData);
  330. }
  331. /**
  332. * Switches to a theme.
  333. */
  334. export function setTheme(themeName) {
  335. const standaloneThemeService = StandaloneServices.get(IStandaloneThemeService);
  336. standaloneThemeService.setTheme(themeName);
  337. }
  338. /**
  339. * Clears all cached font measurements and triggers re-measurement.
  340. */
  341. export function remeasureFonts() {
  342. FontMeasurements.clearAllFontInfos();
  343. }
  344. /**
  345. * Register a command.
  346. */
  347. export function registerCommand(id, handler) {
  348. return CommandsRegistry.registerCommand({ id, handler });
  349. }
  350. /**
  351. * @internal
  352. */
  353. export function createMonacoEditorAPI() {
  354. return {
  355. // methods
  356. create: create,
  357. getEditors: getEditors,
  358. getDiffEditors: getDiffEditors,
  359. onDidCreateEditor: onDidCreateEditor,
  360. onDidCreateDiffEditor: onDidCreateDiffEditor,
  361. createDiffEditor: createDiffEditor,
  362. createDiffNavigator: createDiffNavigator,
  363. addCommand: addCommand,
  364. addEditorAction: addEditorAction,
  365. addKeybindingRule: addKeybindingRule,
  366. addKeybindingRules: addKeybindingRules,
  367. createModel: createModel,
  368. setModelLanguage: setModelLanguage,
  369. setModelMarkers: setModelMarkers,
  370. getModelMarkers: getModelMarkers,
  371. removeAllMarkers: removeAllMarkers,
  372. onDidChangeMarkers: onDidChangeMarkers,
  373. getModels: getModels,
  374. getModel: getModel,
  375. onDidCreateModel: onDidCreateModel,
  376. onWillDisposeModel: onWillDisposeModel,
  377. onDidChangeModelLanguage: onDidChangeModelLanguage,
  378. createWebWorker: createWebWorker,
  379. colorizeElement: colorizeElement,
  380. colorize: colorize,
  381. colorizeModelLine: colorizeModelLine,
  382. tokenize: tokenize,
  383. defineTheme: defineTheme,
  384. setTheme: setTheme,
  385. remeasureFonts: remeasureFonts,
  386. registerCommand: registerCommand,
  387. // enums
  388. AccessibilitySupport: standaloneEnums.AccessibilitySupport,
  389. ContentWidgetPositionPreference: standaloneEnums.ContentWidgetPositionPreference,
  390. CursorChangeReason: standaloneEnums.CursorChangeReason,
  391. DefaultEndOfLine: standaloneEnums.DefaultEndOfLine,
  392. EditorAutoIndentStrategy: standaloneEnums.EditorAutoIndentStrategy,
  393. EditorOption: standaloneEnums.EditorOption,
  394. EndOfLinePreference: standaloneEnums.EndOfLinePreference,
  395. EndOfLineSequence: standaloneEnums.EndOfLineSequence,
  396. MinimapPosition: standaloneEnums.MinimapPosition,
  397. MouseTargetType: standaloneEnums.MouseTargetType,
  398. OverlayWidgetPositionPreference: standaloneEnums.OverlayWidgetPositionPreference,
  399. OverviewRulerLane: standaloneEnums.OverviewRulerLane,
  400. RenderLineNumbersType: standaloneEnums.RenderLineNumbersType,
  401. RenderMinimap: standaloneEnums.RenderMinimap,
  402. ScrollbarVisibility: standaloneEnums.ScrollbarVisibility,
  403. ScrollType: standaloneEnums.ScrollType,
  404. TextEditorCursorBlinkingStyle: standaloneEnums.TextEditorCursorBlinkingStyle,
  405. TextEditorCursorStyle: standaloneEnums.TextEditorCursorStyle,
  406. TrackedRangeStickiness: standaloneEnums.TrackedRangeStickiness,
  407. WrappingIndent: standaloneEnums.WrappingIndent,
  408. InjectedTextCursorStops: standaloneEnums.InjectedTextCursorStops,
  409. PositionAffinity: standaloneEnums.PositionAffinity,
  410. // classes
  411. ConfigurationChangedEvent: ConfigurationChangedEvent,
  412. BareFontInfo: BareFontInfo,
  413. FontInfo: FontInfo,
  414. TextModelResolvedOptions: TextModelResolvedOptions,
  415. FindMatch: FindMatch,
  416. ApplyUpdateResult: ApplyUpdateResult,
  417. // vars
  418. EditorType: EditorType,
  419. EditorOptions: EditorOptions
  420. };
  421. }