<commit_before>var stringWidth = require('string-width')
var stripAnsi = require('strip-ansi')
var wrap = require('wrap-ansi')
var align = {
  right: alignRight,
  center: alignCenter
}
var top = 0
var right = 1
var bottom = 2
var left = 3

function UI (opts) {
  this.width = opts.width
  this.wrap = opts.wrap
  this.rows = []
}

UI.prototype.span = function () {
  var cols = this.div.apply(this, arguments)
  cols.span = true
}

UI.prototype.div = function () {
  if (arguments.length === 0) this.div('')
  if (this.wrap && this._shouldApplyLayoutDSL.apply(this, arguments)) {
    return this._applyLayoutDSL(arguments[0])
  }

  var cols = []

  for (var i = 0, arg; (arg = arguments[i]) !== undefined; i++) {
    if (typeof arg === 'string') cols.push(this._colFromString(arg))
    else cols.push(arg)
  }

  this.rows.push(cols)
  return cols
}

UI.prototype._shouldApplyLayoutDSL = function () {
  return arguments.length === 1 && typeof arguments[0] === 'string' &&
    /[\t\n]/.test(arguments[0])
}

UI.prototype._applyLayoutDSL = function (str) {
  var _this = this
  var rows = str.split('\n')
  var leftColumnWidth = 0

  // simple heuristic for layout, make sure the
  // second column lines up along the left-hand.
  // don't allow the first column to take up more
  // than 50% of the screen.
  rows.forEach(function (row) {
    var columns = row.split('\t')
    if (columns.length > 1 && stringWidth(columns[0]) > leftColumnWidth) {
      leftColumnWidth = Math.min(
        Math.floor(_this.width * 0.5),
        stringWidth(columns[0])
      )
    }
  })

  // generate a table:
  //  replacing ' ' with padding calculations.
  //  using the algorithmically generated width.
  rows.forEach(function (row) {
    var columns = row.split('\t')
    _this.div.apply(_this, columns.map(function (r, i) {
      return {
        text: r.trim(),
        padding: _this._measurePadding(r),
        width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
      }
    }))
  })

  return this.rows[this.rows.length - 1]
}

UI.prototype._colFromString = function (str) {
  return {
    text: str,
    padding: this._measurePadding(str)
  }
}

UI.prototype._measurePadding = function (str) {
  // measure padding without ansi escape codes
  var noAnsi = stripAnsi(str)
  return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]
}

UI.prototype.toString = function () {
  var _this = this
  var lines = []

  _this.rows.forEach(function (row, i) {
    _this.rowToString(row, lines)
  })

  // don't display any lines with the
  // hidden flag set.
  lines = lines.filter(function (line) {
    return !line.hidden
  })

  return lines.map(function (line) {
    return line.text
  }).join('\n')
}

UI.prototype.rowToString = function (row, lines) {
  var _this = this
  var padding
  var rrows = this._rasterize(row)
  var str = ''
  var ts
  var width
  var wrapWidth

  rrows.forEach(function (rrow, r) {
    str = ''
    rrow.forEach(function (col, c) {
      ts = '' // temporary string used during alignment/padding.
      width = row[c].width // the width with padding.
      wrapWidth = _this._negatePadding(row[c]) // the width without padding.

      ts += col

      for (var i = 0; i < wrapWidth - stringWidth(col); i++) {
        ts += ' '
      }

      // align the string within its column.
      if (row[c].align && row[c].align !== 'left' && _this.wrap) {
        ts = align[row[c].align](ts, wrapWidth)
        if (stringWidth(ts) < wrapWidth) ts += new Array(width - stringWidth(ts)).join(' ')
      }

      // apply border and padding to string.
      padding = row[c].padding || [0, 0, 0, 0]
      if (padding[left]) str += new Array(padding[left] + 1).join(' ')
      str += addBorder(row[c], ts, '| ')
      str += ts
      str += addBorder(row[c], ts, ' |')
      if (padding[right]) str += new Array(padding[right] + 1).join(' ')

      // if prior row is span, try to render the
      // current row on the prior line.
      if (r === 0 && lines.length > 0) {
        str = _this._renderInline(str, lines[lines.length - 1])
      }
    })

    // remove trailing whitespace.
    lines.push({
      text: str.replace(/ +$/, ''),
      span: row.span
    })
  })

  return lines
}

function addBorder (row, ts, style) {
  if (row.border) {
    if (/[.']-+[.']/.test(ts)) return ''
    else if (ts.trim().length) return style
    else return '  '
  }
  return ''
}

// if the full 'source' can render in
// the target line, do so.<commit_msg>variable is actually a column not a row<commit_after>var stringWidth = require('string-width')
var stripAnsi = require('strip-ansi')
var wrap = require('wrap-ansi')
var align = {
  right: alignRight,
  center: alignCenter
}
var top = 0
var right = 1
var bottom = 2
var left = 3

