Bladeren bron

work in progress

A. Darian 8 jaren geleden
bovenliggende
commit
4a27cda413

+ 1 - 0
package.json

@@ -5,6 +5,7 @@
   "main": "lib/index.js",
   "typings": "lib/index.d.ts",
   "dependencies": {
+    "ansi-to-html": "^0.4.1",
     "codemirror": "^5.11.0",
     "diff-match-patch": "^1.0.0",
     "file-loader": "^0.8.5",

+ 49 - 15
src/notebook/console/model.ts

@@ -46,6 +46,13 @@ import {
   RawCellModel, isRawCellModel, MetadataCursor, IMetadataCursor
 } from '../cells/model';
 
+import {
+  MimeBundle
+} from '../notebook';
+
+declare var require: any;
+const Filter = require('ansi-to-html');
+
 
 /**
  * The default console kernelspec metadata.
@@ -62,6 +69,7 @@ const DEFAULT_LANG_INFO = {
   name: 'unknown'
 }
 
+
 /**
  * The definition of a model object for a console tooltip widget.
  */
@@ -72,10 +80,15 @@ interface ITooltipModel {
    */
   change: ITextChange;
 
+  /**
+   * The current line of code (which was submitted to API for inspection).
+   */
+  currentLine: string;
+
   /**
    * The API inspect request data payload.
    */
-  bundle: { [mimetype: string]: string };
+  bundle: MimeBundle;
 }
 
 
@@ -420,20 +433,27 @@ class ConsoleModel implements IConsoleModel {
       return;
     }
 
-    let pendingInspect = ++this._pendingInspect;
+    // If final character of current line isn't a whitespace character, bail.
+    let currentLine = args.newValue.split('\n')[args.line];
+    if (!currentLine.match(/\S$/)) {
+      this.tooltip = null;
+      return;
+    }
 
-    this._session.kernel.inspect({
-      code: args.newValue,
-      cursor_pos: args.ch,
-      detail_level: 0
-    }).then((value: IInspectReply) => {
-      if (pendingInspect !== this._pendingInspect || !value.found) {
-        return;
-      }
-      console.log('value', value)
-      let change = args;
-      let bundle = value.data;
-      this.tooltip = { change, bundle };
+    let pendingInspect = ++this._pendingInspect;
+    let contents = {code: currentLine, cursor_pos: args.ch, detail_level: 0};
+
+    this._session.kernel.inspect(contents).then((value: IInspectReply) => {
+      // If a newer text change has created a pending request, bail.
+      if (pendingInspect !== this._pendingInspect) return;
+      // Tooltip request failures or negative results fail silently.
+      if (value.status !== 'ok' || !value.found) return;
+      console.log('value', value);
+      this.tooltip = {
+        change: args,
+        currentLine: currentLine,
+        bundle: Private.formatInspectReply(value.data)
+      };
     });
   }
 
@@ -546,7 +566,7 @@ namespace Private {
     });
   }
 
-  /*
+  /**
    * Handle a change to the model session.
    */
   export
@@ -556,4 +576,18 @@ namespace Private {
     kernelChanged(model);
   }
 
+  /**
+   * Format the IInspectReply plain text data.
+   */
+  export
+  function formatInspectReply(bundle: MimeBundle): MimeBundle {
+    let textMime = 'text/plain';
+    let textHTML = 'text/html';
+    if (!bundle[textMime]) return bundle;
+    // Add a 'text/html' formatted version of the plain text.
+    let filter = new Filter();
+    bundle[textHTML] = `<pre>${filter.toHtml(bundle[textMime])}</pre>`;
+    return bundle;
+  }
+
 }

+ 14 - 20
src/notebook/console/widget.ts

@@ -57,15 +57,6 @@ const CONSOLE_PANEL = 'jp-Console-panel';
  */
 const BANNER_CLASS = 'jp-Console-banner';
 
-/**
- * The width of tooltips.
- */
-const TOOLTIP_WIDTH = 250;
-
-/**
- * The height of tooltips.
- */
-const TOOLTIP_HEIGHT = 175;
 
 /**
  * A panel which contains a toolbar and a console.
@@ -138,7 +129,8 @@ class ConsoleWidget extends Widget {
    * @returns A ConsoleTooltip widget.
    */
   static createTooltip(top: number, left: number): ConsoleTooltip {
-    let rect = { top, left, width: TOOLTIP_WIDTH, height: TOOLTIP_HEIGHT };
+    // Null values are automatically set to 'auto'.
+    let rect = { top, left, width: null as any, height: null as any };
     return new ConsoleTooltip(rect as ClientRect);
   }
 
@@ -258,25 +250,27 @@ class ConsoleWidget extends Widget {
 
       // Offset the height of the tooltip by the height of cursor characters.
       top += model.change.chHeight;
-      // If the last character is a word character, offset its width;
-      if (model.change.newValue.match(/\w$/)) left -= model.change.chWidth;
+      // Offset the width of the tooltip by the width of cursor characters.
+      left -= model.change.chWidth;
 
-      let rect = {top, left, width: TOOLTIP_WIDTH, height: TOOLTIP_HEIGHT};
+      let rect = {top, left, width: null as any, height: null as any};
+      // Account for 1px border on top and bottom.
+      let maxHeight = window.innerHeight - top - 2;
+      // Account for 1px border on both sides.
+      let maxWidth = window.innerWidth - left - 2;
 
-      if (this._tooltip) {
-        this._tooltip.rect = rect as ClientRect;
-      } else {
+      if (!this._tooltip) {
         this._tooltip = constructor.createTooltip(top, left);
         this._tooltip.reference = this;
         this._tooltip.attach(document.body);
       }
 
       let content = this._rendermime.render(model.bundle) || new Widget();
+      this._tooltip.rect = rect as ClientRect;
       this._tooltip.content = content;
-
-      if (this._tooltip.isHidden) {
-        this._tooltip.show();
-      }
+      this._tooltip.node.style.maxHeight = maxHeight + 'px';
+      this._tooltip.node.style.maxWidth = maxWidth + 'px';
+      if (this._tooltip.isHidden) this._tooltip.show();
 
       return;
     }

+ 2 - 0
src/notebook/theme.css

@@ -362,10 +362,12 @@
 
 
 .jp-ConsoleTooltip {
+  display: inline-block;
   background: #FFFFCA;
   border: 1px solid black;
 }
 
 .jp-ConsoleTooltip pre {
   margin: 0;
+  padding: 2px;
 }

+ 1 - 0
src/notebook/typings.d.ts

@@ -3,3 +3,4 @@
 /// <reference path="../typings/codemirror/codemirror.d.ts"/>
 /// <reference path="../typings/diff-match-patch/diff-match-patch.d.ts"/>
 /// <reference path="../typings/mathjax/mathjax.d.ts"/>
+/// <reference path="../typings/ansi-to-html/ansi-to-html.d.ts"/>

+ 17 - 0
typings/ansi-to-html/ansi-to-html.d.ts

@@ -0,0 +1,17 @@
+// Type definitions for ansi-to-html
+// Project: https://github.com/rburns/ansi-to-html
+
+declare class Filter {
+  constructor(options?: {
+    fg?: string;
+    bg?: string;
+    newline?: boolean;
+    escapeXML?: boolean;
+    stream?: boolean;
+  });
+  toHtml(input: string): string;
+}
+
+declare module "ansi-to-html" {
+    export = Filter;
+}