<commit_before>_ = require 'lodash'
{ clearLine, cursorTo } = require 'readline'
{ stripColor } = require 'chalk'
{ inspect } = require 'util'

styler = require './styler'

module.exports = @

# Alias
{ stdout, stderr } = process

# Constants
[ INFO, WARN, ERROR, VERBOSE ] = TAGS = [ "INFO", "WARN", "ERROR", "VERBS" ]
LEFT_MARGIN = _.maxBy(TAGS, _.size).length + 1
TAG_INDICATOR = ': '
LEFT_PADSTRING_LONG_LINES = _.repeat(" ", LEFT_MARGIN + TAG_INDICATOR.length)
MAX_COLS_PER_LINE = stdout.columns - 1
MINIMUM_COLS = 15

# Private methods
getNonOcuppyingLength = (str) -> str.length - stripColor(str).length

tag = (txt, style, tagString) -> style(_.padEnd(txt, LEFT_MARGIN)) + tagString

fold = (string, leftPad = LEFT_PADSTRING_LONG_LINES) ->
    cols = Math.max MINIMUM_COLS, MAX_COLS_PER_LINE - leftPad.length
    chunks = string.split("\n")

    foldImm = (str) ->
        nonOcuppyingLength = getNonOcuppyingLength(str)
        if str.length - nonOcuppyingLength <= cols # Base case
             str
        else # Recursive case
            cutString = str[...cols + nonOcuppyingLength]
            lastSpace = cutString.lastIndexOf(' ')

            # This if-else is in order to avoid cutting a word in half in case it's possible
            if lastSpace >= 0
                cutString[...lastSpace] + "\n" + leftPad + fold(str[lastSpace+1..])
            else # Quite strange there's no space in 70 character string...
                cutString[...-1] + "-\n" + leftPad + fold(str[cutString.length-1..])

    [prefix..., last] = chunks.map foldImm
    # The last endline (if exists, that's what this condition is for),
    # should not be followed by the padString
    if prefix.length
        prefix.join("\n" + leftPad) + "\n" + last
    else
        last

createWriter = (txt, styler, { stream = stdout, tagString = TAG_INDICATOR } = {}) =>
    (msg, { endline = on, margin = off } = {}) =>
        msg = inspect msg unless _.isString msg

        msg += "\n" if endline is on
        if margin
            stream.write "\n " + tag(txt, styler, tagString) +
            fold(msg, LEFT_PADSTRING_LONG_LINES + " ") + "\n"
        else
            stream.write tag(txt, styler, tagString) + fold(msg)
        @

# Exposed methods
@write = (str, stream = stdout) => stream.write str; @

@endLine = (stream = stdout) => stream.write "\n"; @

@eraseLine = (stream = stdout) => clearLine(stream); cursorTo(stream, 0); @

@verbose = @v = do =>
    verboseWriter = createWriter VERBOSE, styler.verbose
    (args...) =>
        verboseWriter args... if global.cli?.verbose?
        @

@noTag = @n = createWriter "", _.identity, { tagString: _.repeat(" ", TAG_INDICATOR.length) }

@info = @i = createWriter INFO, styler.info
<commit_msg>This goes with the previous commit about moving getNonOccupyingLength<commit_after>_ = require 'lodash'
{ clearLine, cursorTo } = require 'readline'
{ inspect } = require 'util'

{ getNonOcuppyingLength } = require './utils'
styler = require './styler'

# Alias
{ stdout, stderr } = process

# Constants
[ INFO, WARN, ERROR, VERBOSE ] = TAGS = [ "INFO", "WARN", "ERROR", "VERBS" ]
LEFT_MARGIN = _.maxBy(TAGS, _.size).length + 1
TAG_INDICATOR = ': '
LEFT_PADSTRING_LONG_LINES = _.repeat(" ", LEFT_MARGIN + TAG_INDICATOR.length)
MAX_COLS_PER_LINE = stdout.columns - 1
MINIMUM_COLS = 15

# Private methods

tag = (txt, style, tagString) -> style(_.padEnd(txt, LEFT_MARGIN)) + tagString

fold = (string, leftPad = LEFT_PADSTRING_LONG_LINES) ->
    cols = Math.max MINIMUM_COLS, MAX_COLS_PER_LINE - leftPad.length
    chunks = string.split("\n")

    foldImm = (str) ->
        nonOcuppyingLength = getNonOcuppyingLength(str)
        if str.length - nonOcuppyingLength <= cols # Base case
             str
        else # Recursive case
            cutString = str[...cols + nonOcuppyingLength]
            lastSpace = cutString.lastIndexOf(' ')

            # This if-else is in order to avoid cutting a word in half in case it's possible
            if lastSpace >= 0
                cutString[...lastSpace] + "\n" + leftPad + fold(str[lastSpace+1..])
            else # Quite strange there's no space in 70 character string...
                cutString[...-1] + "-\n" + leftPad + fold(str[cutString.length-1..])

    [prefix..., last] = chunks.map foldImm
    # The last endline (if exists, that's what this condition is for),
    # should not be followed by the padString
    if prefix.length
        prefix.join("\n" + leftPad) + "\n" + last
    else
        last

createWriter = (txt, styler, { stream = stdout, tagString = TAG_INDICATOR } = {}) =>
    (msg, { endline = on, margin = off } = {}) =>
        msg = inspect msg unless _.isString msg

        msg += "\n" if endline is on
        if margin
            stream.write "\n " + tag(txt, styler, tagString) +
            fold(msg, LEFT_PADSTRING_LONG_LINES + " ") + "\n"
        else
            stream.write tag(txt, styler, tagString) + fold(msg)
        @

# Exposed methods
@write = (str, stream = stdout) => stream.write str; @

@endLine = (stream = stdout) => stream.write "\n"; @openUpdate = no; @

@eraseLine = (stream = stdout) => clearLine(stream); cursorTo(stream, 0); @

@verbose = @v = do =>
    verboseWriter = createWriter VERBOSE, styler.verbose
    (args...) =>
        verboseWriter args... if global.cli?.verbose?
        @

@noTag = @n = createWriter "", _.identity, { tagString: _.repeat(" ", TAG_INDICATOR.length) }

@info = @i = createWriter INFO, styler.info

{'fraction_non_alphanumeric': 0.13790587376869756, 'fraction_numerical': 0.004013133892739876, 'mean_word_length': 2.694743935309973, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 26, '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': '5171203', 'n_tokens_mistral': 1842, 'n_tokens_neox': 1769, 'n_words': 481}