/** * LiveEvaluation.ts */ import { EventEmitter } from "events" import * as os from "os" import { INeovimInstance } from "./../NeovimInstance" import { PluginManager } from "./../Plugins/PluginManager" /// import * as _ from "lodash" _.take([1, 2, 3], 2) /// /** * Implementation of the LiveEvaluation service */ export class LiveEvaluation extends EventEmitter { private _neovimInstance: INeovimInstance private _pluginManager: PluginManager private _keyToBlock: { [key: string]: ILiveCodeBlock } = {} private _bufferToBlocks: { [buffer: string]: ILiveCodeBlock[] } = {} constructor(neovimInstance: INeovimInstance, pluginManager: PluginManager) { super() this._neovimInstance = neovimInstance this._pluginManager = pluginManager this._neovimInstance.on("buffer-update", (context: Oni.EventContext, lines: string[]) => { const currentBlocks = getLiveCodeBlocks(lines) this._bufferToBlocks[context.bufferFullPath] = currentBlocks currentBlocks.forEach((b) => { const code = b.codeBlock.join(os.EOL) const key = context.bufferFullPath + "__" + b.startLine // If there was a previous result, bring it over if (this._keyToBlock[key]) { b.result = this._keyToBlock[key].result } this._keyToBlock[key] = b this._pluginManager.requestEvaluateBlock(key, context.bufferFullPath, code) }) this.emit("evaluate-block-result", context.bufferFullPath, currentBlocks) }) this._pluginManager.on("evaluate-block-result", (res: any) => { const id = res.id const codeBlock = this._keyToBlock[id] if (!codeBlock) { return } codeBlock.result = res const fileName = res.fileName this.emit("evaluate-block-result", fileName, this._bufferToBlocks[fileName]) }) } } export interface ILiveCodeBlock { endLine: number startLine: number codeBlock: string[] result?: Oni.Plugin.EvaluationResult } function getLiveCodeBlocks(buffer: string[]): ILiveCodeBlock[] { let isInLiveBlock = false const result = buffer.reduce((prev: ILiveCodeBlock[], curr: string, idx: number) => { if (!isInLiveBlock) { if (curr.indexOf("") >= 0 && curr.indexOf("///") >= 0) { isInLiveBlock = true return prev.concat([{ startLine: idx + 1, codeBlock: [], endLine: -1 }]) } } else { // const currentCodeBlock = prev[prev.length - 1] if (curr.indexOf("") >= 0 && curr.indexOf("///") >= 0) { isInLiveBlock = false prev[prev.length - 1].endLine = idx + 1 return prev } else { prev[prev.length - 1].codeBlock.push(curr) } } return prev }, []) return result }