index.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. ILayoutRestorer,
  5. JupyterLab,
  6. JupyterLabPlugin
  7. } from '@jupyterlab/application';
  8. import {
  9. ICommandPalette,
  10. InstanceTracker,
  11. MainAreaWidget
  12. } from '@jupyterlab/apputils';
  13. import { IConsoleTracker } from '@jupyterlab/console';
  14. import {
  15. IInspector,
  16. InspectionHandler,
  17. InspectorPanel,
  18. KernelConnector
  19. } from '@jupyterlab/inspector';
  20. import { INotebookTracker } from '@jupyterlab/notebook';
  21. import { InspectorManager } from './manager';
  22. /**
  23. * The command IDs used by the inspector plugin.
  24. */
  25. namespace CommandIDs {
  26. export const open = 'inspector:open';
  27. }
  28. /**
  29. * A service providing code introspection.
  30. */
  31. const inspector: JupyterLabPlugin<IInspector> = {
  32. id: '@jupyterlab/inspector-extension:inspector',
  33. requires: [ICommandPalette, ILayoutRestorer],
  34. provides: IInspector,
  35. autoStart: true,
  36. activate: (
  37. app: JupyterLab,
  38. palette: ICommandPalette,
  39. restorer: ILayoutRestorer
  40. ): IInspector => {
  41. const { commands, shell } = app;
  42. const manager = new InspectorManager();
  43. const category = 'Inspector';
  44. const command = CommandIDs.open;
  45. const label = 'Open Inspector';
  46. const namespace = 'inspector';
  47. const tracker = new InstanceTracker<MainAreaWidget<InspectorPanel>>({
  48. namespace
  49. });
  50. /**
  51. * Create and track a new inspector.
  52. */
  53. function newInspectorPanel(): InspectorPanel {
  54. const inspector = new InspectorPanel();
  55. inspector.id = 'jp-inspector';
  56. inspector.title.label = 'Inspector';
  57. inspector.disposed.connect(() => {
  58. if (manager.inspector === inspector) {
  59. manager.inspector = null;
  60. }
  61. });
  62. // Track the inspector.
  63. let widget = new MainAreaWidget({ content: inspector });
  64. tracker.add(widget);
  65. // Add the default inspector child items.
  66. Private.defaultInspectorItems.forEach(item => {
  67. inspector.add(item);
  68. });
  69. return inspector;
  70. }
  71. // Handle state restoration.
  72. restorer.restore(tracker, {
  73. command,
  74. args: () => null,
  75. name: () => 'inspector'
  76. });
  77. // Add command to registry and palette.
  78. commands.addCommand(command, {
  79. label,
  80. execute: () => {
  81. if (!manager.inspector || manager.inspector.isDisposed) {
  82. manager.inspector = newInspectorPanel();
  83. }
  84. if (!manager.inspector.isAttached) {
  85. shell.addToMainArea(manager.inspector.parent, { activate: false });
  86. }
  87. shell.activateById(manager.inspector.parent.id);
  88. }
  89. });
  90. palette.addItem({ command, category });
  91. return manager;
  92. }
  93. };
  94. /**
  95. * An extension that registers consoles for inspection.
  96. */
  97. const consoles: JupyterLabPlugin<void> = {
  98. id: '@jupyterlab/inspector-extension:consoles',
  99. requires: [IInspector, IConsoleTracker],
  100. autoStart: true,
  101. activate: (
  102. app: JupyterLab,
  103. manager: IInspector,
  104. consoles: IConsoleTracker
  105. ): void => {
  106. // Maintain association of new consoles with their respective handlers.
  107. const handlers: { [id: string]: InspectionHandler } = {};
  108. // Create a handler for each console that is created.
  109. consoles.widgetAdded.connect((sender, parent) => {
  110. const session = parent.console.session;
  111. const rendermime = parent.console.rendermime;
  112. const connector = new KernelConnector({ session });
  113. const handler = new InspectionHandler({ connector, rendermime });
  114. // Associate the handler to the widget.
  115. handlers[parent.id] = handler;
  116. // Set the initial editor.
  117. let cell = parent.console.promptCell;
  118. handler.editor = cell && cell.editor;
  119. // Listen for prompt creation.
  120. parent.console.promptCellCreated.connect((sender, cell) => {
  121. handler.editor = cell && cell.editor;
  122. });
  123. // Listen for parent disposal.
  124. parent.disposed.connect(() => {
  125. delete handlers[parent.id];
  126. handler.dispose();
  127. });
  128. });
  129. // Keep track of console instances and set inspector source.
  130. app.shell.currentChanged.connect((sender, args) => {
  131. let widget = args.newValue;
  132. if (!widget || !consoles.has(widget)) {
  133. return;
  134. }
  135. let source = handlers[widget.id];
  136. if (source) {
  137. manager.source = source;
  138. }
  139. });
  140. app.contextMenu.addItem({
  141. command: CommandIDs.open,
  142. selector: '.jp-CodeConsole-promptCell'
  143. });
  144. }
  145. };
  146. /**
  147. * An extension that registers notebooks for inspection.
  148. */
  149. const notebooks: JupyterLabPlugin<void> = {
  150. id: '@jupyterlab/inspector-extension:notebooks',
  151. requires: [IInspector, INotebookTracker],
  152. autoStart: true,
  153. activate: (
  154. app: JupyterLab,
  155. manager: IInspector,
  156. notebooks: INotebookTracker
  157. ): void => {
  158. // Maintain association of new notebooks with their respective handlers.
  159. const handlers: { [id: string]: InspectionHandler } = {};
  160. // Create a handler for each notebook that is created.
  161. notebooks.widgetAdded.connect((sender, parent) => {
  162. const session = parent.session;
  163. const rendermime = parent.rendermime;
  164. const connector = new KernelConnector({ session });
  165. const handler = new InspectionHandler({ connector, rendermime });
  166. // Associate the handler to the widget.
  167. handlers[parent.id] = handler;
  168. // Set the initial editor.
  169. let cell = parent.content.activeCell;
  170. handler.editor = cell && cell.editor;
  171. // Listen for active cell changes.
  172. parent.content.activeCellChanged.connect((sender, cell) => {
  173. handler.editor = cell && cell.editor;
  174. });
  175. // Listen for parent disposal.
  176. parent.disposed.connect(() => {
  177. delete handlers[parent.id];
  178. handler.dispose();
  179. });
  180. });
  181. // Keep track of notebook instances and set inspector source.
  182. app.shell.currentChanged.connect((sender, args) => {
  183. let widget = args.newValue;
  184. if (!widget || !notebooks.has(widget)) {
  185. return;
  186. }
  187. let source = handlers[widget.id];
  188. if (source) {
  189. manager.source = source;
  190. }
  191. });
  192. app.contextMenu.addItem({
  193. command: CommandIDs.open,
  194. selector: '.jp-Notebook'
  195. });
  196. }
  197. };
  198. /**
  199. * Export the plugins as default.
  200. */
  201. const plugins: JupyterLabPlugin<any>[] = [inspector, consoles, notebooks];
  202. export default plugins;
  203. /**
  204. * A namespace for private data.
  205. */
  206. namespace Private {
  207. /**
  208. * The default set of inspector items added to the inspector panel.
  209. */
  210. export const defaultInspectorItems: IInspector.IInspectorItem[] = [
  211. {
  212. className: 'jp-HintsInspectorItem',
  213. name: 'Hints',
  214. rank: 20,
  215. type: 'hints'
  216. }
  217. ];
  218. }