coc.nvim 插件,放在 .vim/coc-extensions
目录下即可使用。
右侧打开窗口显示执行代码的结果,保存后自动重新执行。
stderr 和 stdout 出现顺序可能会错,暂时不支持 ansi 解析,可通过使用 strip-ansi 模块去掉。
const {Uri, commands, workspace, windw, Mutex} = require('coc.nvim') const path = require('path') const programMap = { Javascript: 'node', typescript: 'ts-node', python: 'python' } let global_id = 0 exports.activate = async cOntext=> { const {nvim, cwd} = workspace // bufnr => Task const taskMap = new Map() let statusItem = window.createStatusBarItem(0, {progress: true}) context.subscriptions.push(statusItem) const executeFile = async (doc, create) => { let uri = doc.uri let relPath = path.relative(cwd, Uri.parse(uri).fsPath) let bufname = `__coc_execute_${doc.bufnr}__` let task = taskMap.get(doc.bufnr) if (task) { task.dispose() taskMap.delete(doc.bufnr) } statusItem.hide() let winnr = await nvim.call('bufwinnr', [bufname]) if (winnr == -1 && !create) return if (winnr == -1) { nvim.pauseNotification() nvim.command(`belowright vs ${bufname}`) nvim.command(`setl buftype=nofile`) nvim.command(`setl cOnceallevel=0`) nvim.command(`setl norelativenumber`) await nvim.resumeNotification() winnr = await nvim.call('winnr', []) await nvim.command('wincmd p') } else { // clear buffer await nvim.command(`silent call deletebufline('${bufname}', 1, '$')`) } let bufId = await nvim.call('bufnr', [bufname]) let buf = nvim.createBuffer(bufId) let t = workspace.createTask(`execute-${global_id}`) global_id = global_id + 1 let cmd = programMap[doc.filetype] // start with options let succeed = await t.start({cwd, cmd, args: [relPath]}) if (!succeed) { window.showErrorMessage(`Command failed to start: ${cmd} ${relPath}`) return } statusItem.text = `${cmd} ${relPath}` statusItem.show() taskMap.set(doc.bufnr, t) t.onExit(code => { statusItem.hide() taskMap.delete(doc.bufnr) if (code != 0) { window.showErrorMessage(`${cmd} exit with code: ${code}`) } }) let empty = true let appendLines = async lines => { if (empty) { empty = false await buf.setLines(lines, {start: 0, end: -1, strictIndexing: false}) } else { await nvim.call('appendbufline', [buf.id, '$', lines]) } } let mutex = new Mutex() t.onStderr(async lines => { let replace = empty let release = await mutex.acquire() try { let len = await buf.length await appendLines(lines) await buf.highlightRanges('coc-execute', 'WarningMsg', [{ start: {line: (replace ? len - 1 : len), character: 0}, end: {line: len + lines.length, character: 0} }]) if (workspace.isVim) nvim.command('redraw', true) } catch (e) { window.showErrorMessage(e.message) } release() }) t.onStdout(async lines => { let release = await mutex.acquire() try { await appendLines(lines) if (workspace.isVim) nvim.command('redraw', true) } catch (e) { window.showErrorMessage(e.message) } release() }) } const execute = async () => { let doc = await workspace.document let program = programMap[doc.filetype] if (!program) { window.showErrorMessage(`filetype not supported`) return } await executeFile(doc, true) } context.subscriptions.push(workspace.onDidSaveTextDocument(async e => { let doc = workspace.getDocument(e.uri) if (!taskMap.has(doc.bufnr)) return await executeFile(doc, false) })) context.subscriptions.push({ dispose: () => { for (let task of taskMap.values()) { task.dispose() } } }) context.subscriptions.push( commands.registerCommand('execute.currentFile', execute) ) }
仅供参考
![]() | 1 IgniteWhite 2021-03-28 21:26:59 +08:00 给大佬点赞 |
![]() | 2 chemzqm OP 多了一行 `if (!taskMap.has(doc.bufnr)) return` |
![]() | 3 yuuko 2021-03-29 17:20:37 +08:00 我这里 nvim.pauseNotification() nvim.command(`belowright vs ${bufname}`) 要改成 await nvim.command(`belowright vs ${bufname}`) nvim.pauseNotification() |