<commit_before>/**
 * program.js - basic curses-like functionality for blessed.
 * Copyright (c) 2013, <NAME> (MIT License).
 * https://github.com/chjj/blessed
 */

/**
 * Modules
 */

var EventEmitter = require('events').EventEmitter
  , Tput = require('./tput')
  , colors = require('./colors')
  , slice = Array.prototype.slice;

/**
 * Program
 */

function Program(options) {
  var self = this;

  if (!(this instanceof Program)) {
    return new Program(options);
  }

  EventEmitter.call(this);

  if (!options || options.__proto__ !== Object.prototype) {
    options = {
      input: arguments[0],
      output: arguments[1]
    };
  }

  if (options.tput !== false) {
    options.tput = true;
  }

  this.options = options;
  this.input = options.input || process.stdin;
  this.output = options.output || process.stdout;

  if (options.dump) {
    this.dump(options.dump);
  }

  this.zero = options.zero !== false;

  this.x = 0;
  this.y = 0;
  this.savedX = 0;
  this.savedY = 0;

  this.cols = this.output.columns || 1;
  this.rows = this.output.rows || 1;

  this.scrollTop = 0;
  this.scrollBottom = this.rows - 1;

  this.terminal = options.term
    || options.terminal
    || process.env.TERM
    || 'xterm';

  if (!Program.global) {
    Program.global = this;
  }

  if (options.tput) {
    this.setupTput();
  }

  this.listen();
}

Program.prototype.__proto__ = EventEmitter.prototype;

Program.prototype.dump = function(file) {
  var self = this
    , _write = this.output.write
    , decoder = new (require('string_decoder')).StringDecoder('utf8')
    , stringify = stringifyLess;

  this.logger = require('fs').createWriteStream(file);

  function stringifyJson(data) {
    return JSON.stringify(caret(data))
      .replace(/\\u00([0-9a-f])/gi, '\\x$1')
      .slice(1, -1);
  }

  function stringifyLess(data) {
    // Could wrap in: \x1b[7m\x1b[m
    // for inverse in `less -R`.
    return caret(data
      .replace(/\r/g, '\\r')
      .replace(/\n/g, '\\n')
      .replace(/\t/g, '\\t'))
      .replace(/[^ -~]/g, function(ch) {
        if (ch.charCodeAt(0) > 0xff) return ch;
        ch = ch.charCodeAt(0).toString(16);
        if (ch.length > 2) {
          if (ch.length < 4) ch = '0' + ch;
          return '\\u' + ch;
        }
        if (ch.length < 2) ch = '0' + ch;
        return '\\x' + ch;
      });
  }

  function stringifyMinimal(data) {
    return data
      //.replace(/\x1b/g, '^[')
      .replace(/\r/g, '\\r')
      .replace(/\n/g, '\\n')
      .replace(/\t/g, '\\t');
  }

  function caret(data) {
    return data.replace(/[\0\x80\x1b-\x1f\x7f\x01-\x1a]/g, function(ch) {
      switch (ch) {
        case '\0':
        case '\200':
          ch = '@';
          break;
        case '\x1b':
          ch = '[';
          break;
        case '\x1c':
          ch = '\\';
          break;
        case '\x1d':
          ch = ']';
          break;
        case '\x1e':
          ch = '^';
          break;
        case '\x1f':
          ch = '_';
          break;
        case '\x7f':
          ch = '?';
          break;
        default:
          ch = ch.charCodeAt(0);
          if (ch >= 1 && ch <= 26) {
          //if (ch >= 'A'.charCodeAt(0) - 64 && ch <= 'Z'.charCodeAt(0) - 64) {
            ch = String.fromCharCode(ch + 64);
          } else {
            return String.fromCharCode(ch);
          }
          break;
      }
      return '^' + ch;
    });
  }

  this.output.write = function(data) {
    self.logger.write('OUT: ' + stringify(data) + '\n-\n');
    return _write.apply(this, arguments);
  };

  this.input.on('data', function(data) {
    self.logger.write('IN: ' + stringify(decoder.write(data)) + '\n-\n');
  });
};

