Adding support for .node_history and .noderc.js in $HOME and `pwd` #3178

Closed
wants to merge 2 commits into
from
View
@@ -25,7 +25,7 @@
// * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
// * http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
-var kHistorySize = 30;
+var kHistorySize = 100;
var util = require('util');
var inherits = require('util').inherits;
@@ -102,6 +102,9 @@ function Interface(input, output, completer, terminal) {
self._refreshLine();
}
+ this.history = [];
+ this.historyIndex = -1;
+
if (!this.terminal) {
input.on('data', ondata);
input.on('end', onend);
@@ -128,9 +131,6 @@ function Interface(input, output, completer, terminal) {
// Cursor position on the line.
this.cursor = 0;
- this.history = [];
- this.historyIndex = -1;
-
output.on('resize', onresize);
self.once('close', function() {
input.removeListener('keypress', onkeypress);
@@ -507,6 +507,17 @@ Interface.prototype._deleteLineRight = function() {
this._refreshLine();
};
+Interface.prototype.getHistory = function() {
+ return this.history;
+};
+
+Interface.prototype.setHistory = function(history) {
+ this.history = history.concat();
+ this.historyIndex = -1;
+ if (this.history.length > kHistorySize) {
+ this.history.splice(kHistorySize, Infinity);
+ }
+};
Interface.prototype.clearLine = function() {
this._moveCursor(+Infinity);
View
@@ -386,6 +386,48 @@ REPLServer.prototype.resetContext = function() {
this.emit('reset', this.context);
};
+REPLServer.prototype.loadContext = function(file) {
+ var Module = require('module');
+ var context = Module._load(file);
+ if (context && typeof context === 'object') {
+ for (var key in context) {
+ if (context.hasOwnProperty(key)) {
+ this.context[key] = context[key];
+ }
+ }
+ }
+};
@teramako

teramako Nov 7, 2012

ensure the file exists and set all exported properties

REPLServer.prototype.loadContext = function(file) {
  var self = this,
      Module = require('module');
  fs.exists(file, function(exists) {
    if (!exists) return;
    var context = Module._load(file);
    if (context && typeof context === 'object') {
      Object.getOwnPropertyNames(context).forEach(function(key) {
        Object.defineProperty(self.context, key, Object.getOwnPropertyDescriptor(context, key));
      });
    }
  });
};
@regality

regality Oct 3, 2013

the context file not being found is handled in src/node.js

+
+REPLServer.prototype.setHistory = function(history) {
+ this.rli.setHistory(history);
+};
+
+REPLServer.prototype.getHistory = function() {
+ return this.rli.getHistory();
+};
+
+REPLServer.prototype.loadHistory = function(file, callback) {
+ var self = this;
+ callback = callback || function() {};
+ if (!file) return callback();
+ fs.readFile(file, function(err, data) {
+ if (err) return callback(err);
+ data = data.toString();
+ if (!data) return callback();
+ var history = data.split('\n').reverse();
+ self.setHistory(history);
+ callback();
+ });
+};
+
+REPLServer.prototype.saveHistory = function(file, callback) {
+ if (!file) return callback();
+ var history = this.getHistory().reverse().join('\n');
+ fs.writeFile(file, history, function(err) {
+ callback(err);
+ });
+};
+
REPLServer.prototype.displayPrompt = function(preserveCursor) {
var prompt = this.prompt;
if (this.bufferedCommand.length) {
View
@@ -125,6 +125,7 @@
} else {
var Module = NativeModule.require('module');
+ var path = NativeModule.require('path');
// If -i or --interactive were passed, or stdin is a TTY.
if (process._forceRepl || NativeModule.require('tty').isatty(0)) {
@@ -140,8 +141,35 @@
opts.useColors = false;
}
var repl = Module.requireRepl().start(opts);
+
+ var home = (process.platform === 'win32' ?
+ process.env.HOMEDRIVE + process.env.HOMEPATH :
+ process.env.HOME);
+ if (home) {
+ var noderc = path.join(home, '.noderc.js');
+ var nodeHistory = path.join(home, '.node_history');
+ }
+ var pwd = path.resolve('.');
+ var pwdrc = path.join(pwd, '.noderc.js');
+ [noderc, pwdrc].forEach(function(file) {
+ try {
+ repl.loadContext(file);
+ } catch (e) {
+ if (e.code !== 'MODULE_NOT_FOUND') {
+ // rethrow any errors generated from noderc
+ throw e;
+ }
+ }
+ });
+
+ repl.loadHistory(nodeHistory, function(err) {
+ // if (err) console.log(err.stack);
+ });
repl.on('exit', function() {
- process.exit();
+ repl.saveHistory(nodeHistory, function(err) {
+ // if (err) console.log(err.stack);
+ process.exit();
+ });
});
} else {
View
@@ -0,0 +1,22 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+exports.foo = 'bar';
@@ -0,0 +1,34 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+var common = require('../common'),
+ path = require('path'),
+ assert = require('assert'),
+ fs = require('fs'),
+ repl = require('repl').start('');
+
+var nodercFile = path.join(common.fixturesDir, 'context.js');
+
+repl.loadContext(nodercFile);
+
+assert.equal(repl.context.foo, 'bar');
+
+process.exit();
@@ -0,0 +1,56 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+var common = require('../common'),
+ path = require('path'),
+ assert = require('assert'),
+ repl = require('repl').start('');
+
+var history = [
+ 'never gonna give you up',
+ 'never gonna let you down',
+ 'never gonna gonna run around and desert you',
+ 'never gonna make you cry',
+ 'never gonna say goodbye',
+ 'never gonna tell a lie and hurt you'
+];
+
+var historyFile = path.join(common.tmpDir, 'history');
+
+saveHistory();
+
+function saveHistory() {
+ repl.setHistory(history);
+
+ repl.saveHistory(historyFile, function(err) {
+ if (err) throw err;
+ loadHistory();
+ });
+}
+
+function loadHistory() {
+ repl.setHistory([]);
+ repl.loadHistory(historyFile, function(err) {
+ if (err) throw err;
+ assert.deepEqual(repl.rli.history, history);
+ process.exit();
+ });
+}