better code

This commit is contained in:
Christopher Jeffrey 2013-02-15 17:08:36 -06:00
parent 14df28fb35
commit c083164e33

View File

@ -288,89 +288,132 @@ Tput.prototype.invoke = function(key, prefix, params, suffix) {
// CSI Ps ; Ps r // CSI Ps ; Ps r
// CSI ? Pm r // CSI ? Pm r
var code = 'var dyn = {}, stat = {}, stack = []; out.push("'; var code = 'var dyn = {}, stat = {}, stack = [], out = []; out.push("';
// man terminfo, around line 940 // man terminfo, around line 940
while (val) {
// '\e' -> ^[ // '\e' -> ^[
val = val.replace(/\\e/gi, '\x1b'); if (cap = /\\e/gi.exec(val)) {
val = val.substring(cap[0].length);
code += '\x1b';
continue;
}
// '^A' -> ^A // '^A' -> ^A
val = val.replace(/\^(.)/gi, function(_, ch) { // case-insensitive? if (cap = /\^(.)/gi.exec(val)) { // case-insensitive?
val = val.substring(cap[0].length);
ch = cap[1];
switch (ch) { switch (ch) {
case '@': case '@':
return '\x00'; code += '\x00';
break;
case 'A': case 'A':
return '\x01'; code += '\x01';
break;
case 'B': case 'B':
return '\x02'; code += '\x02';
break;
case 'C': case 'C':
return '\x03'; code += '\x03';
break;
case 'D': case 'D':
return '\x04'; code += '\x04';
break;
case 'E': case 'E':
return '\x05'; code += '\x05';
break;
case 'F': case 'F':
return '\x06'; code += '\x06';
break;
case 'G': case 'G':
return '\x07'; code += '\x07';
break;
case 'H': case 'H':
return '\x08'; code += '\x08';
break;
case 'I': case 'I':
return '\x09'; // \t code += '\x09'; // \t
break;
case 'J': case 'J':
return '\x0a'; // \n code += '\x0a'; // \n
break;
case 'K': case 'K':
return '\x0b'; code += '\x0b';
break;
case 'L': case 'L':
return '\x0c'; code += '\x0c';
break;
case 'M': case 'M':
return '\x0d'; code += '\x0d';
break;
case 'N': case 'N':
return '\x0e'; code += '\x0e';
break;
case 'O': case 'O':
return '\x0f'; code += '\x0f';
break;
case 'P': case 'P':
return '\x10'; code += '\x10';
break;
case 'Q': case 'Q':
return '\x11'; code += '\x11';
break;
case 'R': case 'R':
return '\x12'; code += '\x12';
break;
case 'S': case 'S':
return '\x13'; code += '\x13';
break;
case 'T': case 'T':
return '\x14'; code += '\x14';
break;
case 'U': case 'U':
return '\x15'; code += '\x15';
break;
case 'V': case 'V':
return '\x16'; code += '\x16';
break;
case 'W': case 'W':
return '\x17'; code += '\x17';
break;
case 'X': case 'X':
return '\x18'; code += '\x18';
break;
case 'Y': case 'Y':
return '\x19'; code += '\x19';
break;
case 'Z': case 'Z':
return '\x1a'; code += '\x1a';
break;
case '\\': case '\\':
return '\x1c'; code += '\x1c';
break;
case '^': case '^':
return '\x1e'; code += '\x1e';
break;
case '_': case '_':
return '\x1f'; code += '\x1f';
break;
case '[': case '[':
return '\x1b'; code += '\x1b';
break;
case ']': case ']':
return '\x1d'; code += '\x1d';
break;
case '?': case '?':
return '\x7f'; code += '\x7f';
break;
}
continue;
} }
});
// '\n' -> \n // '\n' -> \n
// '\r' -> \r // '\r' -> \r
// '\0' -> \200 (special case) // '\0' -> \200 (special case)
val = val.replace(/\\([nlrtbfs\^\\,:0])/g, function(_, ch) { if (cap = /\\([nlrtbfs\^\\,:0])/g.exec(val)) {
val = val.substring(cap[0].length);
ch = cap[1];
switch (ch) { switch (ch) {
case 'n': case 'n':
return '\n'; return '\n';
@ -396,78 +439,91 @@ Tput.prototype.invoke = function(key, prefix, params, suffix) {
//return '\0'; //return '\0';
return '\200'; return '\200';
} }
}); continue;
}
// 3 octal digits -> character // 3 octal digits -> character
val = val.replace(/\\(\d\d\d)/g, function(_, ch) { if (cap = /\\(\d\d\d)/g.exec(val)) {
return String.fromCharCode(parseInt(ch, 8)); val = val.substring(cap[0].length);
}); ch = cap[1];
code += String.fromCharCode(parseInt(ch, 8));
continue;
}
// $<5> -> padding // $<5> -> padding
val = val.replace(/\$<(\d+)>(\*|\/)/g, function(_, ch, opt) { if (cap = /\$<(\d+)>(\*|\/)/g.exec(val)) {
// code += ''; val = val.substring(cap[0].length);
// TODO ch = cap[1];
return ''; code += Array(+ch + 1).join(' '); // "padding" characters?
return Array(+ch + 1).join(' '); // "padding" characters? continue;
}); }
// man terminfo, around page 1034 // man terminfo, around page 1034
// %% outputs `%' // %% outputs `%'
val = val.replace(/%%/g, '%'); if (cap = /%%/g.exec(val)) {
val = val.substring(cap[0].length);
code += '%';
continue;
}
// %[[:]flags][width[.precision]][doxXs] // %[[:]flags][width[.precision]][doxXs]
// as in printf, flags are [-+#] and space. Use a `:' to allow the // as in printf, flags are [-+#] and space. Use a `:' to allow the
// next character to be a `-' flag, avoiding interpreting "%-" as an // next character to be a `-' flag, avoiding interpreting "%-" as an
// operator. // operator.
val = val.replace(/%(?:(:)?([\-+# ]+)?)(?:(\d+)(\.\d+)?)?([doxXs])?/g, function() { if (cap = /%(?:(:)?([\-+# ]+)?)(?:(\d+)(\.\d+)?)?([doxXs])?/g.exec(val)) {
// TODO val = val.substring(cap[0].length);
return ''; code += 'TODO';
}); continue;
}
// %c print pop() like %c in printf // %c print pop() like %c in printf
val = val.replace(/%c/g, function() { if (cap = /%c/g.exec(val)) {
// code += 'out += stack.pop()'; // TODO: FORMAT val = val.substring(cap[0].length);
// TODO code += 'stack.pop()'; // TODO: FORMAT
return ''; continue;
}); }
// %s print pop() like %s in printf // %s print pop() like %s in printf
val = val.replace(/%s/g, function() { if (cap = /%s/g.exec(val)) {
// code += 'out += stack.pop()'; // TODO: FORMAT val = val.substring(cap[0].length);
// TODO code += 'stack.pop()'; // TODO: FORMAT
return ''; continue;
}); }
// %p[1-9] // %p[1-9]
// push i'th parameter // push i'th parameter
val = val.replace(/%p([1-9])/g, function(_, i) { if (cap = /%p([1-9])/g.exec(val)) {
// code += 'params[i]'; val = val.substring(cap[0].length);
return params[i] || ''; code += 'params[i]';
}); continue;
}
// %P[a-z] // %P[a-z]
// set dynamic variable [a-z] to pop() // set dynamic variable [a-z] to pop()
val = val.replace(/%P([a-z])/g, function(_, v) { if (cap = /%P([a-z])/g.exec(val)) {
// code += 'dyn[' + v + '] = stack.pop()'; val = val.substring(cap[0].length);
// TODO v = cap[1];
return ''; code += 'dyn[' + v + '] = stack.pop()';
}); continue;
}
// %g[a-z] // %g[a-z]
// get dynamic variable [a-z] and push it // get dynamic variable [a-z] and push it
val = val.replace(/%g([a-z])/g, function(_, v) { if (cap = /%g([a-z])/g.exec(val)) {
// code += '(stack.push(dyn[' + v + ']), data[' + v + '])'; val = val.substring(cap[0].length);
// TODO v = cap[1];
return ''; code += '(stack.push(dyn[' + v + ']), dyn[' + v + '])';
}); continue;
}
// %P[A-Z] // %P[A-Z]
// set static variable [a-z] to pop() // set static variable [a-z] to pop()
val = val.replace(/%P([A-Z])/g, function(_, v) { if (cap = /%P([A-Z])/g.exec(val)) {
// code += 'stat[' + v + '] = stack.pop()'; val = val.substring(cap[0].length);
// TODO v = cap[1];
return ''; code += 'stat[' + v + '] = stack.pop()';
}); continue;
}
// %g[A-Z] // %g[A-Z]
// get static variable [a-z] and push it // get static variable [a-z] and push it
@ -478,79 +534,76 @@ Tput.prototype.invoke = function(key, prefix, params, suffix) {
// documented in other implementations. Relying on it will adversely // documented in other implementations. Relying on it will adversely
// impact portability to other implementations. // impact portability to other implementations.
val = val.replace(/%g([A-Z])/g, function(_, v) { if (cap = /%g([A-Z])/g.exec(val)) {
// TODO val = val.substring(cap[0].length);
return ''; v = cap[1];
}); code += 'stack.push(stat[' + v + '])';
continue;
}
// %'c' char constant c // %'c' char constant c
val = val.replace(/%'(\w)'/g, function(_, ch) { if (cap = /%'(\w)'/g.exec(val)) {
// code += '"' + ch + '"'; val = val.substring(cap[0].length);
// TODO ch = cap[1];
return ''; code += '"' + ch + '"';
}); continue;
}
// %{nn} // %{nn}
// integer constant nn // integer constant nn
val = val.replace(/%\{(\d+)\}/g, function(_, nn) { if (cap = /%\{(\d+)\}/g.exec(val)) {
// code += '(' + ch + ')'; val = val.substring(cap[0].length);
// TODO ch = cap[1];
return ''; code += '(' + ch + ')';
}); continue;
}
// %l push strlen(pop) // %l push strlen(pop)
val = val.replace(/%l/g, function() { if (cap = /%l/g.exec(val)) {
// code += 'stack.push(stack.pop().length)'; val = val.substring(cap[0].length);
// TODO code += 'stack.push(stack.pop().length)';
return ''; continue;
}); }
// %+ %- %* %/ %m // %+ %- %* %/ %m
// arithmetic (%m is mod): push(pop() op pop()) // arithmetic (%m is mod): push(pop() op pop())
val = val.replace(/%([+\-*\/m])/g, function(_, op) {
// code += 'stack.push(stack.pop() ' + op + ' stack.pop())';
// TODO
return '';
});
// %& %| %^ // %& %| %^
// bit operations (AND, OR and exclusive-OR): push(pop() op pop()) // bit operations (AND, OR and exclusive-OR): push(pop() op pop())
val = val.replace(/%([&|\^])/g, function(_, op) {
// code += 'stack.push(stack.pop() ' + op + ' stack.pop())';
// TODO
return '';
});
// %= %> %< // %= %> %<
// logical operations: push(pop() op pop()) // logical operations: push(pop() op pop())
val = val.replace(/%([=><])/g, function(_, op) { if (cap = /%([+\-*\/m&|\^=><])/g.exec(val)) {
// code += 'stack.push(stack.pop() ' + op + ' stack.pop())'; val = val.substring(cap[0].length);
// TODO op = cap[1];
return ''; if (op === '=') op = '===';
}); else if (op === 'm') op = '%';
code += 'stack.push(stack.pop() ' + op + ' stack.pop())';
continue;
}
// %A, %O // %A, %O
// logical AND and OR operations (for conditionals) // logical AND and OR operations (for conditionals)
val = val.replace(/%([AO])/g, function(_, v) { if (cap = /%([AO])/g.exec(val)) {
// code += v === ' A ' ? ' && ' : ' || '; val = val.substring(cap[0].length);
// TODO op = cap[1];
return ''; code += op === ' A ' ? ' && ' : ' || ';
}); continue;
}
// %! %~ // %! %~
// unary operations (logical and bit complement): push(op pop()) // unary operations (logical and bit complement): push(op pop())
val = val.replace(/%([!~])/g, function(_, op) { if (cap = /%([!~])/g.exec(val)) {
// code += 'stack.push(' + op + 'stack.pop())'; val = val.substring(cap[0].length);
// TODO op = cap[1];
return ''; code += 'stack.push(' + op + 'stack.pop())';
}); continue;
}
// %i add 1 to first two parameters (for ANSI terminals) // %i add 1 to first two parameters (for ANSI terminals)
val = val.replace(/%i/g, function(_, v) { if (cap = /%i/g.exec(val)) {
// code += '(params[0]++, params[1]++)'; val = val.substring(cap[0].length);
// TODO code += '(params[0]++, params[1]++)';
return ''; continue;
}); }
// %? expr %t thenpart %e elsepart %; // %? expr %t thenpart %e elsepart %;
// This forms an if-then-else. The %e elsepart is optional. Usually // This forms an if-then-else. The %e elsepart is optional. Usually
@ -567,36 +620,29 @@ Tput.prototype.invoke = function(key, prefix, params, suffix) {
// if-then-else's. Some strings, e.g., sgr can be very complicated when // if-then-else's. Some strings, e.g., sgr can be very complicated when
// written on one line. The -f option splits the string into lines with // written on one line. The -f option splits the string into lines with
// the parts indented. // the parts indented.
//val = val.replace(/%\?(.+?)%t(.+?)%e(.+?)%;/g, function(_, expr, thenpart, elsepart) { if (cap = /%\?/g.exec(val)) {
// // TODO: Generate code: val = val.substring(cap[0].length);
// // code += ';if (' + parse(expr) + ') {' + out(thenpart) + '} else {' + out(elsepart) + '}'; code += ';if (';
// // TODO continue;
// return ''; }
//});
val = val.replace(/%\?/g, function(_, expr, thenpart, elsepart) { if (cap = /%t/g.exec(val)) {
// code += ';if ('; val = val.substring(cap[0].length);
// TODO code += ') {';
return ''; continue;
}); }
val = val.replace(/%t/g, function(_, expr, thenpart, elsepart) { if (cap = /%e/g.exec(val)) {
// code += ') {'; val = val.substring(cap[0].length);
// TODO code += '} else {';
return ''; continue;
}); }
val = val.replace(/%e/g, function(_, expr, thenpart, elsepart) { if (cap = /%;/g.exec(val)) {
// code += '} else {'; val = val.substring(cap[0].length);
// TODO code += '}';
return ''; continue;
}); }
val = val.replace(/%;/g, function(_, expr, thenpart, elsepart) {
// code += '}';
// TODO
return '';
});
// Binary operations are in postfix form with the operands in the usual // Binary operations are in postfix form with the operands in the usual
// order. That is, to get x-5 one would use "%gx%{5}%-". %P and %g vari // order. That is, to get x-5 one would use "%gx%{5}%-". %P and %g vari
@ -626,10 +672,9 @@ Tput.prototype.invoke = function(key, prefix, params, suffix) {
// Then the same is done for the second parameter. More complex // Then the same is done for the second parameter. More complex
// arithmetic is possible using the stack. // arithmetic is possible using the stack.
//val = val.replace(/%p(\d+)?/g, function(_, n) { code += val[0];
// return params[i++] || ''; val = val.substring(1);
//}); }
break; break;
} }