<commit_before>/**
 * @copyright   2017, <NAME>
 * @license     https://opensource.org/licenses/MIT
 * @flow
 */

/* eslint-disable complexity */

import chalk from 'chalk';
import figures from 'figures';
import logUpdate from 'log-update';
import Module from './Module';
import {
  STATUS_PENDING,
  STATUS_RUNNING,
  STATUS_SKIPPED,
  STATUS_PASSED,
  STATUS_FAILED,
} from './constants';

import type Task from './Task';
import type { ReportLoader } from './types';

export const REFRESH_RATE: number = 100;
export const CURSOR: string = '\x1B[?25h'; // eslint-disable-line unicorn/no-hex-escape

export default class Reporter<To: Object = {}> extends Module<To> {
  instance: IntervalID;

  loader: ?ReportLoader = null;

  /**
   * Create an indentation based on the defined length.
   */
  indent(length: number): string {
    return '  '.repeat(length);
  }

  /**
   * Render the output by looping over all tasks and messages.
   */
  render(code?: number = 0): string {
    if (!this.loader) {
      return CURSOR;
    }

    const {
      debug = false,
      debugs = [],
      errors = [],
      footer = '',
      header = '',
      logs = [],
      silent = false,
      tasks = [],
    } = this.loader();
    const output = [];
    const verbose = !silent;

    if (header && verbose) {
      output.push(header);
    }

    // Tasks first
    if (tasks.length > 0 && verbose) {
      tasks.forEach((task) => {
        output.push(...this.renderTask(task, 0));
      });
    }

    // Debugs second
    if (debugs.length > 0 && debug) {
      output.push('');

      debugs.forEach((log) => {
        output.push(this.renderMessage(log));
      });
    }

    // Messages last
    const messages = (code === 0) ? logs : errors;

    if (messages.length > 0) {
      if (messages[0] !== '') {
        output.push('');
      }

      messages.forEach((log) => {
        output.push(this.renderMessage(log));
      });

      if (messages[messages.length - 1] !== '') {
        output.push('');
      }
    }

    if (footer && verbose) {
      output.push(footer);
    }

    // Show terminal cursor
    output.push(CURSOR);

    return output.join('\n').trim();
  }

  /**
   * Render a debug, log, or error message.
   */
  renderMessage(message: string): string {
    return message;
  }

  /**
   * Render a single task including its title and status.
   * If sub-tasks or sub-routines exist, render them recursively.
   */
  renderTask(task: Task<Object, Object>, level?: number = 0, suffix?: string = ''): string[] {
    const output = [];

    // Generate the message row
    let message = `${this.indent(level)}${this.renderStatus(task)} ${task.title}`;

    if (task.isSkipped()) {
      message += ` ${chalk.yellow('[skipped]')}`;

    } else if (task.hasFailed()) {
      message += ` ${chalk.red('[failed]')}`;

    } else if (suffix) {
      message += ` ${suffix}`;
    }

    output.push(message);

    // Show only one sub-task at a time
    if (task.subtasks.length > 0) {
      let pendingTask;
      let runningTask;
      let failedTask;
      let passed = 0;

      task.subtasks.forEach((subTask) => {
        if (subTask.isPending() && !pendingTask) {
          pendingTask = subTask;

        } else if (subTask.isRunning() && !runningTask) {
          runningTask = subTask;

        } else if (subTask.hasFailed() && !failedTask) {
          failedTask = subTask;

        } else if (subTask.hasPassed()) {
          passed += 1;
        }
      });

      const activeTask = failedTask || runningTask || pendingTask;
      const taskSuffix = chalk.gray(`[${passed}/${task.subtasks.length}]`);

      // Only show if the parent is running or a task failed
      if (activeTask && (task.isRunning() || failedTask)) {
        output.push(...this.renderTask(activeTask, level + 1, taskSuffix));
      }
    }

    // Show the current status output
    if (task.statusText) {
      output.push(`${this.indent(level + 2)}${chalk.gray(task.statusText)}`);
    }

    // Show all sub-routines
    if (task.subroutines.length > 0) {
      task.subroutines.forEach((routine) => {
        output.push(...this.renderTask(routine, level + 1));
      });
    }

    return output;
  }