Program.prototype.setupTput = function() {
  var self = this
    , options = this.options
    , write = this.write.bind(this);
<commit_msg>cleanup new dump method.<commit_after>/**
 * program.js - basic curses-like functionality for blessed.
 * Copyright (c) 2013, <NAME> (MIT License).
 * https://github.com/chjj/blessed
 */

/**
 * Modules
 */

var EventEmitter = require('events').EventEmitter
  , Tput = require('./tput')
  , colors = require('./colors')
  , slice = Array.prototype.slice;

/**
 * Program
 */

function Program(options) {
  var self = this;

  if (!(this instanceof Program)) {
    return new Program(options);
  }

  EventEmitter.call(this);

  if (!options || options.__proto__ !== Object.prototype) {
    options = {
      input: arguments[0],
      output: arguments[1]
    };
  }

  if (options.tput !== false) {
    options.tput = true;
  }

  this.options = options;
  this.input = options.input || process.stdin;
  this.output = options.output || process.stdout;

  if (options.dump) {
    this.dump(options.dump);
  }

  this.zero = options.zero !== false;

  this.x = 0;
  this.y = 0;
  this.savedX = 0;
  this.savedY = 0;

  this.cols = this.output.columns || 1;
  this.rows = this.output.rows || 1;

  this.scrollTop = 0;
  this.scrollBottom = this.rows - 1;

  this.terminal = options.term
    || options.terminal
    || process.env.TERM
    || 'xterm';

  if (!Program.global) {
    Program.global = this;
  }

  if (options.tput) {
    this.setupTput();
  }

  this.listen();
}

Program.prototype.__proto__ = EventEmitter.prototype;

Program.prototype.dump = function(file) {
  var self = this
    , _write = this.output.write
    , decoder = new (require('string_decoder')).StringDecoder('utf8');

  this.logger = require('fs').createWriteStream(file);

  function stringify(data) {
    return caret(data
      .replace(/\r/g, '\\r')
      .replace(/\n/g, '\\n')
      .replace(/\t/g, '\\t'))
      .replace(/[^ -~]/g, function(ch) {
        if (ch.charCodeAt(0) > 0xff) return ch;
        ch = ch.charCodeAt(0).toString(16);
        if (ch.length > 2) {
          if (ch.length < 4) ch = '0' + ch;
          return '\\u' + ch;
        }
        if (ch.length < 2) ch = '0' + ch;
        return '\\x' + ch;
      });
  }

  function caret(data) {
    return data.replace(/[\0\x80\x1b-\x1f\x7f\x01-\x1a]/g, function(ch) {
      switch (ch) {
        case '\0':
        case '\200':
          ch = '@';
          break;
        case '\x1b':
          ch = '[';
          break;
        case '\x1c':
          ch = '\\';
          break;
        case '\x1d':
          ch = ']';
          break;
        case '\x1e':
          ch = '^';
          break;
        case '\x1f':
          ch = '_';
          break;
        case '\x7f':
          ch = '?';
          break;
        default:
          ch = ch.charCodeAt(0);
          // From ('A' - 64) to ('Z' - 64).
          if (ch >= 1 && ch <= 26) {
            ch = String.fromCharCode(ch + 64);
          } else {
            return String.fromCharCode(ch);
          }
          break;
      }
      return '^' + ch;
    });
  }

  this.output.write = function(data) {
    self.logger.write('OUT: ' + stringify(data) + '\n-\n');
    return _write.apply(this, arguments);
  };

  this.input.on('data', function(data) {
    self.logger.write('IN: ' + stringify(decoder.write(data)) + '\n-\n');
  });
};

Program.prototype.setupTput = function() {
  var self = this
    , options = this.options
    , write = this.write.bind(this);

{'fraction_non_alphanumeric': 0.1833194560088815, 'fraction_numerical': 0.01679156258673328, 'mean_word_length': 1.9142741609381317, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4960185', 'n_tokens_mistral': 2621, 'n_tokens_neox': 2514, 'n_words': 504}