diff --git a/src/NotebookProvider.ts b/src/NotebookProvider.ts index 9ef273c02..ee519f32c 100644 --- a/src/NotebookProvider.ts +++ b/src/NotebookProvider.ts @@ -33,33 +33,73 @@ export class NotebookProvider implements vscode.NotebookSerializer { function parseClojure(content: string): vscode.NotebookCellData[] { const cursor = tokenCursor.createStringCursor(content); const topLevelRanges = cursor.rangesForTopLevelForms().flat(); - if (topLevelRanges.length) { - topLevelRanges[0] = 0; - } - - // grab only the ends of ranges, so we can include all of the file in the notebook - const fullRanges = _.filter(topLevelRanges, (_, index) => { - return index % 2 !== 0; - }); // last range should include end of file - fullRanges[fullRanges.length - 1] = content.length; - - // start of file to end of top level sexp pairs - const allRanges = _.zip(_.dropRight([_.first(topLevelRanges), ...fullRanges], 1), fullRanges); + topLevelRanges.push(content.length); + + const allRanges = _.zip(_.dropRight([0, ...topLevelRanges], 1), topLevelRanges); + + const ranges = allRanges + .map(([start, end], index) => { + const isWhitespace = index % 2 === 0; + const rangeContent = content.substring(start, end); + + if (isWhitespace) { + if (start === end) { + return { + value: '', + kind: vscode.NotebookCellKind.Markup, + languageId: 'markdown', + }; + } + + if (rangeContent.startsWith('\n\n;; ')) { + const startingWhitespace = rangeContent.indexOf('\n;; '); + const endingWhitespace = rangeContent.length - rangeContent.trimEnd().length; + + return { + value: rangeContent.substring(startingWhitespace).trimEnd().replace(/\n;; /g, '\n'), + kind: vscode.NotebookCellKind.Markup, + languageId: 'markdown', + metadata: { asMarkdown: true, startingWhitespace, endingWhitespace }, + }; + } + + return { + value: rangeContent, + kind: vscode.NotebookCellKind.Markup, + languageId: 'markdown', + }; + } else { + return { + value: rangeContent, + kind: vscode.NotebookCellKind.Code, + languageId: 'clojure', + }; + } + }) + .filter((x) => x.value.length); - const ranges = allRanges.map(([start, end]) => { - return { - value: content.substring(start, end), - kind: vscode.NotebookCellKind.Code, - languageId: 'clojure', - }; - }); return ranges; } function writeCellsToClojure(cells: vscode.NotebookCellData[]) { - return cells.map((x) => x.value).join(''); + return cells + .map((x, index) => { + if (x.kind === vscode.NotebookCellKind.Code) { + return x.value; + } else { + if (x.metadata.asMarkdown) { + return ( + '\n'.repeat(x.metadata.startingWhitespace) + + x.value.replace(/\n/g, '\n;; ') + + '\n'.repeat(x.metadata.endingWhitespace) + ); + } + return x.value; + } + }) + .join(''); } export class NotebookKernel { diff --git a/test-data/notebook.clj b/test-data/notebook.clj index 78f747f79..d99f99137 100644 --- a/test-data/notebook.clj +++ b/test-data/notebook.clj @@ -2,6 +2,7 @@ (ns notebook) +"string1" "string" ;; A line comment ;; block @@ -12,7 +13,7 @@ :deeper {:a 1, "foo" :bar, [1 2 3] (vec (range 2000))}}) ;; Line comment, line 1 - +;; ;; Line comment, line 2 (defn foo [] (println "bar"))