plugin.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import 'codemirror/addon/edit/matchbrackets.js';
  4. import 'codemirror/addon/edit/closebrackets.js';
  5. import 'codemirror/addon/comment/comment.js';
  6. import 'codemirror/keymap/vim.js';
  7. import {
  8. Menu
  9. } from 'phosphor/lib/ui/menu';
  10. import {
  11. JupyterLab, JupyterLabPlugin
  12. } from '../application';
  13. import {
  14. IEditorServices
  15. } from '../codeeditor';
  16. import {
  17. ICommandPalette
  18. } from '../commandpalette';
  19. import {
  20. IEditorTracker
  21. } from '../editorwidget';
  22. import {
  23. IMainMenu
  24. } from '../mainmenu';
  25. import {
  26. editorServices, CodeMirrorEditor
  27. } from '.';
  28. /**
  29. * The editor services.
  30. */
  31. export
  32. const servicesPlugin: JupyterLabPlugin<IEditorServices> = {
  33. id: IEditorServices.name,
  34. provides: IEditorServices,
  35. activate: (): IEditorServices => editorServices
  36. };
  37. /**
  38. * The editor commands.
  39. */
  40. export
  41. const commandsPlugin: JupyterLabPlugin<void> = {
  42. id: 'jupyter.services.editor-commands',
  43. requires: [IEditorTracker, IMainMenu, ICommandPalette],
  44. activate: activateEditorCommands,
  45. autoStart: true
  46. };
  47. /**
  48. * Export the plugins as default.
  49. */
  50. const plugins: JupyterLabPlugin<any>[] = [commandsPlugin, servicesPlugin];
  51. export default plugins;
  52. /**
  53. * The command IDs used by the editor plugin.
  54. */
  55. export
  56. namespace CommandIDs {
  57. export
  58. const lineNumbers = 'editor:line-numbers';
  59. export
  60. const lineWrap = 'editor:line-wrap';
  61. export
  62. const matchBrackets = 'editor:match-brackets';
  63. export
  64. const vimMode = 'editor:vim-mode';
  65. export
  66. const changeTheme = 'editor:change-theme';
  67. export
  68. const createConsole = 'editor:create-console';
  69. export
  70. const runCode = 'editor:run-code';
  71. };
  72. /**
  73. * Set up the editor widget menu and commands.
  74. */
  75. function activateEditorCommands(app: JupyterLab, tracker: IEditorTracker, mainMenu: IMainMenu, palette: ICommandPalette): void {
  76. let { commands, keymap } = app;
  77. /**
  78. * Toggle editor matching brackets
  79. */
  80. function toggleMatchBrackets(): void {
  81. if (tracker.currentWidget) {
  82. let editor = tracker.currentWidget.editor;
  83. if (editor instanceof CodeMirrorEditor) {
  84. let cm = editor.editor;
  85. cm.setOption('matchBrackets', !cm.getOption('matchBrackets'));
  86. }
  87. }
  88. }
  89. /**
  90. * Toggle the editor's vim mode
  91. */
  92. function toggleVim(): void {
  93. tracker.forEach(widget => {
  94. if (widget.editor instanceof CodeMirrorEditor) {
  95. let cm = widget.editor.editor;
  96. let keymap = cm.getOption('keyMap') === 'vim' ? 'default'
  97. : 'vim';
  98. cm.setOption('keyMap', keymap);
  99. }
  100. });
  101. }
  102. /**
  103. * Create a menu for the editor.
  104. */
  105. function createMenu(): Menu {
  106. let settings = new Menu({ commands, keymap });
  107. let theme = new Menu({ commands, keymap });
  108. let menu = new Menu({ commands, keymap });
  109. menu.title.label = 'Editor';
  110. settings.title.label = 'Settings';
  111. theme.title.label = 'Theme';
  112. settings.addItem({ command: CommandIDs.lineNumbers });
  113. settings.addItem({ command: CommandIDs.lineWrap });
  114. settings.addItem({ command: CommandIDs.matchBrackets });
  115. settings.addItem({ command: CommandIDs.vimMode });
  116. commands.addCommand(CommandIDs.changeTheme, {
  117. label: args => args['theme'] as string,
  118. execute: args => {
  119. let name = args['theme'] as string || CodeMirrorEditor.DEFAULT_THEME;
  120. tracker.forEach(widget => {
  121. if (widget.editor instanceof CodeMirrorEditor) {
  122. let cm = widget.editor.editor;
  123. cm.setOption('theme', name);
  124. }
  125. });
  126. }
  127. });
  128. [
  129. 'jupyter', 'default', 'abcdef', 'base16-dark', 'base16-light',
  130. 'hopscotch', 'material', 'mbo', 'mdn-like', 'seti', 'the-matrix',
  131. 'xq-light', 'zenburn'
  132. ].forEach(name => theme.addItem({
  133. command: 'editor:change-theme',
  134. args: { theme: name }
  135. }));
  136. menu.addItem({ type: 'separator' });
  137. menu.addItem({ type: 'submenu', menu: settings });
  138. menu.addItem({ type: 'submenu', menu: theme });
  139. return menu;
  140. }
  141. mainMenu.addMenu(createMenu(), { rank: 30 });
  142. commands.addCommand(CommandIDs.matchBrackets, {
  143. execute: () => { toggleMatchBrackets(); },
  144. label: 'Toggle Match Brackets',
  145. });
  146. commands.addCommand(CommandIDs.vimMode, {
  147. execute: () => { toggleVim(); },
  148. label: 'Toggle Vim Mode'
  149. });
  150. [
  151. CommandIDs.lineNumbers,
  152. CommandIDs.lineWrap,
  153. CommandIDs.matchBrackets,
  154. CommandIDs.vimMode,
  155. CommandIDs.createConsole,
  156. CommandIDs.runCode
  157. ].forEach(command => palette.addItem({ command, category: 'Editor' }));
  158. }