  /**<commit_msg>Increase passed for skipped.<commit_after>/**
 * @copyright   2017, <NAME>
 * @license     https://opensource.org/licenses/MIT
 * @flow
 */

/* eslint-disable complexity */

import chalk from 'chalk';
import figures from 'figures';
import logUpdate from 'log-update';
import Module from './Module';
import {
  STATUS_PENDING,
  STATUS_RUNNING,
  STATUS_SKIPPED,
  STATUS_PASSED,
  STATUS_FAILED,
} from './constants';

import type Task from './Task';
import type { ReportLoader } from './types';

export const REFRESH_RATE: number = 100;
export const CURSOR: string = '\x1B[?25h'; // eslint-disable-line unicorn/no-hex-escape

export default class Reporter<To: Object = {}> extends Module<To> {
  instance: IntervalID;

  loader: ?ReportLoader = null;

  /**
   * Create an indentation based on the defined length.
   */
  indent(length: number): string {
    return '  '.repeat(length);
  }

  /**
   * Render the output by looping over all tasks and messages.
   */
  render(code?: number = 0): string {
    if (!this.loader) {
      return CURSOR;
    }

    const {
      debug = false,
      debugs = [],
      errors = [],
      footer = '',
      header = '',
      logs = [],
      silent = false,
      tasks = [],
    } = this.loader();
    const output = [];
    const verbose = !silent;

    if (header && verbose) {
      output.push(header);
    }

    // Tasks first
    if (tasks.length > 0 && verbose) {
      tasks.forEach((task) => {
        output.push(...this.renderTask(task, 0));
      });
    }

    // Debugs second
    if (debugs.length > 0 && debug) {
      output.push('');

      debugs.forEach((log) => {
        output.push(this.renderMessage(log));
      });
    }

    // Messages last
    const messages = (code === 0) ? logs : errors;

    if (messages.length > 0) {
      if (messages[0] !== '') {
        output.push('');
      }

      messages.forEach((log) => {
        output.push(this.renderMessage(log));
      });

      if (messages[messages.length - 1] !== '') {
        output.push('');
      }
    }

    if (footer && verbose) {
      output.push(footer);
    }

    // Show terminal cursor
    output.push(CURSOR);

    return output.join('\n').trim();
  }

  /**
   * Render a debug, log, or error message.
   */
  renderMessage(message: string): string {
    return message;
  }

  /**
   * Render a single task including its title and status.
   * If sub-tasks or sub-routines exist, render them recursively.
   */
  renderTask(task: Task<Object, Object>, level?: number = 0, suffix?: string = ''): string[] {
    const output = [];

    // Generate the message row
    let message = `${this.indent(level)}${this.renderStatus(task)} ${task.title}`;

    if (task.isSkipped()) {
      message += ` ${chalk.yellow('[skipped]')}`;

    } else if (task.hasFailed()) {
      message += ` ${chalk.red('[failed]')}`;

    } else if (suffix) {
      message += ` ${suffix}`;
    }

    output.push(message);

    // Show only one sub-task at a time
    if (task.subtasks.length > 0) {
      let pendingTask;
      let runningTask;
      let failedTask;
      let passed = 0;

      task.subtasks.forEach((subTask) => {
        if (subTask.isPending() && !pendingTask) {
          pendingTask = subTask;

        } else if (subTask.isRunning() && !runningTask) {
          runningTask = subTask;

        } else if (subTask.hasFailed() && !failedTask) {
          failedTask = subTask;

        } else if (subTask.hasPassed() || subTask.isSkipped()) {
          passed += 1;
        }
      });

      const activeTask = failedTask || runningTask || pendingTask;
      const taskSuffix = chalk.gray(`[${passed}/${task.subtasks.length}]`);

      // Only show if the parent is running or a task failed
      if (activeTask && (task.isRunning() || failedTask)) {
        output.push(...this.renderTask(activeTask, level + 1, taskSuffix));
      }
    }

    // Show the current status output
    if (task.statusText) {
      output.push(`${this.indent(level + 2)}${chalk.gray(task.statusText)}`);
    }

    // Show all sub-routines
    if (task.subroutines.length > 0) {
      task.subroutines.forEach((routine) => {
        output.push(...this.renderTask(routine, level + 1));
      });
    }

    return output;
  }

  /**
{'fraction_non_alphanumeric': 0.15983992467043315, 'fraction_numerical': 0.006120527306967985, 'mean_word_length': 2.3113795791114575, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 31, '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': '2078271', 'n_tokens_mistral': 2779, 'n_tokens_neox': 2643, 'n_words': 644}