diff --git a/lib/tput.js b/lib/tput.js index 6cfbb01..88ed91b 100644 --- a/lib/tput.js +++ b/lib/tput.js @@ -35,15 +35,37 @@ function Tput(options) { this.term = options.term || process.env.TERM; this.data = null; this.info = {}; + this.termcap = null; + this.debug = options.debug; this.padding = options.padding; this.extended = options.extended; this.printf = options.printf; - this.readTerminfo(); - this.compile(); + try { + if (options.termcap) { + this.readTermcap(); + this.compileTermcap(); + } else { + this.readTerminfo(); + this.compile(); + } + } catch (e) { + this.fallback(); + } } +Tput.prototype.fallback = function() { + delete this.term; + delete this.info; + delete this.data; + delete this.termcap; + + this.term = 'vt102'; + this.readTermcap(Tput._vt102); + this.compileTermcap(); +}; + Tput.prototype.readTerminfo = function() { if (this.data) return; @@ -371,6 +393,10 @@ Tput.prototype.compile = function(key) { var self = this , info = this.info; + if (!info) { + throw new Error('Terminal not found.'); + } + if (this.debug) { console.log(this.info); } @@ -932,12 +958,13 @@ Tput.prototype._parsePadding = function(code, print, done) { * Termcap */ -Tput.prototype.readTermcap = function() { +Tput.prototype.readTermcap = function(data) { if (this.termcap) return; this.termcap = {}; - this.termcap.data = process.env.TERMCAP + this.termcap.data = data + || process.env.TERMCAP || fs.readFileSync('/etc/termcap', 'ascii'); this.termcap.terms = this.parseTermcap(this.termcap.data); @@ -1032,8 +1059,53 @@ Tput.prototype.parseTermcap = function(data) { * man termcap */ -Tput.prototype.compileTermcap = function(info) { - var self = this; +Tput.prototype.translateTermcap = function() { + var self = this + , info = this.termcap.info + , out = {}; + + if (!info) { + throw new Error('Terminal not found.'); + } + + // Separate aliases for termcap + var talias = (function() { + var alias = Tput.alias + , out = {}; + + Object.keys(alias).forEach(function(key) { + var a = alias[key].slice() + , tc = a.terminfo || a.splice(1, 1)[0]; + out[tc] = [key].concat(a); + }); + + return out; + })(); + + ['bools', 'numbers', 'strings'].forEach(function(key) { + out[key] = {}; + Object.keys(info[key]).forEach(function(cap) { + if (talias[cap]) { + out[key][talias[cap][0]] = info[key][cap]; + } + }); + }); + + return out; +}; + +Tput.prototype.compileTermcap = function() { + this.info = this.translateTermcap(); + this.compile(); +}; + +/*Tput.prototype.compileTermcap = function() { + var self = this + , info = this.termcap.info; + + if (!info) { + throw new Error('Terminal not found.'); + } info.all = {}; @@ -1067,7 +1139,7 @@ Tput.prototype.compileTermcap = function(info) { }); return info.all; -}; +};*/ /** * Helpers @@ -1241,6 +1313,22 @@ assert.notEqual(Tput.alias.exit_delete_mode[1], 'ed'); // assert.notEqual(Tput.alias.lines[0], 'lines'); // assert.notEqual(Tput.alias.set_lr_margin[1], 'ML'); +/** + * Fallback Termcap + */ + +Tput.vt102 = '' + + 'vt102|dec vt102:\\\n' + + ' :do=^J:co#80:li#24:cl=50\\E[;H\\E[2J:\\\n' + + ' :le=^H:bs:cm=5\\E[%i%d;%dH:nd=2\\E[C:up=2\\E[A:\\\n' + + ' :ce=3\\E[K:cd=50\\E[J:so=2\\E[7m:se=2\\E[m:us=2\\E[4m:ue=2\\E[m:\\\n' + + ' :md=2\\E[1m:mr=2\\E[7m:mb=2\\E[5m:me=2\\E[m:is=\\E[1;24r\\E[24;1H:\\\n' + + ' :rs=\\E>\\E[?3l\\E[?4l\\E[?5l\\E[?7h\\E[?8h:ks=\\E[?1h\\E=:ke=\\E[?1l\\E>:\\\n' + + ' :ku=\\EOA:kd=\\EOB:kr=\\EOC:kl=\\EOD:kb=^H:\\\n' + + ' :ho=\\E[H:k1=\\EOP:k2=\\EOQ:k3=\\EOR:k4=\\EOS:pt:sr=5\\EM:vt#3:\\\n' + + ' :sc=\\E7:rc=\\E8:cs=\\E[%i%d;%dr:vs=\\E[?7l:ve=\\E[?7h:\\\n' + + ' :mi:al=\\E[L:dc=\\E[P:dl=\\E[M:ei=\\E[4l:im=\\E[4h:'; + /** * Terminfo Data */