refactor
This commit is contained in:
parent
df0aeb5005
commit
d5208b758f
189
lib/tput.js
189
lib/tput.js
|
@ -33,54 +33,39 @@ function Tput(options) {
|
|||
|
||||
this.options = options;
|
||||
this.term = options.term || process.env.TERM;
|
||||
this.data = null;
|
||||
this.info = {};
|
||||
this.methods = null;
|
||||
this.termcap = null;
|
||||
|
||||
this.debug = options.debug;
|
||||
this.padding = options.padding;
|
||||
this.extended = options.extended;
|
||||
this.printf = options.printf;
|
||||
this.termcap = options.termcap;
|
||||
|
||||
try {
|
||||
if (options.termcap) {
|
||||
this.readTermcap();
|
||||
if (this.termcap) {
|
||||
this.compileTermcap();
|
||||
} else {
|
||||
this.readTerminfo();
|
||||
this.compile();
|
||||
this.compileTerminfo();
|
||||
}
|
||||
} catch (e) {
|
||||
this.fallback();
|
||||
this.term = 'vt102';
|
||||
this.compileTermcap();
|
||||
}
|
||||
}
|
||||
|
||||
Tput.prototype.fallback = function() {
|
||||
delete this.term;
|
||||
delete this.data;
|
||||
delete this.info;
|
||||
delete this.methods;
|
||||
delete this.termcap;
|
||||
/**
|
||||
* Terminfo
|
||||
*/
|
||||
|
||||
this.term = 'vt102';
|
||||
this.readTermcap(Tput.vt102);
|
||||
this.compileTermcap();
|
||||
};
|
||||
|
||||
Tput.prototype.readTerminfo = function() {
|
||||
// if (this.data) return;
|
||||
|
||||
var file = path.resolve(
|
||||
'/usr/share/terminfo',
|
||||
path.basename(this.term[0]),
|
||||
path.basename(this.term)
|
||||
);
|
||||
|
||||
this.data = fs.readFileSync(file);
|
||||
this.info = this.parseTerminfo(this.data);
|
||||
|
||||
return this.info;
|
||||
Tput.prototype.readTerminfo = function(data) {
|
||||
if (!data) {
|
||||
var file = path.resolve(
|
||||
'/usr/share/terminfo',
|
||||
path.basename(this.term[0]),
|
||||
path.basename(this.term)
|
||||
);
|
||||
data = fs.readFileSync(file);
|
||||
}
|
||||
return this.parseTerminfo(data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -200,10 +185,10 @@ Tput.prototype.parseTerminfo = function(data) {
|
|||
l = data.length;
|
||||
if (i < l - 1) {
|
||||
var extended = this.parseExtended(data.slice(i));
|
||||
// info.header.extended = extended.header;
|
||||
['bools', 'numbers', 'strings'].forEach(function(key) {
|
||||
merge(info[key], extended[key]);
|
||||
});
|
||||
// info.extendedHexer = extended.header;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,78 +372,86 @@ Tput.prototype.parseExtended = function(data) {
|
|||
return info;
|
||||
};
|
||||
|
||||
Tput.prototype.compileTerminfo = function() {
|
||||
return this.compile.apply(this, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compiler - terminfo cap->javascript
|
||||
*/
|
||||
|
||||
Tput.prototype.compile = function(key) {
|
||||
var self = this
|
||||
, info = this.info;
|
||||
Tput.prototype.compile = function(info, inject) {
|
||||
var self = this;
|
||||
|
||||
if (arguments.length === 0) {
|
||||
info = this.readTerminfo();
|
||||
}
|
||||
|
||||
if (!info) {
|
||||
throw new Error('Terminal not found.');
|
||||
}
|
||||
|
||||
if (this.debug) {
|
||||
console.log(this.info);
|
||||
console.log(info);
|
||||
}
|
||||
|
||||
this.methods = {};
|
||||
this.info.all = {};
|
||||
info.all = {};
|
||||
info.methods = {};
|
||||
|
||||
Object.keys(info.bools).forEach(function(key) {
|
||||
info.all[key] = info.bools[key];
|
||||
});
|
||||
|
||||
Object.keys(info.numbers).forEach(function(key) {
|
||||
info.all[key] = info.numbers[key];
|
||||
});
|
||||
|
||||
Object.keys(info.strings).forEach(function(key) {
|
||||
info.all[key] = info.strings[key];
|
||||
});
|
||||
|
||||
Object.keys(info.all).forEach(function(key) {
|
||||
if (self.debug) {
|
||||
console.log('Compiling %s: %s', key, JSON.stringify(info.all[key]));
|
||||
}
|
||||
self.methods[key] = self._compile(info.all[key]);
|
||||
['bools', 'numbers', 'strings'].forEach(function(type) {
|
||||
Object.keys(info[type]).forEach(function(key) {
|
||||
info.all[key] = info[type][key];
|
||||
if (self.debug) {
|
||||
console.log('Compiling %s: %s', key, JSON.stringify(info.all[key]));
|
||||
}
|
||||
info.methods[key] = self._compile(info.all[key]);
|
||||
});
|
||||
});
|
||||
|
||||
Tput.bools.forEach(function(key) {
|
||||
if (self.methods[key] == null) self.methods[key] = false;
|
||||
if (info.methods[key] == null) info.methods[key] = false;
|
||||
});
|
||||
|
||||
Tput.numbers.forEach(function(key) {
|
||||
if (self.methods[key] == null) self.methods[key] = -1;
|
||||
if (info.methods[key] == null) info.methods[key] = -1;
|
||||
});
|
||||
|
||||
Tput.strings.forEach(function(key) {
|
||||
if (!self.methods[key]) self.methods[key] = noop;
|
||||
if (!info.methods[key]) info.methods[key] = noop;
|
||||
});
|
||||
|
||||
Object.keys(this.methods).forEach(function(key) {
|
||||
Object.keys(info.methods).forEach(function(key) {
|
||||
var alias = Tput.alias[key];
|
||||
if (alias) {
|
||||
if (!Array.isArray(alias)) alias = [alias];
|
||||
alias.forEach(function(alias) {
|
||||
if (self.methods[alias] && alias !== key && alias !== 'ML') {
|
||||
// We can ignore `lines` and `ML` here.
|
||||
throw new Error('Alias collision: ' + key + ' -> ' + alias);
|
||||
}
|
||||
self.methods[alias] = self.methods[key];
|
||||
});
|
||||
}
|
||||
if (!alias) return;
|
||||
if (!Array.isArray(alias)) alias = [alias];
|
||||
alias.forEach(function(alias) {
|
||||
if (info.methods[alias] && alias !== key && alias !== 'ML') {
|
||||
// We can ignore `lines` and `ML` here.
|
||||
throw new Error('Alias collision: ' + key + ' -> ' + alias);
|
||||
}
|
||||
info.methods[alias] = info.methods[key];
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(self.methods).forEach(function(key) {
|
||||
if (typeof self.methods[key] !== 'function') {
|
||||
self[key] = self.methods[key];
|
||||
if (inject !== false) {
|
||||
this.inject(info);
|
||||
}
|
||||
|
||||
return info;
|
||||
};
|
||||
|
||||
Tput.prototype.inject = function(info) {
|
||||
var self = this
|
||||
, methods = info.methods || info;
|
||||
|
||||
Object.keys(methods).forEach(function(key) {
|
||||
if (typeof methods[key] !== 'function') {
|
||||
self[key] = methods[key];
|
||||
return;
|
||||
}
|
||||
self[key] = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return self.methods[key].call(self, args);
|
||||
return methods[key].call(self, args);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -871,7 +864,7 @@ Tput.prototype._compile = function(val) {
|
|||
// arithmetic is possible using the stack.
|
||||
|
||||
// $ man termcap
|
||||
if (this.options.termcap) {
|
||||
if (this.termcap) {
|
||||
// %r Single parameter capability
|
||||
if (read(/^%r/)) {
|
||||
expr('()');
|
||||
|
@ -991,19 +984,13 @@ Tput.prototype._parsePadding = function(code, print, done) {
|
|||
*/
|
||||
|
||||
Tput.prototype.readTermcap = function(data) {
|
||||
// if (this.termcap) return;
|
||||
|
||||
this.termcap = {};
|
||||
|
||||
this.termcap.data = data
|
||||
var data = data
|
||||
|| process.env.TERMCAP
|
||||
|| tryRead('/etc/termcap')
|
||||
|| Tput.vt102;
|
||||
|
||||
this.termcap.terms = this.parseTermcap(this.termcap.data);
|
||||
this.termcap.info = this.termcap.terms[this.term];
|
||||
|
||||
return this.termcap;
|
||||
var terms = this.parseTermcap(data);
|
||||
return terms[this.term];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1092,15 +1079,18 @@ Tput.prototype.parseTermcap = function(data) {
|
|||
* man termcap
|
||||
*/
|
||||
|
||||
Tput.prototype.translateTermcap = function() {
|
||||
Tput.prototype.translateTermcap = function(info) {
|
||||
var self = this
|
||||
, info = this.termcap.info
|
||||
, out = {};
|
||||
|
||||
if (!info) {
|
||||
throw new Error('Terminal not found.');
|
||||
}
|
||||
|
||||
if (this.debug) {
|
||||
console.log(info);
|
||||
}
|
||||
|
||||
['name', 'names', 'desc'].forEach(function(key) {
|
||||
out[key] = info[key];
|
||||
});
|
||||
|
@ -1112,13 +1102,15 @@ Tput.prototype.translateTermcap = function() {
|
|||
|
||||
Object.keys(alias).forEach(function(key) {
|
||||
var a = alias[key].slice()
|
||||
, tc = a.terminfo || a.splice(1, 1)[0];
|
||||
, tc = a.termcap || a.splice(1, 1)[0];
|
||||
out[tc] = [key].concat(a);
|
||||
});
|
||||
|
||||
return out;
|
||||
})();
|
||||
|
||||
// Translate termcap cap names to terminfo cap names.
|
||||
// e.g. `up` -> `cursor_up`
|
||||
['bools', 'numbers', 'strings'].forEach(function(key) {
|
||||
out[key] = {};
|
||||
Object.keys(info[key]).forEach(function(cap) {
|
||||
|
@ -1131,9 +1123,14 @@ Tput.prototype.translateTermcap = function() {
|
|||
return out;
|
||||
};
|
||||
|
||||
Tput.prototype.compileTermcap = function() {
|
||||
this.info = this.translateTermcap();
|
||||
this.compile();
|
||||
Tput.prototype.compileTermcap = function(info) {
|
||||
if (arguments.length === 0) {
|
||||
info = this.readTermcap();
|
||||
}
|
||||
|
||||
info = this.translateTermcap(info);
|
||||
|
||||
return this.compile(info);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1291,7 +1288,8 @@ delete Tput.alias.numbers;
|
|||
merge(Tput.alias, Tput.alias.strings);
|
||||
delete Tput.alias.strings;
|
||||
|
||||
// Make sure there are no collisions between cap and tcap.
|
||||
// Make sure there are no collisions between terminfo names
|
||||
// and termcap names. Terminfo takes precedence.
|
||||
Tput._vec = Object.keys(Tput.alias).map(function(key) {
|
||||
return Array.isArray(Tput.alias[key])
|
||||
? Tput.alias[key][0]
|
||||
|
@ -1306,10 +1304,13 @@ Object.keys(Tput.alias).forEach(function(key) {
|
|||
var alias = Tput.alias[key]
|
||||
, tcap = alias[1];
|
||||
|
||||
alias.name = key;
|
||||
alias.terminfo = alias[0];
|
||||
alias.termcap = alias[1];
|
||||
|
||||
if (!tcap) return;
|
||||
|
||||
if (~Tput._vec.indexOf(tcap)) {
|
||||
alias.termcap = tcap;
|
||||
alias.splice(1, 1);
|
||||
}
|
||||
});
|
||||
|
@ -1319,7 +1320,7 @@ assert.notEqual(Tput.alias.exit_delete_mode[1], 'ed');
|
|||
// assert.notEqual(Tput.alias.set_lr_margin[1], 'ML');
|
||||
|
||||
/**
|
||||
* Fallback Termcap
|
||||
* Fallback Termcap Entry
|
||||
*/
|
||||
|
||||
Tput.vt102 = ''
|
||||
|
|
Loading…
Reference in New Issue