better terminfo/cap discovery. fixes #17.

This commit is contained in:
Christopher Jeffrey 2013-08-24 22:25:38 -05:00
parent fdfdac63a8
commit 00ee15a32f

View File

@ -124,6 +124,19 @@ Tput.prototype._useInternalCap = function(name) {
* Terminfo * Terminfo
*/ */
Tput.ipaths = [
process.env.TERMINFO || '',
(process.env.TERMINFO_DIRS || '').split(':'),
(process.env.HOME || '') + '/.terminfo',
'/usr/share/terminfo',
'/usr/share/lib/terminfo',
'/usr/lib/terminfo',
'/usr/local/share/terminfo',
'/usr/local/share/lib/terminfo',
'/usr/local/lib/terminfo',
'/usr/local/ncurses/lib/terminfo'
];
Tput.prototype.readTerminfo = function(term) { Tput.prototype.readTerminfo = function(term) {
var term = term || this.terminal var term = term || this.terminal
, data , data
@ -143,33 +156,52 @@ Tput.prototype.readTerminfo = function(term) {
Tput._prefix = Tput._prefix =
Tput.prototype._prefix = function(term) { Tput.prototype._prefix = function(term) {
var TERMINFO = process.env.TERMINFO || '' // If we have a terminfoFile, or our
, TERMINFO_DIRS = process.env.TERMINFO_DIRS || '' // term looks like a filename, use it.
, HOME = process.env.HOME || ''; if (term) {
if (~term.indexOf(path.sep)) {
return term;
}
if (this.terminfoFile) {
return this.terminfoFile;
}
}
return (term && ~term.indexOf(path.sep) && term) var paths = Tput.ipaths.slice()
|| (term && this.terminfoFile) , file
|| this._tprefix(this.terminfoPrefix, term) , i;
|| this._tprefix(TERMINFO, term)
|| this._tprefix(TERMINFO_DIRS.split(':'), term) if (this.terminfoPrefix) {
|| this._tprefix(HOME + '/.terminfo', term) paths.unshift(this.terminfoPrefix);
|| this._tprefix('/usr/share/terminfo', term) }
|| this._tprefix('/usr/share/lib/terminfo', term)
|| this._tprefix('/usr/lib/terminfo', term) // Try exact matches.
|| this._tprefix('/usr/local/share/terminfo', term) for (i = 0; i < paths.length; i++) {
|| this._tprefix('/usr/local/share/lib/terminfo', term) file = this._tprefix(paths[i], term);
|| this._tprefix('/usr/local/lib/terminfo', term) if (file) return file;
|| this._tprefix('/usr/local/ncurses/lib/terminfo', term) }
|| (function() { throw new Error('Terminfo directory not found.'); })();
// Try similar matches.
for (i = 0; i < paths.length; i++) {
file = this._tprefix(paths[i], term, true);
if (file) return file;
}
// Not found.
throw new Error('Terminfo directory not found.');
}; };
Tput._tprefix = Tput._tprefix =
Tput.prototype._tprefix = function(prefix, term) { Tput.prototype._tprefix = function(prefix, term, soft) {
if (!prefix) return; if (!prefix) return;
var file var file
, dir
, ch , ch
, i; , i
, sdiff
, sfile
, list;
if (Array.isArray(prefix)) { if (Array.isArray(prefix)) {
for (i = 0; i < prefix.length; i++) { for (i = 0; i < prefix.length; i++) {
@ -179,18 +211,40 @@ Tput.prototype._tprefix = function(prefix, term) {
return; return;
} }
if (!term) { var find = function(word) {
file = path.resolve(prefix, 'x'); var file, ch;
file = path.resolve(prefix, word[0]);
try { try {
fs.statSync(file); fs.statSync(file);
return prefix; return file;
} catch (e) { } catch (e) {
; ;
} }
file = path.resolve(prefix, '78');
ch = word[0].charCodeAt(0).toString(16);
if (ch.length < 2) ch = '0' + ch;
file = path.resolve(prefix, ch);
try { try {
fs.statSync(file); fs.statSync(file);
return prefix; return file;
} catch (e) {
;
}
};
if (!term) {
// Make sure the directory's sub-directories
// are all one-letter, or hex digits.
// return find('x') ? prefix : null;
try {
dir = fs.readdirSync(prefix).filter(function(file) {
return file.length !== 1 && !/^[0-9a-fA-F]{2}$/.test(file);
});
if (!dir.length) {
return prefix;
}
} catch (e) { } catch (e) {
; ;
} }
@ -198,19 +252,33 @@ Tput.prototype._tprefix = function(prefix, term) {
} }
term = path.basename(term); term = path.basename(term);
dir = find(term);
file = path.resolve(prefix, term[0], term); if (!dir) return;
try {
fs.statSync(file); if (soft) {
return file; try {
} catch (e) { list = fs.readdirSync(dir);
; } catch (e) {
return;
}
list.forEach(function(file) {
if (file.indexOf(term) === 0) {
var diff = file.length - term.length;
if (!sfile || diff < sdiff) {
sdiff = diff;
sfile = file;
}
}
});
return sfile && (soft || sdiff === 0)
? path.resolve(dir, sfile)
: null;
} }
ch = term[0].charCodeAt(0).toString(16); file = path.resolve(dir, term);
if (ch.length < 2) ch = '0' + ch;
file = path.resolve(prefix, ch, term);
try { try {
fs.statSync(file); fs.statSync(file);
return file; return file;
@ -1154,6 +1222,14 @@ Tput.prototype._print = function(code, print, done) {
* Termcap * Termcap
*/ */
Tput.cpaths = [
process.env.TERMCAP || '',
(process.env.TERMPATH || '').split(/[: ]/),
(process.env.HOME || '') + '/.termcap',
'/usr/share/misc/termcap',
'/etc/termcap'
];
Tput.prototype.readTermcap = function(term) { Tput.prototype.readTermcap = function(term) {
var self = this var self = this
, term = term || this.terminal , term = term || this.terminal
@ -1162,7 +1238,9 @@ Tput.prototype.readTermcap = function(term) {
, HOME = process.env.HOME || '' , HOME = process.env.HOME || ''
, terms , terms
, term_ , term_
, root; , root
, paths
, i;
// Termcap has a bunch of terminals usually stored in one file/string, // Termcap has a bunch of terminals usually stored in one file/string,
// so we need to find the one containing our desired terminal. // so we need to find the one containing our desired terminal.
@ -1176,13 +1254,18 @@ Tput.prototype.readTermcap = function(term) {
term = Object.keys(terms)[0]; term = Object.keys(terms)[0];
} }
} else { } else {
terms = this._tryCap(this.termcapFile, term) paths = Tput.cpaths.slice();
|| this._tryCap(TERMCAP, term)
|| this._tryCap(TERMPATH && TERMPATH.split(/[: ]/), term) if (this.termcapFile) {
|| this._tryCap(HOME + '/.termcap', term) paths.unshift(this.termcapFile);
|| this._tryCap('/usr/share/misc/termcap', term) }
|| this._tryCap('/etc/termcap', term)
|| this._tryCap(Tput.termcap, term); paths.push(Tput.termcap);
for (i = 0; i < paths.length; i++) {
terms = this._tryCap(paths[i], term);
if (terms) break;
}
} }
if (!terms) { if (!terms) {