neo-blessed/lib/widgets/filemanager.js

209 lines
4.2 KiB
JavaScript
Raw Normal View History

/**
* filemanager.js - file manager element for blessed
* Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
* https://github.com/chjj/blessed
*/
/**
* Modules
*/
var path = require('path')
, fs = require('fs');
var helpers = require('../helpers');
var Node = require('./node');
var List = require('./list');
/**
* FileManager
*/
function FileManager(options) {
var self = this;
if (!(this instanceof Node)) {
return new FileManager(options);
}
options = options || {};
options.parseTags = true;
// options.label = ' {blue-fg}%path{/blue-fg} ';
List.call(this, options);
this.cwd = options.cwd || process.cwd();
this.file = this.cwd;
this.value = this.cwd;
if (options.label && ~options.label.indexOf('%path')) {
this._label.setContent(options.label.replace('%path', this.cwd));
}
this.on('select', function(item) {
var value = item.content.replace(/\{[^{}]+\}/g, '').replace(/@$/, '')
, file = path.resolve(self.cwd, value);
return fs.stat(file, function(err, stat) {
if (err) {
return self.emit('error', err, file);
}
self.file = file;
self.value = file;
if (stat.isDirectory()) {
self.emit('cd', file, self.cwd);
self.cwd = file;
if (options.label && ~options.label.indexOf('%path')) {
self._label.setContent(options.label.replace('%path', file));
}
self.refresh();
} else {
self.emit('file', file);
}
});
});
}
FileManager.prototype.__proto__ = List.prototype;
FileManager.prototype.type = 'file-manager';
FileManager.prototype.refresh = function(cwd, callback) {
if (!callback) {
callback = cwd;
cwd = null;
}
var self = this;
if (cwd) this.cwd = cwd;
else cwd = this.cwd;
return fs.readdir(cwd, function(err, list) {
if (err && err.code === 'ENOENT') {
self.cwd = cwd !== process.env.HOME
? process.env.HOME
: '/';
return self.refresh(callback);
}
if (err) {
if (callback) return callback(err);
return self.emit('error', err, cwd);
}
var dirs = []
, files = [];
list.unshift('..');
list.forEach(function(name) {
var f = path.resolve(cwd, name)
, stat;
try {
stat = fs.lstatSync(f);
} catch (e) {
;
}
if ((stat && stat.isDirectory()) || name === '..') {
dirs.push({
name: name,
text: '{light-blue-fg}' + name + '{/light-blue-fg}/',
dir: true
});
} else if (stat && stat.isSymbolicLink()) {
files.push({
name: name,
text: '{light-cyan-fg}' + name + '{/light-cyan-fg}@',
dir: false
});
} else {
files.push({
name: name,
text: name,
dir: false
});
}
});
dirs = helpers.asort(dirs);
files = helpers.asort(files);
list = dirs.concat(files).map(function(data) {
return data.text;
});
self.setItems(list);
self.select(0);
self.screen.render();
self.emit('refresh');
if (callback) callback();
});
};
FileManager.prototype.pick = function(cwd, callback) {
if (!callback) {
callback = cwd;
cwd = null;
}
var self = this
, focused = this.screen.focused === this
, hidden = this.hidden
, onfile
, oncancel;
function resume() {
self.removeListener('file', onfile);
self.removeListener('cancel', oncancel);
if (hidden) {
self.hide();
}
if (!focused) {
self.screen.restoreFocus();
}
self.screen.render();
}
this.on('file', onfile = function(file) {
resume();
return callback(null, file);
});
this.on('cancel', oncancel = function() {
resume();
return callback();
});
this.refresh(cwd, function(err) {
if (err) return callback(err);
if (hidden) {
self.show();
}
if (!focused) {
self.screen.saveFocus();
self.focus();
}
self.screen.render();
});
};
FileManager.prototype.reset = function(cwd, callback) {
if (!callback) {
callback = cwd;
cwd = null;
}
this.cwd = cwd || this.options.cwd;
this.refresh(callback);
};
module.exports = FileManager;