Bläddra i källkod

#1357 Respect markdown code boundaries for code execution

https://github.com/jupyterlab/jupyterlab/issues/1357
Vineet Gorhe 8 år sedan
förälder
incheckning
570a3c0a62
1 ändrade filer med 127 tillägg och 8 borttagningar
  1. 127 8
      packages/fileeditor-extension/src/index.ts

+ 127 - 8
packages/fileeditor-extension/src/index.ts

@@ -96,6 +96,21 @@ function activate(app: JupyterLab, registry: IDocumentRegistry, restorer: ILayou
     shell
   });
 
+  const markdownMarkers: string[] = ["```", "~~~~", "`"]
+  const markdownExtensions: string[] = [
+    '.markdown',
+    '.mdown',
+    '.mkdn',
+    '.md',
+    '.mkd',
+    '.mdwn',
+    '.mdtxt',
+    '.mdtext',
+    '.text',
+    '.txt',
+    '.Rmd'
+  ];
+
   let lineNumbers = true;
   let wordWrap = true;
 
@@ -174,6 +189,95 @@ function activate(app: JupyterLab, registry: IDocumentRegistry, restorer: ILayou
     return tracker.currentWidget !== null;
   }
 
+
+  class CodeSnippet {
+    startLine: number;
+    endLine: number;
+    code: string;
+    constructor(startLine: number) {
+      this.startLine = startLine;
+      this.code = "";
+    }
+  }
+
+  function findNextMarker(text: string) {
+    for (let marker of markdownMarkers) {
+      const index = text.indexOf(marker);
+      if (index > -1) {
+        return marker;
+      }
+    }
+    return '';
+  }
+  /**
+   * Construct all code snippets from current text
+   * (this could be potentially optimized if we can cache and detect differences)
+   */
+  function findCodeSnippets(): CodeSnippet[] {
+    let widget = tracker.currentWidget;
+    if (!widget) {
+      return [];
+    }
+    const lines = widget.editor.model.value.text.split("\n");
+    const codeSnippets: CodeSnippet[] = [];
+    var currentCode = null;
+    for (var lineIndex = 0; lineIndex < lines.length; lineIndex++) {
+      const line = lines[lineIndex];
+      const marker = findNextMarker(line);
+      const lineContainsMarker = marker != '';
+      const constructingSnippet = currentCode != null;
+      //skip this line if it is not part of any code snippet and doesn't contain a marker
+      if (!lineContainsMarker && !constructingSnippet) {
+        continue;
+      }
+
+      //check if we are already constructing a code snippet
+      if (!constructingSnippet) {
+        //start constructing
+        currentCode = new CodeSnippet(lineIndex);
+
+        //check whether this is a single line code snippet
+        const firstIndex = line.indexOf(marker);
+        const lastIndex = line.lastIndexOf(marker);
+        const isSingleLine = firstIndex != lastIndex
+        if (isSingleLine) {
+          currentCode.code = line.substring(firstIndex + marker.length, lastIndex);
+          currentCode.endLine = lineIndex;
+          codeSnippets.push(currentCode);
+          currentCode = null;
+        } else {
+          currentCode.code = line.substring(firstIndex + marker.length);
+        } 
+      } else {
+        //already constructing
+        if (lineContainsMarker) {
+          currentCode.code += "\n" + line.substring(0, line.indexOf(marker));
+          currentCode.endLine = lineIndex;
+          codeSnippets.push(currentCode);
+          currentCode = null;
+        } else {
+          currentCode.code += "\n" + line;
+        }
+      }
+    }
+    return codeSnippets;
+  }
+
+  /** To detect if there is no current selection */
+  function hasSelection(): boolean {
+    let widget = tracker.currentWidget;
+    if (!widget) {
+      return false;
+    }
+    const editor = widget.editor;
+    const selection = editor.getSelection();
+    if (selection.start.column == selection.end.column &&
+      selection.start.line == selection.end.line) {
+      return false;
+    }
+    return true;
+  }
+
   commands.addCommand(CommandIDs.lineNumbers, {
     execute: toggleLineNums,
     isEnabled: hasWidget,
@@ -211,18 +315,33 @@ function activate(app: JupyterLab, registry: IDocumentRegistry, restorer: ILayou
       if (!widget) {
         return;
       }
-      // Get the selected code from the editor.
+
+      var code = ""
       const editor = widget.editor;
-      const selection = editor.getSelection();
-      const start = editor.getOffsetAt(selection.start);
-      const end = editor.getOffsetAt(selection.end);
-      let targetText = editor.model.value.text.substring(start, end);
-      if (start == end) {
-        targetText = editor.getLine(selection.start.line); 
+      const extension = widget.context.path.substring(widget.context.path.lastIndexOf("."));
+      if (!hasSelection() && markdownExtensions.indexOf(extension) > -1) {
+        var snippets = findCodeSnippets();
+        for (let codeSnippet of snippets) {
+          if (codeSnippet.startLine <= editor.getSelection().start.line &&
+            editor.getSelection().start.line <= codeSnippet.endLine) {
+            code = codeSnippet.code;
+            break;
+          }
+        }
+      } else {
+        // Get the selected code from the editor.
+        const selection = editor.getSelection();
+        const start = editor.getOffsetAt(selection.start);
+        const end = editor.getOffsetAt(selection.end);
+        code = editor.model.value.text.substring(start, end);
+        if (start == end) {
+          code = editor.getLine(selection.start.line); 
+        }
       }
+
       const options: JSONObject = {
         path: widget.context.path,
-        code: targetText,
+        code: code,
         activate: false
       };
       // Advance cursor to the next line.