Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,21 @@ inquirer.prompt([{

See also [example.js](https://github.com/nicksrandall/inquierer-directory/blob/master/example.js) for a working example

To select files and directories.
```javascript
//registering it as type file allows files to be selected.
inquirer.registerPrompt('file', require('inquirer-directory'));
inquirer.prompt([{
type: 'file',
name: 'from',
message: 'Where you like to put this component?',
basePath: './src'
}]).then(function(answers) {
// (answers.from is the path chosen)
});
```


## License

MIT
18 changes: 18 additions & 0 deletions example-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Directory prompt example
*/

"use strict";
var inquirer = require("inquirer");
inquirer.registerPrompt('file', require('./index'));

inquirer.prompt([
{
type: "file",
name: "path",
message: "In what directory would like to perform this action?",
basePath: "./node_modules"
}
], function( answers ) {
console.log( JSON.stringify(answers, null, " ") );
});
96 changes: 53 additions & 43 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ var BACK = "go back a directory";
*/

function Prompt() {
Base.apply( this, arguments );
Base.apply(this, arguments);

if (!this.opt.basePath) {
this.throwParamError("basePath");
}

this.includeFiles = this.opt.type === 'file';
this.depth = 0;
this.currentPath = path.isAbsolute(this.opt.basePath) ? path.resolve(this.opt.basePath) : path.resolve(process.cwd(), this.opt.basePath);
this.createChoices = this.createChoices.bind(this);
this.opt.choices = new Choices(this.createChoices(this.currentPath), this.answers);
this.selected = 0;

Expand All @@ -52,7 +53,8 @@ function Prompt() {

this.paginator = new Paginator();
}
util.inherits( Prompt, Base );

util.inherits(Prompt, Base);


/**
Expand All @@ -61,7 +63,7 @@ util.inherits( Prompt, Base );
* @return {this}
*/

Prompt.prototype._run = function( cb ) {
Prompt.prototype._run = function (cb) {
var self = this;
self.searchMode = false;
this.done = cb;
Expand Down Expand Up @@ -105,23 +107,23 @@ Prompt.prototype._run = function( cb ) {
}
return self.searchTerm;
})
.takeUntil(done$)
.doOnCompleted(function() {
self.searchMode = false;
self.render();
return false;
});
.takeUntil(done$)
.doOnCompleted(function () {
self.searchMode = false;
self.render();
return false;
});
}).share();

var outcome = this.handleSubmit(events.line);
outcome.drill.forEach( this.handleDrill.bind(this) );
outcome.back.forEach( this.handleBack.bind(this) );
keyUps.takeUntil( outcome.done ).forEach( this.onUpKey.bind(this) );
keyDowns.takeUntil( outcome.done ).forEach( this.onDownKey.bind(this) );
keyMinus.takeUntil( outcome.done ).forEach( this.handleBack.bind(this) );
events.keypress.takeUntil( outcome.done ).forEach( this.hideKeyPress.bind(this) );
searchTerm.takeUntil( outcome.done ).forEach( this.onKeyPress.bind(this) );
outcome.done.forEach( this.onSubmit.bind(this) );
outcome.drill.forEach(this.handleDrill.bind(this));
outcome.back.forEach(this.handleBack.bind(this));
keyUps.takeUntil(outcome.done).forEach(this.onUpKey.bind(this));
keyDowns.takeUntil(outcome.done).forEach(this.onDownKey.bind(this));
keyMinus.takeUntil(outcome.done).forEach(this.handleBack.bind(this));
events.keypress.takeUntil(outcome.done).forEach(this.hideKeyPress.bind(this));
searchTerm.takeUntil(outcome.done).forEach(this.onKeyPress.bind(this));
outcome.done.forEach(this.onSubmit.bind(this));

// Init the prompt
cliCursor.hide();
Expand All @@ -136,21 +138,21 @@ Prompt.prototype._run = function( cb ) {
* @return {Prompt} self
*/

Prompt.prototype.render = function() {
Prompt.prototype.render = function () {
// Render question
var message = this.getQuestion();

if ( this.firstRender ) {
message += chalk.dim( "(Use arrow keys)" );
if (this.firstRender) {
message += chalk.dim("(Use arrow keys)");
}


// Render choices or answer depending on the state
if ( this.status === "answered" ) {
message += chalk.cyan( path.relative(this.opt.basePath, this.currentPath) );
if (this.status === "answered") {
message += chalk.cyan(path.relative(this.opt.basePath, this.currentPath));
} else {
message += chalk.bold("\n Current directory: ") + this.opt.basePath + "/" + chalk.cyan(path.relative(this.opt.basePath, this.currentPath));
var choicesStr = listRender(this.opt.choices, this.selected );
var choicesStr = listRender(this.opt.choices, this.selected);
message += "\n" + this.paginator.paginate(choicesStr, this.selected, this.opt.pageSize);
}
if (this.searchMode) {
Expand All @@ -171,10 +173,13 @@ Prompt.prototype.render = function() {
Prompt.prototype.handleSubmit = function (e) {
var self = this;
var obx = e.map(function () {
return self.opt.choices.getChoice( self.selected ).value;
return self.opt.choices.getChoice(self.selected).value;
}).share();

var done = obx.filter(function (choice) {
if (self.includeFiles && !fs.lstatSync(self.currentPath).isDirectory()){
return true;
}
return choice === CHOOSE;
}).take(1);

Expand All @@ -183,6 +188,9 @@ Prompt.prototype.handleSubmit = function (e) {
}).takeUntil(done);

var drill = obx.filter(function (choice) {
if (self.includeFiles && !fs.lstatSync(self.currentPath).isDirectory()){
return false;
}
return choice !== BACK && choice !== CHOOSE;
}).takeUntil(done);

Expand All @@ -197,9 +205,9 @@ Prompt.prototype.handleSubmit = function (e) {
* when user selects to drill into a folder (by selecting folder name)
*/
Prompt.prototype.handleDrill = function () {
var choice = this.opt.choices.getChoice( this.selected );
this.depth++;
var choice = this.opt.choices.getChoice(this.selected);
this.currentPath = path.join(this.currentPath, choice.value);
this.depth++;
this.opt.choices = new Choices(this.createChoices(this.currentPath), this.answers);
this.selected = 0;
this.render();
Expand All @@ -210,7 +218,7 @@ Prompt.prototype.handleDrill = function () {
*/
Prompt.prototype.handleBack = function () {
if (this.depth > 0) {
var choice = this.opt.choices.getChoice( this.selected );
var choice = this.opt.choices.getChoice(this.selected);
this.depth--;
this.currentPath = path.dirname(this.currentPath);
this.opt.choices = new Choices(this.createChoices(this.currentPath), this.answers);
Expand All @@ -222,54 +230,54 @@ Prompt.prototype.handleBack = function () {
/**
* when user selects "choose this folder"
*/
Prompt.prototype.onSubmit = function(value) {
Prompt.prototype.onSubmit = function (value) {
this.status = "answered";

// Rerender prompt
this.render();

this.screen.done();
cliCursor.show();
this.done( path.relative(this.opt.basePath, this.currentPath) );
this.done(path.relative(this.opt.basePath, this.currentPath));
};


/**
* When user press a key
*/
Prompt.prototype.hideKeyPress = function() {
Prompt.prototype.hideKeyPress = function () {
if (!this.searchMode) {
this.render();
}
};

Prompt.prototype.onUpKey = function() {
Prompt.prototype.onUpKey = function () {
var len = this.opt.choices.realLength;
this.selected = (this.selected > 0) ? this.selected - 1 : len - 1;
this.render();
};

Prompt.prototype.onDownKey = function() {
Prompt.prototype.onDownKey = function () {
var len = this.opt.choices.realLength;
this.selected = (this.selected < len - 1) ? this.selected + 1 : 0;
this.render();
};

Prompt.prototype.onSlashKey = function(e) {
Prompt.prototype.onSlashKey = function (e) {
this.render();
};

Prompt.prototype.onKeyPress = function(e) {
Prompt.prototype.onKeyPress = function (e) {
var index = findIndex.call(this, this.searchTerm);
if (index >= 0) {
this.selected = index;
}
this.render();
};

function findIndex (term) {
function findIndex(term) {
var item;
for (var i=0; i < this.opt.choices.realLength; i++) {
for (var i = 0; i < this.opt.choices.realLength; i++) {
item = this.opt.choices.realChoices[i].name.toLowerCase();
if (item.indexOf(term) === 0) {
return i;
Expand All @@ -282,7 +290,7 @@ function findIndex (term) {
* Helper to create new choices based on previous selection.
*/
Prompt.prototype.createChoices = function (basePath) {
var choices = getDirectories(basePath);
var choices = getDirectories(basePath, this.includeFiles);
if (choices.length > 0) {
choices.push(new Separator());
}
Expand All @@ -300,7 +308,7 @@ Prompt.prototype.createChoices = function (basePath) {
* @param {Number} pointer Position of the pointer
* @return {String} Rendered content
*/
function listRender(choices, pointer) {
function listRender(choices, pointer) {
var output = '';
var separatorOffset = 0;

Expand All @@ -327,17 +335,19 @@ Prompt.prototype.createChoices = function (basePath) {
* @param {String} basePath the path the folder to get a list of containing folders
* @return {Array} array of folder names inside of basePath
*/
function getDirectories(basePath) {
function getDirectories(basePath, includeFile) {
if (!fs.lstatSync(basePath).isDirectory()){
return [];
}
return fs
.readdirSync(basePath)
.filter(function(file) {
.filter(function (file) {
var stats = fs.lstatSync(path.join(basePath, file));
if (stats.isSymbolicLink()) {
return false;
}
var isDir = stats.isDirectory();
var isNotDotFile = path.basename(file).indexOf('.') !== 0;
return isDir && isNotDotFile;
return isNotDotFile && (includeFile || stats.isDirectory());
})
.sort();
}
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "inquirer-directory",
"version": "2.2.0",
"description": "a directory (relative to given path) selector for Inquirer.js",
"name": "speajus-inquirer-directory-fork",
"version": "2.3.1",
"description": "A fork of a inquirer-directory to allow file selection (relative to given path) selector for Inquirer.js",
"main": "index.js",
"scripts": {
"test": "node_modules/.bin/_mocha test/spec",
Expand All @@ -10,7 +10,7 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/nicksrandall/inquierer-directory.git"
"url": "git+https://github.com/jspears/inquirer-directory.git"
},
"keywords": [
"Inquirer",
Expand All @@ -20,9 +20,9 @@
"author": "Nick Randall <nicksrandall@gmail.com> (http://nickrandall.com)",
"license": "MIT",
"bugs": {
"url": "https://github.com/nicksrandall/inquierer-directory/issues"
"url": "https://github.com/jspears/inquirer-directory/issues"
},
"homepage": "https://github.com/nicksrandall/inquierer-directory#readme",
"homepage": "+https://github.com/jspears/inquirer-directory#readme",
"dependencies": {
"chalk": "^1.1.1",
"cli-cursor": "^1.0.2",
Expand Down
50 changes: 26 additions & 24 deletions test/helpers/readline.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,39 @@ var sinon = require('sinon');
var util = require('util');
var _ = require('lodash');

var stub = {};

_.assign(stub, {
write: sinon.stub().returns(stub),
moveCursor: sinon.stub().returns(stub),
setPrompt: sinon.stub().returns(stub),
close: sinon.stub().returns(stub),
pause: sinon.stub().returns(stub),
resume: sinon.stub().returns(stub),
_getCursorPos: sinon.stub().returns({
cols: 0,
rows: 0
}),
output: {
end: sinon.stub(),
mute: sinon.stub(),
unmute: sinon.stub(),
__raw__: '',
write: function(str) {
this.__raw__ += str;
}
}
});

var ReadlineStub = function() {
this.line = '';
this.input = new EventEmitter();
EventEmitter.apply(this, arguments);

var stub = {};

Object.assign(this, {
write: sinon.stub().returns(stub),
moveCursor: sinon.stub().returns(stub),
setPrompt: sinon.stub().returns(stub),
close: sinon.stub().returns(stub),
pause: sinon.stub().returns(stub),
resume: sinon.stub().returns(stub),
_getCursorPos: sinon.stub().returns({
cols: 0,
rows: 0
}),
output: {
end: sinon.stub(),
mute: sinon.stub(),
unmute: sinon.stub(),
__raw__: '',
write: function(str) {
this.__raw__ += str;
}
}
});

};

util.inherits(ReadlineStub, EventEmitter);
_.assign(ReadlineStub.prototype, stub);
//_.assign(ReadlineStub.prototype, stub);

module.exports = ReadlineStub;
Loading