0.0.8 • Published 6 years ago

problemsjs v0.0.8

Weekly downloads
1
License
MIT
Repository
github
Last release
6 years ago

Problems.js

The hackable problems viewer

Problems.js Demo

Problems.js automatically executes development related tasks and displays resulting problems in a nice CLI.

😱Problems.js in a Nutshell
✅Flexible: Executes arbitrary tasks, parses the output and displays the result in a CLI.
✅Easy to get started: problemsjs init && problemsjs view. Done.
✅Interactive Problems View: Use the arrow keys to jump between found problems. Use ⏎ to open the selected problem in your favorit editor.
✅Watches you constantly: Problems.js watches your code for changes and reruns your tasks to find new problems.

Installation

Via npm:

$ npm install problemsjs --global

Using Problems.js

Run Problems.js from the command line by passing it a configuration file:

$ problemsjs --config path/to/pv-config.json

The default value for --config is .problemsjs.config.json.

Assuming path/to/pv-config.json contains a valid Problems.js configuration the following things will happen:

  • The configured tasks are executed.
  • Any reported problems are displayed in the terminal.
  • Relevant files are watched for changes.
  • On each change the tasks are executed again.

You can use the ⬆︎ and ⬇︎ keys to navigate between displayed problems. Use ⏎ to open the selected problem.

Before you can actually run Problems.js you have to configure it.

Configuration

Before Problems.js any do anything meaningful it has to be configured. You do so by creating a configuration file:(preferably in the root directory of your project):

$ problemsjs init

This creates a default configuration file (.problemsjs.config.json). You should be able to run Problems.js like this:

$ problemsjs view

The command above starts Problems.js (using the configuration file you just created) and display a few sample problems.

Example Configurations

You can have as many tasks as you want.

Testing with Jest

{
  "tasks": [{
    "name": "test",
    "matcher": "jest",
    "program": "jest",
    "args": [
       "--rootDir",
       "${workspaceFolder}",
       "--config",
       "${workspaceFolder}/jest.config.js",
       "--json",
       "--silent",
       "--reporters",
       "--all"
    ]
  }]
}

Type Checking with Flow

{
  "tasks": [{
    "name": "flow",
    "matcher": "flow",
    "program": "flow",
    "args": [
      "check",
      "--json",
      "--pretty",
      "${workspaceFolder}"
    ]
  }]
}

Linting with ESLint

{
  "tasks": [{
    "name": "lint",
    "matcher": "eslint",
    "program": "eslint",
    "args": [
      "${workspaceFolder}",
      "--config",
      "${workspaceFolder}/.eslintrc.js",
      "--ext",
      ".js,.json",
      "--format=json"
    ]
  }]
}

File Format

PropertyTypeDescription
openInEditorCommandstringCommand to be executed when hitting ⏎ in the Problems.js CLI app. You should definitely read the detailed documentation about this property if you want to use this feature.
watcherOptionsWatcherOptionsSpecifies which files should be watched for changes.
tasksArray of TasksSpecifies the tasks that should be executed automatically when a watched file is modified.

Important

You can use ${workspaceFolder} anywhere in the configuration file. ${workspaceFolder} will be substituted by the root folder of your project/workspace. Problems.js is using the folder of your configuration file as the ${workspaceFolder}.

Property: openInEditorCommand

You can use the following variables in your openInEditorCommand-string:

VariableTypeDescriptionExample Value
absolutePathstringAbsolute path to the currently selected problem./Users/chris/test/file.js
linenumberLine number of the currently selected problem.123 (defaults to 1)

Example: Open Problem in Visual Studio Code

{
…
  "openInEditorCommand": "code --goto ${absolutePath}:${line}",
…
}

