From 7fe609bd61d8e32dd7fcc052dd56be92dfb89a87 Mon Sep 17 00:00:00 2001 From: Sami Samhuri Date: Fri, 24 Sep 2010 00:14:29 -0700 Subject: [PATCH] first commit --- LICENSE | 18 +++++++ Readme.md | 1 + lib/index.js | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 23 +++++++++ repl.js | 3 ++ 5 files changed, 180 insertions(+) create mode 100644 LICENSE create mode 100644 Readme.md create mode 100644 lib/index.js create mode 100644 package.json create mode 100755 repl.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..633af2e --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ +Copyright 2009, 2010 Sami Samhuri. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..30404ce --- /dev/null +++ b/Readme.md @@ -0,0 +1 @@ +TODO \ No newline at end of file diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..8ba73d1 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,135 @@ +// +// Copyright 2010 Sami Samhuri @_sjs +// MIT license +// +// github.com/samsonjs/edit-repl +// + +// TODO proper error handling + +var fs = require('fs') + , _repl + +exports.startRepl = function() { + console.log('Commands: edit(), run(), stash(filename), unstash(filename), setEditor(editor)') + // TODO extend the repl context instead, problem is that repl.js:resetContext() isn't exported + // so simple assignments to _repl.context can't survive .clear yet + exports.extend(global) + _repl = require('repl').start() +} + +exports.extend = function(obj) { + var path = require('path') + , spawn = require('child_process').spawn + , sys = require('sys') + , _tmpfile = path.join(process.env['TMPDIR'], 'node-repl-' + process.pid + '.js') + + obj.edit = function(editor) { + editor = editor || process.ENV['EDITOR'] + pausingRepl(function(unpause) { + var fds = [process.openStdin(), process.stdout, process.stdout] + , args = [_tmpfile] + // handle things like 'mate -w' and 'emacsclient --server-file ' + if (editor.match(/\s/)) { + var words = editor.split(/\s+/) + args = words.slice(1).concat(args) + editor = words[0] + } + spawn(editor, args, {customFds: fds}).on('exit', function(code) { + // FIXME figure out why obj.run doesn't work properly here (output is skewed) + if (code === 0) { + runFile(_tmpfile, function() { unpause() }) + } else { + unpause() + } + }) + }) + } + + obj.run = function() { + pausingRepl(function(unpause) { + runFile(_tmpfile, function() { unpause() }) + }) + } + + obj.setEditor = function(editor) { + process.ENV['EDITOR'] = editor + } + + obj.stash = function(dest) { + try { + fs.statSync(_tmpfile) + } catch (e) { + console.log('nothing to stash') + return + } + pausingRepl(function(unpause) { + var read = fs.createReadStream(_tmpfile) + read.on('end', function() { + console.log('stashed') + unpause() + }) + // TODO confirm before overwriting an existing file + sys.pump(read, fs.createWriteStream(dest)) + }) + } + + obj.unstash = function(source) { + try { + fs.statSync(source) + } catch (e) { + console.log('no stash at ' + source) + return + } + pausingRepl(function(unpause) { + var read = fs.createReadStream(source) + read.on('end', function() { + console.log('unstashed') + unpause() + }) + sys.pump(read, fs.createWriteStream(_tmpfile)) + }) + } +} + +function pausingRepl(fn) { + var origPrompt = _repl.prompt || '> ' + _repl.stream.pause() + _repl.rli.enabled = false + _repl.prompt = '' + fn(function() { + _repl.prompt = origPrompt + _repl.rli.enabled = true + _repl.stream.resume() + _repl.displayPrompt() + }) +} + +function runFile(filename, callback) { + var Script = process.binding('evals').Script + , evalcx = Script.runInContext + , read = fs.createReadStream(filename) + , s = '' + read.on('data', function(d) { s += d }) + read.on('end', function() { + // The catchall for errors + try { + // Use evalcx to supply the global context + var ret = evalcx(s, _repl.context, "repl"); + if (ret !== undefined) { + _repl.context._ = ret; + repl.writer(ret) + "\n" + } + } catch (e) { + // On error: Print the error and clear the buffer + if (e.stack) { + _repl.stream.write(e.stack + "\n"); + } else { + _repl.stream.write(e.toString() + "\n"); + } + } + if (callback) callback() + }) +} + +if (require.main === module) exports.startRepl() diff --git a/package.json b/package.json new file mode 100644 index 0000000..c566d2d --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ "name" : "edit-repl" +, "description" : "Edit code in the repl using a real text editor" +, "version" : "0.0.1" +, "homepage" : "http://samhuri.net/node/edit-repl" +, "author" : "Sami Samhuri (http://blog.izs.me)" +, "repository" : + { "type" : "git" + , "url" : "http://github.com/samsonjs/edit-repl.git" + } +, "bugs" : + { "mail" : "sami.samhuri+edit-repl@gmail.com" + , "web" : "http://github.com/samsonjs/edit-repl/issues" + } +, "directories" : { "lib" : "./lib" } +, "bin" : { "node-edit-repl" : "./repl.js" } +, "main" : "./lib/index" +, "engines" : { "node" : ">=0.2.0" } +, "licenses" : + [ { "type" : "MIT" + , "url" : "http://github.com/samsonjs/edit-repl/raw/master/LICENSE" + } + ] +} \ No newline at end of file diff --git a/repl.js b/repl.js new file mode 100755 index 0000000..8c39f37 --- /dev/null +++ b/repl.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +require('./lib/index').startRepl()