function UI (opts) {
  this.width = opts.width
  this.wrap = opts.wrap
  this.rows = []
}

UI.prototype.span = function () {
  var cols = this.div.apply(this, arguments)
  cols.span = true
}

UI.prototype.div = function () {
  if (arguments.length === 0) this.div('')
  if (this.wrap && this._shouldApplyLayoutDSL.apply(this, arguments)) {
    return this._applyLayoutDSL(arguments[0])
  }

  var cols = []

  for (var i = 0, arg; (arg = arguments[i]) !== undefined; i++) {
    if (typeof arg === 'string') cols.push(this._colFromString(arg))
    else cols.push(arg)
  }

  this.rows.push(cols)
  return cols
}

UI.prototype._shouldApplyLayoutDSL = function () {
  return arguments.length === 1 && typeof arguments[0] === 'string' &&
    /[\t\n]/.test(arguments[0])
}

UI.prototype._applyLayoutDSL = function (str) {
  var _this = this
  var rows = str.split('\n')
  var leftColumnWidth = 0

  // simple heuristic for layout, make sure the
  // second column lines up along the left-hand.
  // don't allow the first column to take up more
  // than 50% of the screen.
  rows.forEach(function (row) {
    var columns = row.split('\t')
    if (columns.length > 1 && stringWidth(columns[0]) > leftColumnWidth) {
      leftColumnWidth = Math.min(
        Math.floor(_this.width * 0.5),
        stringWidth(columns[0])
      )
    }
  })

  // generate a table:
  //  replacing ' ' with padding calculations.
  //  using the algorithmically generated width.
  rows.forEach(function (row) {
    var columns = row.split('\t')
    _this.div.apply(_this, columns.map(function (r, i) {
      return {
        text: r.trim(),
        padding: _this._measurePadding(r),
        width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
      }
    }))
  })

  return this.rows[this.rows.length - 1]
}

UI.prototype._colFromString = function (str) {
  return {
    text: str,
    padding: this._measurePadding(str)
  }
}

UI.prototype._measurePadding = function (str) {
  // measure padding without ansi escape codes
  var noAnsi = stripAnsi(str)
  return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]
}

UI.prototype.toString = function () {
  var _this = this
  var lines = []

  _this.rows.forEach(function (row, i) {
    _this.rowToString(row, lines)
  })

  // don't display any lines with the
  // hidden flag set.
  lines = lines.filter(function (line) {
    return !line.hidden
  })

  return lines.map(function (line) {
    return line.text
  }).join('\n')
}

UI.prototype.rowToString = function (row, lines) {
  var _this = this
  var padding
  var rrows = this._rasterize(row)
  var str = ''
  var ts
  var width
  var wrapWidth

  rrows.forEach(function (rrow, r) {
    str = ''
    rrow.forEach(function (col, c) {
      ts = '' // temporary string used during alignment/padding.
      width = row[c].width // the width with padding.
      wrapWidth = _this._negatePadding(row[c]) // the width without padding.

      ts += col

      for (var i = 0; i < wrapWidth - stringWidth(col); i++) {
        ts += ' '
      }

      // align the string within its column.
      if (row[c].align && row[c].align !== 'left' && _this.wrap) {
        ts = align[row[c].align](ts, wrapWidth)
        if (stringWidth(ts) < wrapWidth) ts += new Array(width - stringWidth(ts)).join(' ')
      }

      // apply border and padding to string.
      padding = row[c].padding || [0, 0, 0, 0]
      if (padding[left]) str += new Array(padding[left] + 1).join(' ')
      str += addBorder(row[c], ts, '| ')
      str += ts
      str += addBorder(row[c], ts, ' |')
      if (padding[right]) str += new Array(padding[right] + 1).join(' ')

      // if prior row is span, try to render the
      // current row on the prior line.
      if (r === 0 && lines.length > 0) {
        str = _this._renderInline(str, lines[lines.length - 1])
      }
    })

    // remove trailing whitespace.
    lines.push({
      text: str.replace(/ +$/, ''),
      span: row.span
    })
  })

  return lines
}

function addBorder (col, ts, style) {
  if (col.border) {
    if (/[.']-+[.']/.test(ts)) return ''
    else if (ts.trim().length) return style
    else return '  '
  }
  return ''
}

// if the full 'source' can render in
// the target line, do so.
{'fraction_non_alphanumeric': 0.1570669029685423, 'fraction_numerical': 0.007753655294638901, 'mean_word_length': 2.6231942215088284, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, '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': '5020022', 'n_tokens_mistral': 3089, 'n_tokens_neox': 2994, 'n_words': 818}