Browse Source

Merge pull request #346 from eskirk/editor_stuff

Added editor main menu item
Steven Silvester 8 years ago
parent
commit
46b41a4de0
2 changed files with 371 additions and 17 deletions
  1. 366 16
      src/editorwidget/plugin.ts
  2. 5 1
      src/editorwidget/widget.ts

+ 366 - 16
src/editorwidget/plugin.ts

@@ -6,13 +6,51 @@ import {
 } from 'phosphide/lib/core/application';
 } from 'phosphide/lib/core/application';
 
 
 import {
 import {
-  DocumentRegistry, IWidgetFactoryOptions
+  DocumentRegistry
 } from '../docregistry';
 } from '../docregistry';
 
 
 import {
 import {
-  EditorWidgetFactory
+  EditorWidgetFactory, EditorWidget
 } from './widget';
 } from './widget';
 
 
+import {
+  MainMenu
+} from '../mainmenu/plugin';
+
+import {
+  WidgetTracker
+} from '../widgettracker';
+
+import {
+  MenuItem, Menu
+} from 'phosphor-menus';
+
+import 'codemirror/theme/material.css';
+import 'codemirror/theme/zenburn.css';
+import 'codemirror/theme/abcdef.css';
+import 'codemirror/theme/base16-light.css';
+import 'codemirror/theme/base16-dark.css';
+import 'codemirror/theme/dracula.css';
+import 'codemirror/theme/hopscotch.css';
+import 'codemirror/theme/mbo.css';
+import 'codemirror/theme/mdn-like.css';
+import 'codemirror/theme/seti.css';
+import 'codemirror/theme/the-matrix.css';
+import 'codemirror/theme/xq-light.css';
+import 'codemirror/addon/edit/matchbrackets.js';
+import 'codemirror/keymap/vim.js';
+
+export
+class EditorTracker extends WidgetTracker<EditorWidget> { }
+
+export
+let tracker = new EditorTracker();
+
+let currentApp : Application;
+let activeEditor : EditorWidget;
+tracker.activeWidgetChanged.connect((sender, widget) => {
+  activeEditor = widget;
+});
 
 
 /**
 /**
  * The class name for all main area portrait tab icons.
  * The class name for all main area portrait tab icons.
@@ -31,19 +69,331 @@ const TEXTEDITOR_ICON_CLASS = 'jp-ImageTextEditor';
 export
 export
 const editorHandlerExtension = {
 const editorHandlerExtension = {
   id: 'jupyter.extensions.editorHandler',
   id: 'jupyter.extensions.editorHandler',
-  requires: [DocumentRegistry],
-  activate: (app: Application, registry: DocumentRegistry) => {
-    let options: IWidgetFactoryOptions = {
-      fileExtensions: ['.*'],
-      displayName: 'Editor',
-      modelName: 'text',
-      defaultFor: ['.*'],
-      preferKernel: false,
-      canStartKernel: false
-    };
-    let factory = new EditorWidgetFactory();
-    let icon = `${PORTRAIT_ICON_CLASS} ${TEXTEDITOR_ICON_CLASS}`;
-    factory.widgetCreated.connect((sender, widget) => widget.title.icon = icon);
-    registry.addWidgetFactory(factory, options);
+  requires: [DocumentRegistry, MainMenu],
+  activate: activateEditorHandler
+};
+
+/**
+ * Sets up the editor widget
+ */
+function activateEditorHandler(app: Application, registry: DocumentRegistry, mainMenu: MainMenu) {
+  let saveFile = 'editor:save-file';
+  let lineNumbers = 'editor:line-numbers';
+  let lineWrap = 'editor:line-wrap';
+  let matchBrackets = 'editor:match-brackets';
+  let vimMode = 'editor:vim-mode';
+  let defaultMode = 'editor:default-mode';
+  let closeAll = 'editor:close-all';
+
+  let editorMenu = new MenuItem({
+    text: 'Editor',
+    submenu: menu
+  });
+  currentApp = app;
+  mainMenu.addItem(editorMenu);
+  registry.addWidgetFactory(new EditorWidgetFactory(),
+  {
+    fileExtensions: ['.*'],
+    displayName: 'Editor',
+    modelName: 'text',
+    defaultFor: ['.*'],
+    preferKernel: false,
+    canStartKernel: false
+  });
+
+  app.commands.add([
+  {
+    id: saveFile,
+    handler: saveDoc
+  },
+  {
+    id: lineNumbers,
+    handler: toggleLineNums
+  },
+  {
+    id: lineWrap,
+    handler: toggleLineWrap
+  },
+  {
+    id: matchBrackets,
+    handler: toggleMatchBrackets
+  },
+  {
+    id: defaultMode,
+    handler: toggleDefault
+  },
+  {
+    id: vimMode,
+    handler: toggleVim
+  },
+  {
+    id: closeAll,
+    handler: closeAllFiles
+  }
+  ]);
+
+  app.palette.add([
+  {
+    command: saveFile,
+    category: 'Editor',
+    text: 'Save File',
+    caption: 'Save the currently open text file'
+  },
+  {
+    command: lineNumbers,
+    category: 'Editor',
+    text: 'Line Numbers',
+    caption: 'Toggles the line numbers on the editor'
+  },
+  {
+    command: lineWrap,
+    category: 'Editor',
+    text: 'Line Wrap',
+    caption: 'Toggles line wrapping on the editor'
+  },
+  {
+    command: matchBrackets,
+    category: 'Editor',
+    text: 'Match Brackets',
+    caption: 'Toggles bracket matching on the editor'
+  },
+  {
+    command: defaultMode,
+    category: 'Editor',
+    text: 'Vim Mode Off',
+    caption: 'Turns off vim mode (default)'
+  },
+  {
+    command: vimMode,
+    category: 'Editor',
+    text: 'Vim Mode',
+    caption: 'Turns on vim mode'
+  },
+  {
+    command: closeAll,
+    category: 'Editor',
+    text: 'Close all files',
+    caption: 'Closes all currently open text files'
+  }
+  ]);
+}
+
+let liNums = true;
+let liWrap = false;
+let matchBracks = false;
+
+/**
+ * Saves the current document
+ */
+function saveDoc() {
+  currentApp.commands.execute('file-operations:save');
+}
+
+/**
+ * Creates a new text file
+ */
+function newFile() {
+  currentApp.commands.execute('file-operations:new-text-file');
+}
+
+/**
+ * Toggle editor line numbers
+ */
+function toggleLineNums() {
+  if (!tracker.isDisposed) {
+    let editors = tracker.widgets;
+    liNums = !liNums;
+    for (let i = 0; i < editors.length; i++) {
+      editors[i].editor.setOption('lineNumbers', liNums);
+    }
+  }
+}
+
+/**
+ * Toggle editor line wrap
+ */
+function toggleLineWrap() {
+  if (!tracker.isDisposed) {
+    let editors = tracker.widgets;
+    liWrap = !liWrap;
+    for (let i = 0; i < editors.length; i++) {
+      editors[i].editor.setOption('lineWrap', liWrap);
+    }
+  }
+}
+
+/**
+ * Toggle editor matching brackets
+ */
+function toggleMatchBrackets() {
+  if (!tracker.isDisposed) {
+    let editors = tracker.widgets;
+    matchBracks = !matchBracks;
+    for (let i = 0; i < editors.length; i++) {
+      editors[i].editor.setOption('matchBrackets', matchBracks);
+    }
+  }
+}
+
+/**
+ * Turns on the editor's vim mode
+ */
+function toggleVim() {
+  let editors = tracker.widgets;
+  for (let i = 0; i < editors.length; i++) {
+    editors[i].editor.setOption('keyMap', 'vim');
+  }
+}
+
+/**
+ * Sets the editor to default editing mode
+ */
+function toggleDefault() {
+  if (!tracker.isDisposed) {
+    let editors = tracker.widgets;
+    for (let i = 0; i < editors.length; i++) {
+      editors[i].editor.setOption('keyMap', 'default');
+    }
+  }
+}
+
+/**
+ * Close all currently open text editor files
+ */
+function closeAllFiles() {
+  if (!tracker.isDisposed) {
+    let editors = tracker.widgets;
+    for (let i = 0; i < editors.length; i++) {
+      editors[i].close();
+    }
+  }
+}
+
+/**
+ * Handlers and menu items for the editor widget menu bar item
+ */
+let themeHandler = (item : MenuItem) => {
+  let editors = tracker.widgets;
+  for (let i = 0; i < editors.length; i++) {
+    editors[i].editor.setOption('theme', item.text);
+  }
+};
+
+let file = new Menu([
+  new MenuItem({
+    text: 'New file',
+    handler: newFile,
+    shortcut: 'Ctrl-O'
+  }),
+  new MenuItem({
+    text: 'Save',
+    handler: saveDoc,
+    shortcut: 'Cmd-S'
+  }),
+  new MenuItem({
+    text: 'Close all editors',
+    handler: closeAllFiles
+  })
+  ]);
+
+let settings = new Menu([
+  new MenuItem({
+    text: 'Line Numbers',
+    handler: toggleLineNums
+  }),
+  new MenuItem({
+    text: 'Line Wrapping',
+    handler: toggleLineWrap
+  }),
+  new MenuItem({
+    text: 'Match Brackets',
+    handler: toggleMatchBrackets
+  }),
+  new MenuItem({
+    text: 'Default Mode',
+    handler: toggleDefault,
+    shortcut: 'Ctrl+D'
+  }),
+  new MenuItem({
+    text: 'Vim Mode',
+    handler: toggleVim
+  }),
+  ]);
+
+let themes = new Menu([
+  new MenuItem({
+    text: 'default',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'abcdef',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'base16-dark',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'base16-light',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'hopscotch',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'material',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'mbo',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'mdn-like',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'seti',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'the-matrix',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'xq-light',
+    handler: themeHandler
+  }),
+  new MenuItem({
+    text: 'zenburn',
+    handler: themeHandler
+  })
+  ]);
+
+let menu = new Menu([
+  new MenuItem({
+    text: 'File',
+    submenu: file
+  }),
+  new MenuItem({
+    text: 'Settings',
+    submenu: settings
+  }),
+  new MenuItem({
+    text: 'Themes',
+    submenu: themes
+  })
+  ]);
+
+/**
+ * The editor widget tracker provider
+ */
+export
+const editorTrackerProvider = {
+  id: 'jupyter.plugins.editorTracker',
+  provides: EditorTracker,
+  resolve: () => {
+    return tracker;
   }
   }
 };
 };

+ 5 - 1
src/editorwidget/widget.ts

@@ -19,9 +19,12 @@ import {
 } from '../codemirror/widget';
 } from '../codemirror/widget';
 
 
 import {
 import {
-  ABCWidgetFactory, IDocumentModel, IWidgetFactory, IDocumentContext
+  ABCWidgetFactory, IDocumentModel, IDocumentContext
 } from '../docregistry';
 } from '../docregistry';
 
 
+import {
+  tracker
+} from './plugin';
 
 
 /**
 /**
  * The class name added to a dirty widget.
  * The class name added to a dirty widget.
@@ -44,6 +47,7 @@ class EditorWidget extends CodeMirrorWidget {
    */
    */
   constructor(context: IDocumentContext<IDocumentModel>) {
   constructor(context: IDocumentContext<IDocumentModel>) {
     super();
     super();
+    tracker.addWidget(this);
     this.addClass(EDITOR_CLASS);
     this.addClass(EDITOR_CLASS);
     let editor = this.editor;
     let editor = this.editor;
     let model = context.model;
     let model = context.model;