UNPKG

vorpal

Version:

Node's first framework for building immersive CLI apps.

168 lines (138 loc) 3.87 kB
'use strict'; var _ = require('lodash'); var LocalStorage = require('node-localstorage').LocalStorage; // Number of command histories kept in persistent storage var HISTORY_SIZE = 50; var DEFAULT_STORAGE_PATH = './.cmd_history'; var History = function () { this._storageKey = undefined; // Prompt Command History // Histctr moves based on number of times 'up' (+= ctr) // or 'down' (-= ctr) was pressed in traversing // command history. this._hist = []; this._histCtr = 0; // When in a 'mode', we reset the // history and store it in a cache until // exiting the 'mode', at which point we // resume the original history. this._histCache = []; this._histCtrCache = 0; }; /** * Initialize the history with local storage data * Called from setId when history id is set */ History.prototype._init = function () { if (!this._storageKey) { return; } // Load history from local storage var persistedHistory = JSON.parse(this._localStorage.getItem(this._storageKey)); if (_.isArray(persistedHistory)) { Array.prototype.push.apply(this._hist, persistedHistory); } }; /** * Set id for this history instance. * Calls init internally to initialize * the history with the id. */ History.prototype.setId = function (id) { // Initialize a localStorage instance with default // path if it is not initialized if (!this._localStorage) { this._localStorage = new LocalStorage(DEFAULT_STORAGE_PATH); } this._storageKey = 'cmd_history' + id; this._init(); }; /** * Initialize a local storage instance with * the path if not already initialized. * * @param path */ History.prototype.setStoragePath = function (path) { if (!this._localStorage) { this._localStorage = new LocalStorage(path); } }; /** * Get previous history. Called when up is pressed. * * @return {String} */ History.prototype.getPreviousHistory = function () { this._histCtr++; this._histCtr = (this._histCtr > this._hist.length) ? this._hist.length : this._histCtr; return this._hist[this._hist.length - (this._histCtr)]; }; /** * Get next history. Called when down is pressed. * * @return {String} */ History.prototype.getNextHistory = function () { this._histCtr--; // Return empty prompt if the we dont have any history to show if (this._histCtr < 1) { this._histCtr = 0; return ''; } return this._hist[this._hist.length - (this._histCtr)]; }; /** * A new command was submitted. Called when enter is pressed and the prompt is not empty. * * @param cmd */ History.prototype.newCommand = function (cmd) { this._hist.push(cmd); this._histCtr = 0; // Only persist history when not in mode if (this._storageKey && !this._inMode) { var persistedHistory = this._hist; var historyLen = this._hist.length; if (historyLen > HISTORY_SIZE) { persistedHistory = this._hist.slice(historyLen - HISTORY_SIZE - 1, historyLen - 1); } // Add to local storage this._localStorage.setItem(this._storageKey, JSON.stringify(persistedHistory)); } }; /** * Called when entering a mode */ History.prototype.enterMode = function () { // Reassign the command history to a // cache, replacing it with a blank // history for the mode. this._histCache = _.clone(this._hist); this._histCtrCache = parseFloat(this._histCtr); this._hist = []; this._histCtr = 0; this._inMode = true; }; /** * Called when exiting a mode */ History.prototype.exitMode = function () { this._hist = this._histCache; this._histCtr = this._histCtrCache; this._histCache = []; this._histCtrCache = 0; this._inMode = false; }; /** * Clears the command history * (Currently only used in unit test) */ History.prototype.clear = function () { if (this._storageKey) { this._localStorage.removeItem(this._storageKey); } }; module.exports = History;