index.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. ILayoutRestorer,
  5. JupyterFrontEnd,
  6. JupyterFrontEndPlugin,
  7. LabShell
  8. } from '@jupyterlab/application';
  9. import { ICommandPalette } from '@jupyterlab/apputils';
  10. import { WidgetTracker, MainAreaWidget } from '@jupyterlab/apputils';
  11. import { IConsoleTracker, ConsolePanel } from '@jupyterlab/console';
  12. import { IStateDB } from '@jupyterlab/coreutils';
  13. import { IEditorTracker } from '@jupyterlab/fileeditor';
  14. import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';
  15. import { UUID } from '@phosphor/coreutils';
  16. import { Debugger } from './debugger';
  17. import { IDebugger, IDebuggerSidebar } from './tokens';
  18. import { DebuggerNotebookHandler } from './handlers/notebook';
  19. import { DebuggerConsoleHandler } from './handlers/console';
  20. import { DebuggerSidebar } from './sidebar';
  21. import { SessionTypes } from './breakpoints';
  22. import { DebugSession } from './session';
  23. /**
  24. * The command IDs used by the debugger plugin.
  25. */
  26. export namespace CommandIDs {
  27. export const create = 'debugger:create';
  28. export const debugConsole = 'debugger:debug-console';
  29. export const debugFile = 'debugger:debug-file';
  30. export const debugNotebook = 'debugger:debug-notebook';
  31. }
  32. /**
  33. * A plugin that provides visual debugging support for consoles.
  34. */
  35. const consoles: JupyterFrontEndPlugin<void> = {
  36. id: '@jupyterlab/debugger:consoles',
  37. autoStart: true,
  38. requires: [IDebugger, IDebuggerSidebar, IConsoleTracker],
  39. activate: (
  40. _,
  41. debug: IDebugger,
  42. sidebar: IDebuggerSidebar,
  43. tracker: IConsoleTracker
  44. ) => {
  45. debug.currentChanged.connect((_, update) => {
  46. if (update) {
  47. update.content.model.sidebar = sidebar;
  48. new DebuggerConsoleHandler({
  49. debuggerModel: update.content.model,
  50. consoleTracker: tracker
  51. });
  52. }
  53. });
  54. }
  55. };
  56. /**
  57. * A plugin that provides visual debugging support for file editors.
  58. */
  59. const files: JupyterFrontEndPlugin<void> = {
  60. id: '@jupyterlab/debugger:files',
  61. autoStart: true,
  62. requires: [IEditorTracker, IDebugger, INotebookTracker],
  63. activate: (
  64. app: JupyterFrontEnd,
  65. tracker: IEditorTracker | null,
  66. debug: IDebugger,
  67. notebook: INotebookTracker
  68. ) => {
  69. const shell = app.shell;
  70. (shell as LabShell).currentChanged.connect((sender, update) => {
  71. const newWidget = update.newValue;
  72. const session =
  73. newWidget && (newWidget as NotebookPanel | ConsolePanel).session
  74. ? (newWidget as NotebookPanel | ConsolePanel).session
  75. : false;
  76. if (session && debug.currentWidget) {
  77. const debugModel: Debugger.Model = debug.currentWidget.content.model;
  78. debugModel.session = new DebugSession({ client: session });
  79. debugModel.sidebar.breakpoints.model.type = session.type as SessionTypes;
  80. }
  81. });
  82. app.commands.addCommand(CommandIDs.debugFile, {
  83. execute: async _ => {
  84. if (!tracker || !tracker.currentWidget) {
  85. return;
  86. }
  87. if (tracker.currentWidget) {
  88. // TODO: Find if the file is backed by a kernel or attach it to one.
  89. // const widget = await app.commands.execute(CommandIDs.create);
  90. // app.shell.add(widget, 'main');
  91. }
  92. }
  93. });
  94. }
  95. };
  96. /**
  97. * A plugin that provides visual debugging support for notebooks.
  98. */
  99. const notebooks: JupyterFrontEndPlugin<void> = {
  100. id: '@jupyterlab/debugger:notebooks',
  101. autoStart: true,
  102. requires: [IDebugger, IDebuggerSidebar],
  103. optional: [INotebookTracker, ICommandPalette],
  104. activate: (
  105. app: JupyterFrontEnd,
  106. debug: IDebugger,
  107. sidebar: IDebuggerSidebar,
  108. notebook: INotebookTracker,
  109. palette: ICommandPalette
  110. ) => {
  111. // 1. Keep track of any new notebook that is created.
  112. // 2. When the *active* notebook changes, hook it up to the debugger.
  113. // 3. If a notebook is closed, dispose the debugger session.
  114. debug.currentChanged.connect((_, update) => {
  115. if (update) {
  116. update.content.model.sidebar = sidebar;
  117. new DebuggerNotebookHandler({
  118. debuggerModel: update.content.model,
  119. notebookTracker: notebook
  120. });
  121. }
  122. });
  123. // // Debugger model:
  124. // // LIST of editors that it currently cares about.
  125. // // Manages life cycle signal connections.
  126. // // Manages variables
  127. // });
  128. // this exist only for my test in futre will be removed
  129. const command: string = CommandIDs.debugNotebook;
  130. app.commands.addCommand(command, {
  131. label: 'test',
  132. execute: () => {}
  133. });
  134. palette.addItem({ command, category: 'dev test' });
  135. }
  136. };
  137. /**
  138. * A plugin providing a condensed sidebar UI for debugging.
  139. */
  140. const sidebar: JupyterFrontEndPlugin<IDebuggerSidebar> = {
  141. id: '@jupyterlab/debugger:sidebar',
  142. optional: [ILayoutRestorer],
  143. provides: IDebuggerSidebar,
  144. autoStart: true,
  145. activate: (
  146. app: JupyterFrontEnd,
  147. restorer: ILayoutRestorer | null
  148. ): DebuggerSidebar => {
  149. const { shell } = app;
  150. const label = 'Environment';
  151. const namespace = 'jp-debugger-sidebar';
  152. const sidebar = new DebuggerSidebar(null);
  153. sidebar.id = namespace;
  154. sidebar.title.label = label;
  155. shell.add(sidebar, 'right', { activate: false });
  156. if (restorer) {
  157. restorer.add(sidebar, sidebar.id);
  158. }
  159. return sidebar;
  160. }
  161. };
  162. /**
  163. * A plugin providing a tracker code debuggers.
  164. */
  165. const tracker: JupyterFrontEndPlugin<IDebugger> = {
  166. id: '@jupyterlab/debugger:tracker',
  167. optional: [ILayoutRestorer, IDebuggerSidebar, ICommandPalette],
  168. requires: [IStateDB],
  169. provides: IDebugger,
  170. autoStart: true,
  171. activate: (
  172. app: JupyterFrontEnd,
  173. state: IStateDB,
  174. restorer: ILayoutRestorer | null,
  175. sidebar: IDebuggerSidebar | null,
  176. palette: ICommandPalette
  177. ): IDebugger => {
  178. const tracker = new WidgetTracker<MainAreaWidget<Debugger>>({
  179. namespace: 'debugger'
  180. });
  181. tracker.widgetUpdated.connect((_, update) => {
  182. update;
  183. });
  184. const command = CommandIDs.create;
  185. app.commands.addCommand(command, {
  186. label: 'Debugger',
  187. execute: args => {
  188. const id = (args.id as string) || UUID.uuid4();
  189. if (id) {
  190. console.log('Debugger ID: ', id);
  191. }
  192. const existedWidget = tracker.find(
  193. widget => id === widget.content.model.id
  194. );
  195. if (existedWidget) {
  196. app.shell.add(existedWidget, 'main');
  197. return;
  198. }
  199. const widget = new MainAreaWidget({
  200. content: new Debugger({
  201. connector: state,
  202. id: id
  203. })
  204. });
  205. void tracker.add(widget);
  206. app.shell.add(widget, 'main');
  207. return widget;
  208. }
  209. });
  210. palette.addItem({ command, category: 'Debugger' });
  211. if (restorer) {
  212. // Handle state restoration.
  213. void restorer.restore(tracker, {
  214. command: command,
  215. args: widget => ({ id: widget.content.model.id }),
  216. name: widget => widget.content.model.id
  217. });
  218. }
  219. return tracker;
  220. }
  221. };
  222. /**
  223. * Export the plugins as default.
  224. */
  225. const plugins: JupyterFrontEndPlugin<any>[] = [
  226. consoles,
  227. files,
  228. notebooks,
  229. sidebar,
  230. tracker
  231. ];
  232. export default plugins;