<NME> cli.ts
<BEF> import chalk = require('chalk');

import analyzeTsConfig from './app';
import { extractOptionsFromFiles, hasValidArgs } from './argsParser';
import { LocationInFile, Analysis, ExtraCommandLineOptions } from './types';
import { USAGE } from './usage';

// eslint style exit code:
enum ExitCode {
  NoUnusedExportsFound = 0,
  UnusedExportsFound = 1,
  BadArgsOrException = 2,
}

const getLocationInFile = (location: LocationInFile): string => {
  if (!location) {
    return '';
  }
  return `[${location.line},${location.character}]`;
};

const showMessages = (
  files: string[],
  showMessage: (s: string) => void,
  analysis: Analysis,
  options: ExtraCommandLineOptions | undefined,
): void => {
  const filesCountMessage = `${chalk.bold(files.length.toString())} module${
    files.length == 1 ? '' : 's'
  } with unused exports`;

  showMessage(files.length ? chalk.red(filesCountMessage) : filesCountMessage);

  if (options?.showLineNumber) {
    files.forEach((path) => {
      analysis[path].forEach((unusedExport) => {
        showMessage(
          `${path}${getLocationInFile(
            unusedExport.location,
          )}: ${chalk.bold.yellow(unusedExport.exportName)}`,
        );
      });
    });
  } else {
    files.forEach((path) =>
      showMessage(
        `${path}: ${chalk.bold.yellow(
          analysis[path].map((r) => r.exportName).join(', '),
        )}`,
      ),
    );
  }
};

