UNPKG

isoterm

Version:

A Terminal With Precisely Configurable Fonts Using CSS Unicode Ranges

1,306 lines (1,180 loc) 3.09 MB
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ (function (process){(function (){ (function() { //########################################################################################################### var CND, PATH, njs_fs, njs_path, njs_util, number_formatter, rpr; njs_path = require('path'); njs_fs = require('fs'); njs_util = require('util'); rpr = njs_util.inspect; CND = require('./main'); PATH = require('path'); this.flatten = function(x, depth = 2e308) { return x.flat(depth); }; //----------------------------------------------------------------------------------------------------------- this.jr = JSON.stringify; this.assign = Object.assign; //----------------------------------------------------------------------------------------------------------- this.here_abspath = function(dirname, ...P) { return PATH.resolve(dirname, ...P); }; this.cwd_abspath = function(...P) { return PATH.resolve(process.cwd(), ...P); }; this.cwd_relpath = function(...P) { return PATH.relative(process.cwd(), ...P); }; //----------------------------------------------------------------------------------------------------------- this.deep_copy = function(...P) { return (require('./universal-copy'))(...P); }; //----------------------------------------------------------------------------------------------------------- number_formatter = new Intl.NumberFormat('en-US'); this.format_number = function(x) { return number_formatter.format(x); }; //----------------------------------------------------------------------------------------------------------- this.escape_regex = function(text) { /* Given a `text`, return the same with all regular expression metacharacters properly escaped. Escaped characters are `[]{}()*+?-.,\^$|#` plus whitespace. */ //......................................................................................................... return text.replace(/[-[\]{}()*+?.,\\\/^$|#\s]/g, "\\$&"); }; //----------------------------------------------------------------------------------------------------------- this.escape_html = function(text) { /* Given a `text`, return the same with all characters critical in HTML (`&`, `<`, `>`) properly escaped. */ var R; R = text; R = R.replace(/&/g, '&amp;'); R = R.replace(/</g, '&lt;'); R = R.replace(/>/g, '&gt;'); //......................................................................................................... return R; }; //----------------------------------------------------------------------------------------------------------- this.find_all = function(text, matcher) { var flags, ref; /* `CND.find_all` expects a `text` and a `matcher` (which must be a RegExp object); it returns a (possibly empty) list of all matching parts in the text. If `matcher` does not have the `g` (global) flag set, a new RegExp object will be cloned behind the scenes, so passsing in a regular expression with `g` turned on may improve performance. With thanks to http://www.2ality.com/2013/08/regexp-g.html, http://www.2ality.com/2011/04/javascript-overview-of-regular.html. */ if (!((Object.prototype.toString.call(matcher === '[object RegExp]')) && matcher.global)) { flags = matcher.multiline ? 'gm' : 'g'; if (matcher.ignoreCase) { flags += 'i'; } if (matcher.sticky) { flags += 'y'; } matcher = new RegExp(matcher.source, flags); } if (!matcher.global) { throw new Error("matcher must be a RegExp object with global flag set"); } matcher.lastIndex = 0; return (ref = text.match(matcher)) != null ? ref : []; }; //=========================================================================================================== // UNSORTING //----------------------------------------------------------------------------------------------------------- this.shuffle = function(list, ratio = 1) { var this_idx; if ((this_idx = list.length) < 2) { /* Shuffles the elements of a list randomly. After the call, the elements of will be—most of the time— be reordered (but this is not guaranteed, as there is a realistic probability for recurrence of orderings with short lists). This is an implementation of the renowned Fisher-Yates algorithm, but with a twist: You may pass in a `ratio` as second argument (which should be a float in the range `0 <= ratio <= 1`); if set to a value less than one, a random number will be used to decide whether or not to perform a given step in the shuffling process, so lists shuffled with zero-ish ratios will show less disorder than lists shuffled with a one-ish ratio. Implementation gleaned from http://stackoverflow.com/a/962890/256361. */ //......................................................................................................... return list; } return this._shuffle(list, ratio, Math.random, this.random_integer.bind(this)); }; //----------------------------------------------------------------------------------------------------------- this.get_shuffle = function(seed_0 = 0, seed_1 = 1) { /* This method works similar to `get_rnd`; it accepts two `seed`s which are used to produce random number generators and returns a predictable shuffling function that accepts arguments like Bits'N'Pieces `shuffle`. */ var random_integer, rnd; rnd = this.get_rnd(seed_0); random_integer = this.get_rnd_int(seed_1); return (list, ratio = 1) => { return this._shuffle(list, ratio, rnd, random_integer); }; }; //----------------------------------------------------------------------------------------------------------- this._shuffle = function(list, ratio, rnd, random_integer) { var that_idx, this_idx; if ((this_idx = list.length) < 2) { //......................................................................................................... return list; } while (true) { //......................................................................................................... this_idx += -1; if (this_idx < 1) { return list; } if (ratio >= 1 || rnd() <= ratio) { // return list if this_idx < 1 that_idx = random_integer(0, this_idx); [list[that_idx], list[this_idx]] = [list[this_idx], list[that_idx]]; } } //......................................................................................................... return list; }; //=========================================================================================================== // RANDOM NUMBERS //----------------------------------------------------------------------------------------------------------- /* see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number */ this.MIN_SAFE_INTEGER = -(2 ** 53) - 1; this.MAX_SAFE_INTEGER = +(2 ** 53) - 1; //----------------------------------------------------------------------------------------------------------- this.random_number = function(min = 0, max = 1) { /* Return a random number between min (inclusive) and max (exclusive). From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random via http://stackoverflow.com/a/1527820/256361. */ return Math.random() * (max - min) + min; }; //----------------------------------------------------------------------------------------------------------- this.integer_from_normal_float = function(x, min = 0, max = 2) { /* Given a 'normal' float `x` so that `0 <= x < 1`, return an integer `n` so that `min <= n < min`. */ return (Math.floor(x * (max - min))) + min; }; //----------------------------------------------------------------------------------------------------------- this.random_integer = function(min = 0, max = 2) { /* Return a random integer between min (inclusive) and max (inclusive). From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random via http://stackoverflow.com/a/1527820/256361. */ return this.integer_from_normal_float(Math.random(), min, max); }; //----------------------------------------------------------------------------------------------------------- this.get_rnd_int = function(seed = 1, delta = 1) { /* Like `get_rnd`, but returns a predictable random integer generator. */ var rnd; rnd = this.get_rnd(seed, delta); return (min = 0, max = 1) => { return this.integer_from_normal_float(rnd(), min, max); }; }; //----------------------------------------------------------------------------------------------------------- this.get_rnd = function(seed = 1, delta = 1) { var R; /* This method returns a simple deterministic pseudo-random number generator—basically like `Math.random`, but (1) very probably with a much worse distribution of results, and (2) with predictable series of numbers, which is good for some testing scenarios. You may seed this method by passing in a `seed` and a `delta`, both of which must be non-zero numbers; the ensuing series of calls to the returned method will then always result in the same series of numbers. Here is a usage example that also shows how to reset the generator: CND = require 'cnd' rnd = CND.get_rnd() # or, say, `rnd = CND.get_rnd 123, 0.5` log rnd() for idx in [ 0 .. 5 ] log() rnd.reset() log rnd() for idx in [ 0 .. 5 ] Please note that there are no strong guarantees made about the quality of the generated values except the (1) deterministic repeatability, (2) boundedness, and (3) 'apparent randomness'. Do **not** use this for cryptographic purposes. */ //......................................................................................................... R = function() { var x; R._idx += 1; x = (Math.sin(R._s)) * 10000; R._s += R._delta; return x - Math.floor(x); }; //......................................................................................................... R.reset = function(seed, delta) { /* Reset the generator. After calling `rnd.reset` (or `rnd.seed` with the same arguments), ensuing calls to `rnd` will always result in the same sequence of pseudo-random numbers. */ if (seed == null) { seed = this._seed; } if (delta == null) { delta = this._delta; } //....................................................................................................... if (!((typeof seed) === 'number' && (Number.isFinite(seed)))) { throw new Error(`^3397^ expected a number, got ${rpr(seed)}`); } if (!((typeof delta) === 'number' && (Number.isFinite(delta)))) { throw new Error(`^3398^ expected a number, got ${rpr(delta)}`); } if (seed === 0) { //....................................................................................................... throw new Error("seed should not be zero"); } if (delta === 0) { throw new Error("delta should not be zero"); } //....................................................................................................... R._s = seed; R._seed = seed; R._delta = delta; R._idx = -1; return null; }; //......................................................................................................... R.reset(seed, delta); //......................................................................................................... return R; }; //=========================================================================================================== // PODs //----------------------------------------------------------------------------------------------------------- this.pluck = function(x, name, fallback) { var R; /* Given some object `x`, a `name` and a `fallback`, return the value of `x[ name ]`, or, if it does not exist, `fallback`. When the method returns, `x[ name ]` has been deleted. */ if (x[name] != null) { R = x[name]; delete x[name]; } else { R = fallback; } return R; }; //=========================================================================================================== // ROUTES //----------------------------------------------------------------------------------------------------------- this.get_parent_routes = function(route) { var R; R = []; while (true) { //......................................................................................................... R.push(route); if (route.length === 0 || route === '/') { break; } route = njs_path.dirname(route); } //......................................................................................................... return R; }; //=========================================================================================================== // CALLER LOCATION //----------------------------------------------------------------------------------------------------------- this.get_V8_CallSite_objects = function(error = null) { /* Save original Error.prepareStackTrace */ var R, prepareStackTrace_original; prepareStackTrace_original = Error.prepareStackTrace; //......................................................................................................... Error.prepareStackTrace = function(ignored, stack) { return stack; }; if (error == null) { error = new Error(); } R = error.stack; //......................................................................................................... /* Restore original Error.prepareStackTrace */ Error.prepareStackTrace = prepareStackTrace_original; //......................................................................................................... return R; }; //----------------------------------------------------------------------------------------------------------- this.get_caller_info_stack = function(delta = 0, error = null, limit = 2e308, include_source = false) { var R, call_sites, cs, entry, i, idx, len; if (error == null) { /* Return a list of PODs representing information about the call stack; newest items will be closer to the start ('top') of the list. `delta` represents the call distance of the site the inquirer is interested about, relative to the *inquirer*; this will be `0` if that is the very line where the call originated from, `1` in case another function is called to collect this information, and so on. A custom error will be produced and analyzed (with a suitably adjusted value for `delta`) in case no `error` has been given. Often, one will want to use this facility to see what the source for a caught error looks like; in that case, just pass in the caught `error` object along with a `delta` of (typically) `0` (because the error really originated where the problem occurred). It is further possible to cut down on the amount of data returned by setting `limit` to a smallish number; entries too close (with a stack index smaller than `delta`) or too far from the interesting point will be omitted. When `include_source` is `true`, an attempt will be made to open each source file, read its contents, split it into lines, and include the indicated line in the respective entry. Note that this is currently done in a very stupid, blocking, and non-memoizing way, so try not to do that if your stack trace is hundreds of lines long and includes megabyte-sized sources. Also see `get_caller_info`, which should be handy if you do not need an entire stack but just a single targetted entry. Have a look at https://github.com/loveencounterflow/guy-test to see how to use the BNP caller info methods to copy with error locations in an asynchronous world. */ //......................................................................................................... delta += +2; } call_sites = this.get_V8_CallSite_objects(error); R = []; //......................................................................................................... for (idx = i = 0, len = call_sites.length; i < len; idx = ++i) { cs = call_sites[idx]; if ((delta != null) && idx < delta) { continue; } if (R.length >= limit) { break; } entry = { 'function-name': cs.getFunctionName(), 'method-name': cs.getMethodName(), 'route': cs.getFileName(), 'line-nr': cs.getLineNumber(), 'column-nr': cs.getColumnNumber() }; if (include_source) { entry['source'] = this._source_line_from_caller_info(entry); } R.push(entry); } //......................................................................................................... return R; }; //----------------------------------------------------------------------------------------------------------- this.get_caller_info = function(delta = 0, error = null, include_source = false) { var R; R = null; while (delta >= 0 && (R == null)) { R = (this.get_caller_info_stack(delta, error, 1, include_source))[0]; delta += -1; } // console.log '©3cc0i', rpr R return R; }; //----------------------------------------------------------------------------------------------------------- this._source_line_from_caller_info = function(info) { var R, error, line_nr, route, source_lines; route = info['route']; line_nr = info['line-nr']; try { source_lines = (njs_fs.readFileSync(route, { encoding: 'utf-8' })).split(/\r?\n/); R = source_lines[line_nr - 1]; } catch (error1) { error = error1; R = null; } return R; }; //=========================================================================================================== // ID CREATION //----------------------------------------------------------------------------------------------------------- this.create_id = function(values, length) { var value; /* Given a number of `values` and a `length`, return an ID with `length` hexadecimal digits (`[0-9a-f]`) that deterministically depends on the input but can probably not reverse-engeneered to yield the input values. This is in no way meant to be cryptographically strong, just arbitrary enough so that we have a convenient method to derive an ID with little chance of overlap given different inputs. **Note** It is certainly possible to use this method (or `id_from_text`) to create a hash from a password to be stored in a DB. Don't do this. Use `bcrypt` or similar best-practices for password storage. Again, the intent of the BITSNPIECES ID utilities is *not* to be 'crypto-safe'; its intent is to give you a tool for generating repetition-free IDs. */ return this.id_from_text(((function() { var i, len, results; results = []; for (i = 0, len = values.length; i < len; i++) { value = values[i]; results.push(rpr(value)); } return results; })()).join('-'), length); }; //----------------------------------------------------------------------------------------------------------- this.create_random_id = function(values, length) { /* Like `create_id`, but with an extra random factor built in that should exclude that two identical outputs are ever returned for any two identical inputs. Under the assumption that two calls to this method are highly unlikely two produce an identical pair `( 1 * new Date(), Math.random() )` (which could only happen if `Math.random()` returned the same number again *within the same clock millisecond*), and assuming you are using a reasonable value for `length` (i.e., say, `7 < length < 20`), you should never see the same ID twice. */ values.push(1 * new Date() * Math.random()); return this.create_id(values, length); }; //----------------------------------------------------------------------------------------------------------- this.get_create_rnd_id = function(seed, delta) { var R; /* Given an optional `seed` and `delta`, returns a function that will create pseudo-random IDs similar to the ones `create_random_id` returns; however, the Bits'n'Pieces `get_rnd` method is used to obtain a repeatable random number generator so that ID sequences are repeatable. The underlying PRNG is exposed as `fn.rnd`, so `fn.rnd.reset` may be used to start over. **Use Case Example**: The below code demonstrates the interesting properties of the method returned by `get_create_rnd_id`: **(1)** we can seed the PRNG with numbers of our choice, so we get a chance to create IDs that are unlikely to be repeated by other people using the same software, even when later inputs (such as the email adresses shown here) happen to be the same. **(2)** Calling the ID generator with three diffferent user-specific inputs, we get three different IDs, as expected. **(3)** Repeating the ID generation calls with the *same* arguments will yield *different* IDs. **(4)** After calling `create_rnd_id.rnd.reset()` and feeding `create_rnd_id` with the *same* user-specific inputs, we can still see the identical *same* IDs generated—which is great for testing. create_rnd_id = CND.get_create_rnd_id 1234, 87.23 * three different user IDs: log create_rnd_id [ 'foo@example.com' ], 12 log create_rnd_id [ 'alice@nosuchname.com' ], 12 log create_rnd_id [ 'tim@cern.ch' ], 12 * the same repeated, but yielding random other IDs: log() log create_rnd_id [ 'foo@example.com' ], 12 log create_rnd_id [ 'alice@nosuchname.com' ], 12 log create_rnd_id [ 'tim@cern.ch' ], 12 * the same repeated, but yielding the same IDs as in the first run: log() create_rnd_id.rnd.reset() log create_rnd_id [ 'foo@example.com' ], 12 log create_rnd_id [ 'alice@nosuchname.com' ], 12 log create_rnd_id [ 'tim@cern.ch' ], 12 The output you should see is c40f774fce65 9d44f31f9a55 1b26e6e3e736 a0e11f616685 d7242f6935c7 976f26d1b25b c40f774fce65 9d44f31f9a55 1b26e6e3e736 Note the last three IDs exactly match the first three IDs. The upshot of this is that we get reasonably hard-to-guess, yet on-demand replayable IDs. Apart from weaknesses in the PRNG itself (for which see the caveats in the description to `get_rnd`), the obvious way to cheat the system is by making it so that a given piece of case-specific data is fed into the ID generator as the n-th call a second time. In theory, we could make it so that each call constributes to the state change inside of `create_rnd_id`; a replay would then need to provide all of the case-specific pieces of data a second time, in the right order. */ //......................................................................................................... R = (values, length) => { values.push(R.rnd()); return this.create_id(values, length); }; //......................................................................................................... R.rnd = this.get_rnd(seed, delta); //......................................................................................................... return R; }; //----------------------------------------------------------------------------------------------------------- this.id_from_text = function(text, length) { /* Given a `text` and a `length`, return an ID with `length` hexadecimal digits (`[0-9a-f]`)—this is like `create_id`, but working on a text rather than a number of arbitrary values. The hash algorithm currently used is SHA-1, which returns 40 hex digits; it should be good enough for the task at hand and has the advantage of being widely implemented. */ /* TAINT should be a user option, or take 'good' algorithm universally available */ var R; R = (((require('crypto')).createHash('sha1')).update(text, 'utf-8')).digest('hex'); if (length != null) { return R.slice(0, length); } else { return R; } }; //----------------------------------------------------------------------------------------------------------- this.id_from_route = function(route, length, handler) { var R, content; if (handler != null) { /* Like `id_from_text`, but accepting a file route instead of a text. */ throw new Error("asynchronous `id_from_route` not yet supported"); } content = njs_fs.readFileSync(route); R = (((require('crypto')).createHash('sha1')).update(content)).digest('hex'); if (length != null) { return R.slice(0, length); } else { return R; } }; //=========================================================================================================== // APP INFO //----------------------------------------------------------------------------------------------------------- this.get_app_home = function(routes = null) { var error, i, len, route; njs_fs = require('fs'); if (routes == null) { routes = require['main']['paths']; } //......................................................................................................... for (i = 0, len = routes.length; i < len; i++) { route = routes[i]; try { if ((njs_fs.statSync(route)).isDirectory()) { return njs_path.dirname(route); } } catch (error1) { //....................................................................................................... error = error1; if (error['code'] === 'ENOENT') { /* silently ignore missing routes: */ continue; } throw error; } } //......................................................................................................... throw new Error(`unable to determine application home; tested routes: \n\n ${routes.join('\n ')}\n`); }; //=========================================================================================================== // FS ROUTES //----------------------------------------------------------------------------------------------------------- this.swap_extension = function(route, extension) { var extname; if (extension[0] !== '.') { extension = '.' + extension; } extname = njs_path.extname(route); return route.slice(0, route.length - extname.length) + extension; }; //=========================================================================================================== // NETWORK //----------------------------------------------------------------------------------------------------------- this.get_local_ips = function() { /* thx to http://stackoverflow.com/a/10756441/256361 */ var R, _, description, i, interface_, len, ref; R = []; ref = (require('os')).networkInterfaces(); for (_ in ref) { interface_ = ref[_]; for (i = 0, len = interface_.length; i < len; i++) { description = interface_[i]; if (description['family'] === 'IPv4' && !description['internal']) { R.push(description['address']); } } } return R; }; // thx to https://github.com/xxorax/node-shell-escape/blob/master/shell-escape.js this.shellescape = function shellescape(a) { var ret = []; a.forEach(function(s) { if (/[^A-Za-z0-9_\/:=-]/.test(s)) { s = "'"+s.replace(/'/g,"'\\''")+"'"; s = s.replace(/^(?:'')+/g, '') // unduplicate single-quote at the beginning .replace(/\\'''/g, "\\'" ); // remove non-escaped single-quote if there are enclosed between 2 escaped } ret.push(s); }); return ret.join(' '); } //=========================================================================================================== // ESCAPE FOR COMMAND LINE //----------------------------------------------------------------------------------------------------------- ; }).call(this); }).call(this)}).call(this,require('_process')) },{"./main":5,"./universal-copy":6,"_process":175,"crypto":100,"fs":89,"os":162,"path":168,"util":215}],2:[function(require,module,exports){ // Generated by CoffeeScript 2.5.1 (function() { //----------------------------------------------------------------------------------------------------------- // Effects On //........................................................................................................... this.blink = "\x1b[5m"; this.bold = "\x1b[1m"; this.reverse = "\x1b[7m"; this.underline = "\x1b[4m"; //----------------------------------------------------------------------------------------------------------- // Effects Off //........................................................................................................... this.no_blink = "\x1b[25m"; this.no_bold = "\x1b[22m"; this.no_reverse = "\x1b[27m"; this.no_underline = "\x1b[24m"; this.reset = "\x1b[0m"; //----------------------------------------------------------------------------------------------------------- // Colors //........................................................................................................... this.colors = { black: "\x1b[38;05;16m", blue: "\x1b[38;05;27m", green: "\x1b[38;05;34m", cyan: "\x1b[38;05;51m", sepia: "\x1b[38;05;52m", indigo: "\x1b[38;05;54m", steel: "\x1b[38;05;67m", brown: "\x1b[38;05;94m", olive: "\x1b[38;05;100m", lime: "\x1b[38;05;118m", red: "\x1b[38;05;124m", crimson: "\x1b[38;05;161m", plum: "\x1b[38;05;176m", pink: "\x1b[38;05;199m", orange: "\x1b[38;05;208m", gold: "\x1b[38;05;214m", tan: "\x1b[38;05;215m", yellow: "\x1b[38;05;226m", grey: "\x1b[38;05;240m", darkgrey: "\x1b[38;05;234m", white: "\x1b[38;05;255m", // experimental: // colors as defined by http://ethanschoonover.com/solarized BASE03: "\x1b[38;05;234m", BASE02: "\x1b[38;05;235m", BASE01: "\x1b[38;05;240m", BASE00: "\x1b[38;05;241m", BASE0: "\x1b[38;05;244m", BASE1: "\x1b[38;05;245m", BASE2: "\x1b[38;05;254m", BASE3: "\x1b[38;05;230m", YELLOW: "\x1b[38;05;136m", ORANGE: "\x1b[38;05;166m", RED: "\x1b[38;05;124m", MAGENTA: "\x1b[38;05;125m", VIOLET: "\x1b[38;05;61m", BLUE: "\x1b[38;05;33m", CYAN: "\x1b[38;05;37m", GREEN: "\x1b[38;05;64m" }; //----------------------------------------------------------------------------------------------------------- // Moves etc //........................................................................................................... this.cr = "\x1b[1G"; // Carriage Return; move to first column this.clear_line_right = "\x1b[0K"; // Clear to end of line this.clear_line_left = "\x1b[1K"; // Clear to start of line this.clear_line = "\x1b[2K"; // Clear all line content this.clear_below = "\x1b[0J"; // Clear to the bottom this.clear_above = "\x1b[1J"; // Clear to the top (including current line) this.clear = "\x1b[2J"; // Clear entire screen }).call(this); },{}],3:[function(require,module,exports){ // Generated by CoffeeScript 2.5.1 (function() { var CND, ansi_vt100_cc_matcher, rgb_hex_by_vt100_colorcode; CND = require('./main'); //----------------------------------------------------------------------------------------------------------- rgb_hex_by_vt100_colorcode = { // Primary 3-bit 8 colors. Unique representation! '0': '000000', '1': '800000', '2': '008000', '3': '808000', '4': '000080', '5': '800080', '6': '008080', '7': 'c0c0c0', // Equivalent "bright" versions of original 8 colors. '8': '808080', '9': 'ff0000', '10': '00ff00', '11': 'ffff00', '12': '0000ff', '13': 'ff00ff', '14': '00ffff', '15': 'ffffff', // Strictly ascending. '16': '000000', '17': '00005f', '18': '000087', '19': '0000af', '20': '0000d7', '21': '0000ff', '22': '005f00', '23': '005f5f', '24': '005f87', '25': '005faf', '26': '005fd7', '27': '005fff', '28': '008700', '29': '00875f', '30': '008787', '31': '0087af', '32': '0087d7', '33': '0087ff', '34': '00af00', '35': '00af5f', '36': '00af87', '37': '00afaf', '38': '00afd7', '39': '00afff', '40': '00d700', '41': '00d75f', '42': '00d787', '43': '00d7af', '44': '00d7d7', '45': '00d7ff', '46': '00ff00', '47': '00ff5f', '48': '00ff87', '49': '00ffaf', '50': '00ffd7', '51': '00ffff', '52': '5f0000', '53': '5f005f', '54': '5f0087', '55': '5f00af', '56': '5f00d7', '57': '5f00ff', '58': '5f5f00', '59': '5f5f5f', '60': '5f5f87', '61': '5f5faf', '62': '5f5fd7', '63': '5f5fff', '64': '5f8700', '65': '5f875f', '66': '5f8787', '67': '5f87af', '68': '5f87d7', '69': '5f87ff', '70': '5faf00', '71': '5faf5f', '72': '5faf87', '73': '5fafaf', '74': '5fafd7', '75': '5fafff', '76': '5fd700', '77': '5fd75f', '78': '5fd787', '79': '5fd7af', '80': '5fd7d7', '81': '5fd7ff', '82': '5fff00', '83': '5fff5f', '84': '5fff87', '85': '5fffaf', '86': '5fffd7', '87': '5fffff', '88': '870000', '89': '87005f', '90': '870087', '91': '8700af', '92': '8700d7', '93': '8700ff', '94': '875f00', '95': '875f5f', '96': '875f87', '97': '875faf', '98': '875fd7', '99': '875fff', '100': '878700', '101': '87875f', '102': '878787', '103': '8787af', '104': '8787d7', '105': '8787ff', '106': '87af00', '107': '87af5f', '108': '87af87', '109': '87afaf', '110': '87afd7', '111': '87afff', '112': '87d700', '113': '87d75f', '114': '87d787', '115': '87d7af', '116': '87d7d7', '117': '87d7ff', '118': '87ff00', '119': '87ff5f', '120': '87ff87', '121': '87ffaf', '122': '87ffd7', '123': '87ffff', '124': 'af0000', '125': 'af005f', '126': 'af0087', '127': 'af00af', '128': 'af00d7', '129': 'af00ff', '130': 'af5f00', '131': 'af5f5f', '132': 'af5f87', '133': 'af5faf', '134': 'af5fd7', '135': 'af5fff', '136': 'af8700', '137': 'af875f', '138': 'af8787', '139': 'af87af', '140': 'af87d7', '141': 'af87ff', '142': 'afaf00', '143': 'afaf5f', '144': 'afaf87', '145': 'afafaf', '146': 'afafd7', '147': 'afafff', '148': 'afd700', '149': 'afd75f', '150': 'afd787', '151': 'afd7af', '152': 'afd7d7', '153': 'afd7ff', '154': 'afff00', '155': 'afff5f', '156': 'afff87', '157': 'afffaf', '158': 'afffd7', '159': 'afffff', '160': 'd70000', '161': 'd7005f', '162': 'd70087', '163': 'd700af', '164': 'd700d7', '165': 'd700ff', '166': 'd75f00', '167': 'd75f5f', '168': 'd75f87', '169': 'd75faf', '170': 'd75fd7', '171': 'd75fff', '172': 'd78700', '173': 'd7875f', '174': 'd78787', '175': 'd787af', '176': 'd787d7', '177': 'd787ff', '178': 'd7af00', '179': 'd7af5f', '180': 'd7af87', '181': 'd7afaf', '182': 'd7afd7', '183': 'd7afff', '184': 'd7d700', '185': 'd7d75f', '186': 'd7d787', '187': 'd7d7af', '188': 'd7d7d7', '189': 'd7d7ff', '190': 'd7ff00', '191': 'd7ff5f', '192': 'd7ff87', '193': 'd7ffaf', '194': 'd7ffd7', '195': 'd7ffff', '196': 'ff0000', '197': 'ff005f', '198': 'ff0087', '199': 'ff00af', '200': 'ff00d7', '201': 'ff00ff', '202': 'ff5f00', '203': 'ff5f5f', '204': 'ff5f87', '205': 'ff5faf', '206': 'ff5fd7', '207': 'ff5fff', '208': 'ff8700', '209': 'ff875f', '210': 'ff8787', '211': 'ff87af', '212': 'ff87d7', '213': 'ff87ff', '214': 'ffaf00', '215': 'ffaf5f', '216': 'ffaf87', '217': 'ffafaf', '218': 'ffafd7', '219': 'ffafff', '220': 'ffd700', '221': 'ffd75f', '222': 'ffd787', '223': 'ffd7af', '224': 'ffd7d7', '225': 'ffd7ff', '226': 'ffff00', '227': 'ffff5f', '228': 'ffff87', '229': 'ffffaf', '230': 'ffffd7', '231': 'ffffff', // Gray-scale range '232': '080808', '233': '121212', '234': '1c1c1c', '235': '262626', '236': '303030', '237': '3a3a3a', '238': '444444', '239': '4e4e4e', '240': '585858', '241': '626262', '242': '6c6c6c', '243': '767676', '244': '808080', '245': '8a8a8a', '246': '949494', '247': '9e9e9e', '248': 'a8a8a8', '249': 'b2b2b2', '250': 'bcbcbc', '251': 'c6c6c6', '252': 'd0d0d0', '253': 'dadada', '254': 'e4e4e4', '255': 'eeeeee' }; //----------------------------------------------------------------------------------------------------------- ansi_vt100_cc_matcher = /(?:\x1b\x5b)([\?=;0-9]*?)([ABCDHJKfhlmnpsu])/g; //----------------------------------------------------------------------------------------------------------- this.analyze = function(text) { /* Parse ANSI control codes out of `text` and return a list of alternating text / opcode chunks; the first element of the list and all elements with even indexes will represent (possibly empty) literal texts, while elements with even indexes will be sub-lists representing control codes. Each control code looks like `[ 'm', 38, 5, 199 ]` or `[ 'm', 0 ]`, with the opcode letter coming first, followed by the integer parameters. Adapted from https://github.com/atdt/escapes.js/blob/master/escapes.js */ var R, i, len, match, parameters, position, ref, x; R = []; while (true) { //......................................................................................................... position = ansi_vt100_cc_matcher.lastIndex; match = ansi_vt100_cc_matcher.exec(text); if (match !== null) { R.push(text.slice(position, match.index)); parameters = [match[2]]; ref = match[1].split(';'); for (i = 0, len = ref.length; i < len; i++) { x = ref[i]; parameters.push(parseInt(x, 10)); } R.push(parameters); } if (ansi_vt100_cc_matcher.lastIndex === 0) { break; } } if (position < text.length) { //......................................................................................................... R.push(text.slice(position)); } return R; }; //----------------------------------------------------------------------------------------------------------- this.as_html = function(text, options) { return (this._as_html(text, options)).join(''); }; //----------------------------------------------------------------------------------------------------------- this._as_html = function(text, options) { var R, chunk, color_code, css_class, css_prefix, i, is_ansicode, j, len, n, open_span_count, ref, ref1, vt100_clear, vt100_reset; is_ansicode = true; R = []; open_span_count = 0; css_prefix = (options != null) && (options['css-prefix'] != null) ? options['css-prefix'] : 'ansi'; vt100_reset = css_prefix.concat('-m-0'); vt100_clear = css_prefix.concat('-K'); ref = this.analyze(text); //......................................................................................................... for (i = 0, len = ref.length; i < len; i++) { chunk = ref[i]; is_ansicode = !is_ansicode; if (is_ansicode) { color_code = chunk[chunk.length - 1]; css_class = css_prefix.concat('-', chunk.join('-')); if (css_class === vt100_reset || css_class === vt100_clear) { R.push('</span>'); open_span_count -= 1; } else { R.push(`<span style='color:#${rgb_hex_by_vt100_colorcode[color_code]};'>`); // R.push "<span class='#{css_class}'>" open_span_count += 1; } continue; } else { /* TAINT must escape */ R.push(CND.escape_html(chunk)); } } //......................................................................................................... if (open_span_count > 0 && ((options != null) && options['close-spans'])) { for (n = j = 0, ref1 = open_span_count; (0 <= ref1 ? j < ref1 : j > ref1); n = 0 <= ref1 ? ++j : --j) { R.push('</span>'); } } //......................................................................................................... return R; }; //----------------------------------------------------------------------------------------------------------- this.get_css_source = function(options) { var R, color_code, css_prefix, rgb_hex; R = []; css_prefix = (options != null) && (options['css-prefix'] != null) ? options['css-prefix'] : 'ansi'; for (color_code in rgb_hex_by_vt100_colorcode) { rgb_hex = rgb_hex_by_vt100_colorcode[color_code]; R.push(`.${css_prefix}-m-38-5-${color_code} { color: ${rgb_hex}; }`); } //......................................................................................................... return R.join('\n'); }; }).call(this); },{"./main":5}],4:[function(require,module,exports){ (function (process,global){(function (){ (function() { //########################################################################################################### var _inspect, badge, color_code, color_name, effect_name, effect_names, effect_off, effect_on, get_timestamp, inspect_settings, isa_text, lines_from_stdout, rainbow_color_names, rainbow_idx, ref, rpr, rpr_settings, σ_cnd; this.constants = require('./TRM-CONSTANTS'); this.separator = ' '; this.depth_of_inspect = 20; badge = 'TRM'; this.ANSI = require('./TRM-VT100-ANALYZER'); σ_cnd = Symbol.for('cnd'); _inspect = (require('util')).inspect; isa_text = function(x) { return (typeof x) === 'string'; }; //----------------------------------------------------------------------------------------------------------- rpr_settings = { depth: 2e308, maxArrayLength: 2e308, breakLength: 2e308, compact: true, colors: false }; this.rpr = rpr = function(...P) { var x; return ((function() { var i, len, results; results = []; for (i = 0, len = P.length; i < len; i++) { x = P[i]; results.push(_inspect(x, rpr_settings)); } return results; })()).join(' '); }; //----------------------------------------------------------------------------------------------------------- inspect_settings = { depth: 2e308, maxArrayLength: 2e308, breakLength: 2e308, compact: false, colors: true }; this.inspect = function(...P) { var x; return ((function() { var i, len, results; results = []; for (i = 0, len = P.length; i < len; i++) { x = P[i]; results.push(_inspect(x, inspect_settings)); } return results; })()).join(' '); }; //----------------------------------------------------------------------------------------------------------- this.get_output_method = function(target, options) { return (...P) => { return target.write(this.pen(...P)); }; }; //----------------------------------------------------------------------------------------------------------- this.pen = function(...P) { /* Given any number of arguments, return a text representing the arguments as seen fit for output commands like `log`, `echo`, and the colors. */ return (this._pen(...P)).concat('\n'); }; //----------------------------------------------------------------------------------------------------------- this._pen = function(...P) { /* ... */ var R, p; R = (function() { var i, len, results; results = []; for (i = 0, len = P.length; i < len; i++) { p = P[i]; results.push(isa_text(p) ? p : this.rpr(p)); } return results; }).call(this); return R.join(this.separator); }; //----------------------------------------------------------------------------------------------------------- this.log = this.get_output_method(process.stderr); this.echo = this.get_output_method(process.stdout); //=========================================================================================================== // KEY CAPTURING //----------------------------------------------------------------------------------------------------------- this.listen_to_keys = function(handler) { var R, help, last_key_was_ctrl_c; if (handler.__TRM__listen_to_keys__is_registered) { /* thx to http://stackoverflow.com/a/12506613/256361 */ //......................................................................................................... /* try not to bind handler to same handler more than once: */ return null; } Object.defineProperty(handler, '__TRM__listen_to_keys__is_registered', { value: true, enumerable: false }); help = this.get_logger('help', badge); last_key_was_ctrl_c = false; R = process.openStdin(); R.setRawMode(true); R.setEncoding('utf-8'); R.resume(); //......................................................................................................... R.on('data', (key) => { var response; response = handler(key); if (key === '\u0003') { if (last_key_was_ctrl_c) { process.exit(); } last_key_was_ctrl_c = true; return help("press ctrl-C again to exit"); } else { return last_key_was_ctrl_c = false; } }); //......................................................................................................... return R; }; //----------------------------------------------------------------------------------------------------------- this.ask = function(prompt, handler) { var rl; rl = (require('readline')).createInterface({ input: process.stdin, output: process.stdout }); if (!/\s+$/.test(prompt)) { //......................................................................................................... prompt += ' '; } return rl.question(this.cyan(prompt), function(answer) { rl.close(); return handler(null, answer); }); }; // #=========================================================================================================== // # SHELL COMMANDS // #----------------------------------------------------------------------------------------------------------- // @execute = ( command, handler ) -> // unless handler? // ### https://github.com/gvarsanyi/sync-exec ### // exec = require 'sync-exec' // #........................................................................................................... // { stdout // stderr // status } = exec 'ls' // throw new Error stderr if stderr? and stderr.length > 0 // return lines_from_stdout stdout // #......................................................................................................... // ( require 'child_process' ).exec O[ 'on-change' ], ( error, stdout, stderr ) => // return handler error if error? // return handler new Error stderr if stderr? and stderr.length isnt 0 // handler null, lines_from_stdout stdout // #......................................................................................................... // return null //----------------------------------------------------------------------------------------------------------- lines_from_stdout = function(stdout) { var R; R = stdout.split('\n'); if (R[R.length - 1].length === 0) { R.length -= 1; } return R; }; //----------------------------------------------------------------------------------------------------------- this.spawn = function(command, parameters, handler) { var R; R = (require('child_process')).spawn(command, parameters, { stdio: 'inherit' }); R.on('close', handler); //......................................................................................................... return R; }; //=========================================================================================================== // COLORS & EFFECTS //----------------------------------------------------------------------------------------------------------- this.clear_line_right = this.constants.clear_