You refer to variables by using the well known ${varname}-syntax. ${line} is always present (even if the line number is unknown to Problems.js or if the problem concerns the whole file. In that case ${line} will simply be 1 – to make life easier.

Property: watcherOptions

At the moment there is only a single property that can be specified by watcherOptions.

VariableTypeDescriptionExample Value
watchedFolderstringAbsolute path to the root folder whose files should be watched for changes./Users/chris/test/
includesArray of strings; optionalSpecifies which files should be watched. An array of globs. By default all JavaScript files are watched.['**/*.css', '**/*.html']
ignoresArray of strings; optionalSpecifies which files should be ignored. An array of globs. By default nothing is ignored.['**/node_modules', '**/*.cpp']

Implementation Detail

Internally Chokidar is used to watch for changes. The specified folder passed as is, without further configuration, to Chokidar. This means that Chokidar defaults apply when it comes to detecting changes. In my tests it worked good enough.

Property: tasks

A single task has the following properties:

PropertyTypeDescription
namestringName of the task. Will be used in the CLI UI to allow differentiation of problems.
cwdstring (optional)Current working directory used when executing the task. Defaults to the current working directory (process.cwd()).
programstringThe program (without any arguments) to be executed by Problems.js.
matcherstringSpecifies the matcher used to transform the task output to a set of problems. Available matchers: jest, eslint, line, tslint and flow.
argsArray of stringsArguments passed to the program.

Command Line

problemsjs --help
problemsjs <command>

Commands:
  problemsjs init  Creates a new Problem.js configuration file in the
                   current directory
  problemsjs view  Displays problems and continiously checks for new
                   problems.

Options:
  --version  Show version number
  --help     Show help

Matcher

Each task must be associated with a matcher. A matcher is responsible for turning the output of a task into something that Problems.js understands. Problems.js comes with several matchers that you can use out of the box.

Matcher: eslint

Turns the JSON-output from ESLint into problems.

Example

eslint ${workspaceFolder} --config ${workspaceFolder}/.eslintrc.js --ext .js,.json --format=json

Matcher: tslint

Turns the JSON-output from TSLint into problems.

Example

tslint --config ${workspaceFolder}/tslint.json --project ${workspaceFolder} -t json

Matcher: flow

Turns the JSON-output from flow into problems.

Example

flow check --json --pretty ${workspaceFolder}

Matcher: jest

Turns the JSON-output from jest into problems. In addition a summary is also displayed in the status bar.

Example

jest --rootDir ${workspaceFolder} --config ${workspaceFolder}/jest.config.js --json --silent --reporters --all

Matcher: line

Turns each line of text into a problem.

Example

echo "first problem\nsecond problem"

You can use this matcher to integrate with other tools that are not supported by default.

Hacking Problems.js

⚠️ ⚠️ DANGER ZONE ⚠️ ⚠️

The API is not yet stable at all. The following example is simply trying to convey the current state of the API.

⚠️ ⚠️ DANGER ZONE ⚠️ ⚠️

You can configure Problems.js even more by using the API directly. A short summary of what is possible:

  • Write and register custom matchers.
  • Add custom things to the status bar.
  • Modify the configuration at runtime.
  • Intercept and modify the most important events.

The following example shows most of what is already possible:

// @flow
'use strict';

const { App, CLI } = require('problemsjs');

const { CLI, App } = require('problemsjs');
const app = new App();
const cli = new CLI();

app.config.tasks = [{
  program: 'echo',
  args: ['hello world'],
  matcher: 'my_matcher'
}];

app.useMatcher('my_matcher', (input) => {
  return {
    problems: [{
      category: 'my_matcher',
      message: `Message from Matcher: ${input}`,
      location: { source: '', line: 1 },
    }]
  };
});

app.delegate = cli;
app.start();
  • This example first imports App and CLI - the two main building blocks and creates an instance of both.
  • Then we tell Problem.js to execute echo hello world on each run.
  • After that, we reguster a custom matcher (my_matcher). The custom matcher simply takes the input and uses it to create a single problem.
  • After that, app and cli are hooked up (app.delegage = cli;).
  • app emits several events which are simply piped directly to the cli-instance.
  • Then start() 🚀 the glory.

If you execute the code above node yourfile.js, you will see a problems view with a single task. If you change yourfile.js (or any other *.js-file) the task is run again, your matcher is called and the result is displayed.