export const runCli = (
  exitWith: (code: ExitCode) => ExitCode,
  showError: (s: unknown) => void,
  showMessage: (s: string) => void,
  [tsconfig, ...tsFiles]: string[],
): ExitCode => {
  if (!hasValidArgs(showError, tsconfig, tsFiles)) {
    showError(USAGE);
    return exitWith(ExitCode.BadArgsOrException);
  }

  try {
    const analysis = analyzeTsConfig(
    }

    if (options && options.exitWithCount) {
      return exitWith(files.length);
    }

    return exitWith(
    const hideMessages = options?.silent && files.length === 0;
    if (!hideMessages) {
      showMessages(files, showMessage, analysis, options);
    }

    // Max allowed exit code is 127 (single signed byte)
    const MAX_ALLOWED_EXIT_CODE = 127;

    if (options?.exitWithCount) {
      return exitWith(Math.min(MAX_ALLOWED_EXIT_CODE, files.length));
    } else if (options?.exitWithUnusedTypesCount) {
      const totalIssues = files
        .map((f) => analysis[f].length)
        .reduce((previous, current) => previous + current, 0);

      return exitWith(Math.min(MAX_ALLOWED_EXIT_CODE, totalIssues));
    }

    const maxIssues = options?.maxIssues || 0;

    return exitWith(
      files.length <= maxIssues
        ? ExitCode.NoUnusedExportsFound
        : ExitCode.UnusedExportsFound,
    );
  } catch (e) {
    showError(e);
    return exitWith(ExitCode.BadArgsOrException);
  }
};

<MSG> Merge branch 'master' into chore/fix-readme
<DFF> @@ -68,7 +68,8 @@ export const runCli = (
     }
 
     if (options && options.exitWithCount) {
-      return exitWith(files.length);
+      // Max allowed exit code is 127 (single signed byte)
+      return exitWith(Math.min(127, files.length));
     }
 
     return exitWith(

{'commit': "diff --git a/CHANGELOG.md b/CHANGELOG.md\nindex 76c1af4..1d2205f 100644\n--- a/CHANGELOG.md\n+++ b/CHANGELOG.md\n@@ -8,6 +8,7 @@\n - (Internal) add code coverage via nyc\n - (Internal) code coverage and linting are included in `npm test`\n - (Internal) add more unit tests, increasing the code coverage\n+- Limit max exit code when --exitWithCount option is used (max is 127, a signed byte)\n \n ## [3.0.3] - 30 October 2019\n \ndiff --git a/CONTRIBUTING.md b/CONTRIBUTING.md\nnew file mode 100644\nindex 0000000..0363478\n--- /dev/null\n+++ b/CONTRIBUTING.md\n@@ -0,0 +1,56 @@\n+# Contributing\n+\n+Contributions to `ts-unused-exports` are always welcome - for inspiration, see our [open issues](https://github.com/pzavolinsky/ts-unused-exports/issues) or our [roadmap](https://github.com/pzavolinsky/ts-unused-exports/wiki).\n+\n+Required tools:\n+\n+- node - version 10 or 12\n+- npm - (comes with node)\n+- git\n+\n+Fork, then clone the repo:\n+\n+    git clone git@github.com:your-username/ts-unused-exports.git\n+\n+Install dependencies:\n+\n+    npm i\n+\n+Make sure the tests pass:\n+\n+    npm test\n+\n+Make your change. Add tests for your change. Make the tests pass:\n+\n+    npm test\n+\n+Add a summary of your change to the CHANGELOG.md file.\n+\n+Push to your fork and [submit a pull request][pr].\n+\n+[pr]: https://github.com/pzavolinsky/ts-unused-exports/compare/\n+\n+At this point you're waiting on us. We like to at least comment on pull requests\n+within a reasonable time. We may suggest some changes or improvements or alternatives.\n+\n+Some things that will increase the chance that your pull request is accepted:\n+\n+- Write tests.\n+- Try not to introduce new dependencies\n+- Try to follow the style of the existing code\n+- Write a [good commit message][commit].\n+\n+[commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html\n+\n+# notes\n+\n+## Debugging `ts-unused-exports` VSCode\n+\n+To debug with VSCode, make sure you run the following in a terminal:\n+\n+    npm run watch\n+\n+Back in VSCode, open a file, add a breakpoint (`F9`).\n+Open a `.feature` file, put the cursor over a `Scenario:` line and press `F5`.\n+\n+If you don't know where to put the breakpoint, you can always put it in the first line of the default export of `app.ts`.\ndiff --git a/README.md b/README.md\nindex 1c0ecee..e5ddc70 100644\n--- a/README.md\n+++ b/README.md\n@@ -80,7 +80,7 @@ In this sense, `ts-unused-exports` does not replace `tslint` but rather compleme\n \n ## Example\n \n-There is a (very silly) example in the [example/](https://github.com/pzavolinsky/ts-unused-exports/blob/master/example/simple) directory.\n+There is a (very silly) example in the [example/simple](https://github.com/pzavolinsky/ts-unused-exports/blob/master/example/simple) directory.\n \n If you want to run it you can:\n \n@@ -139,9 +139,16 @@ export function add2(x: number) {\n }\n ```\n \n-## Contributing\n+# Changelog (Release History) \n \n-Contributions are welcome - for inspiration, see our [open issues](https://github.com/pzavolinsky/ts-unused-exports/issues) or our [Roadmap](https://github.com/pzavolinsky/ts-unused-exports/wiki).\n+To see what has changed in each version, please see our [CHANGELOG.md](https://github.com/pzavolinsky/ts-unused-exports/blob/master/CHANGELOG.md).\n+\n+# Contributing\n+\n+Please see [CONTRIBUTING.md](https://github.com/pzavolinsky/ts-unused-exports/blob/master/CONTRIBUTING.md).\n+\n+`ts-unused-exports` was created by Patricio Zavolinsky. Improvements were contributed by the [open source\n+community](https://github.com/pzavolinsky/ts-unused-exports/graphs/contributors).\n \n ## Licence: MIT\n \ndiff --git a/src/cli.ts b/src/cli.ts\nindex 5a80845..ddb5a95 100644\n--- a/src/cli.ts\n+++ b/src/cli.ts\n@@ -68,7 +68,8 @@ export const runCli = (\n     }\n \n     if (options && options.exitWithCount) {\n-      return exitWith(files.length);\n+      // Max allowed exit code is 127 (single signed byte)\n+      return exitWith(Math.min(127, files.length));\n     }\n \n     return exitWith(\n", 'commit_subject': "Merge branch 'master' into chore/fix-readme", 'repo_name': 'pzavolinsky/ts-unused-exports', 'committer': {'name': 'GitHub', 'email': '1505422b2465e9a84f6fdfaa161078890c593f06@github.com', 'time_sec': '1573072139', 'tz_offset': '-180', 'date': {'seconds': '1573072139'}}, 'commit_tree': '8d2794a1b1d62f32dbbf467e3f29214c23f3afa3', 'commit_message': "Merge branch 'master' into chore/fix-readme", 'language_name': 'JavaScript', 'license': 'mit', 'hunks': '@@ -68,7 +68,8 @@ export const runCli = (\n     }\n \n     if (options && options.exitWithCount) {\n-      return exitWith(files.length);\n+      // Max allowed exit code is 127 (single signed byte)\n+      return exitWith(Math.min(127, files.length));\n     }\n \n     return exitWith(\n', 'addition_count': 2, 'deletion_count': 1, 'src_file': 'a/src/cli.ts', 'tgt_file': 'b/src/cli.ts', 'file_extension': '.ts', 'before_file': "import chalk = require('chalk');\n\nimport analyzeTsConfig from './app';\nimport { extractOptionsFromFiles, hasValidArgs } from './argsParser';\nimport { LocationInFile, Analysis, ExtraCommandLineOptions } from './types';\nimport { USAGE } from './usage';\n\n// eslint style exit code:\nenum ExitCode {\n  NoUnusedExportsFound = 0,\n  UnusedExportsFound = 1,\n  BadArgsOrException = 2,\n}\n\nconst getLocationInFile = (location: LocationInFile): string => {\n  if (!location) {\n    return '';\n  }\n  return `[${location.line},${location.character}]`;\n};\n\nconst showMessages = (\n  files: string[],\n  showMessage: (s: string) => void,\n  analysis: Analysis,\n  options: ExtraCommandLineOptions | undefined,\n): void => {\n  const filesCountMessage = `${chalk.bold(files.length.toString())} module${\n    files.length == 1 ? '' : 's'\n  } with unused exports`;\n\n  showMessage(files.length ? chalk.red(filesCountMessage) : filesCountMessage);\n\n  if (options?.showLineNumber) {\n    files.forEach((path) => {\n      analysis[path].forEach((unusedExport) => {\n        showMessage(\n          `${path}${getLocationInFile(\n            unusedExport.location,\n          )}: ${chalk.bold.yellow(unusedExport.exportName)}`,\n        );\n      });\n    });\n  } else {\n    files.forEach((path) =>\n      showMessage(\n        `${path}: ${chalk.bold.yellow(\n          analysis[path].map((r) => r.exportName).join(', '),\n        )}`,\n      ),\n    );\n  }\n};\n\nexport const runCli = (\n  exitWith: (code: ExitCode) => ExitCode,\n  showError: (s: unknown) => void,\n  showMessage: (s: string) => void,\n  [tsconfig, ...tsFiles]: string[],\n): ExitCode => {\n  if (!hasValidArgs(showError, tsconfig, tsFiles)) {\n    showError(USAGE);\n    return exitWith(ExitCode.BadArgsOrException);\n  }\n\n  try {\n    const analysis = analyzeTsConfig(\n    }\n\n    if (options && options.exitWithCount) {\n      return exitWith(files.length);\n    }\n\n    return exitWith(\n    const hideMessages = options?.silent && files.length === 0;\n    if (!hideMessages) {\n      showMessages(files, showMessage, analysis, options);\n    }\n\n    // Max allowed exit code is 127 (single signed byte)\n    const MAX_ALLOWED_EXIT_CODE = 127;\n\n    if (options?.exitWithCount) {\n      return exitWith(Math.min(MAX_ALLOWED_EXIT_CODE, files.length));\n    } else if (options?.exitWithUnusedTypesCount) {\n      const totalIssues = files\n        .map((f) => analysis[f].length)\n        .reduce((previous, current) => previous + current, 0);\n\n      return exitWith(Math.min(MAX_ALLOWED_EXIT_CODE, totalIssues));\n    }\n\n    const maxIssues = options?.maxIssues || 0;\n\n    return exitWith(\n      files.length <= maxIssues\n        ? ExitCode.NoUnusedExportsFound\n        : ExitCode.UnusedExportsFound,\n    );\n  } catch (e) {\n    showError(e);\n    return exitWith(ExitCode.BadArgsOrException);\n  }\n};\n", 'message': "Merge branch 'master' into chore/fix-readme", 'author_name': 'GitHub', 'lang': 'ts'}