diff --git a/README.md b/README.md index 2a095775..15e42a64 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Concurrently -[![Build Status](https://github.com/open-cli-tools/concurrently/workflows/Tests/badge.svg)](https://github.com/open-cli-tools/concurrently/actions?workflow=Tests) +[![Build Status](https://github.com/open-cli-tools/concurrently/workflows/Tests/badge.svg)](https://github.com/open-cli-tools/concurrently/actions?workflow=Tests) [![Coverage Status](https://coveralls.io/repos/github/open-cli-tools/concurrently/badge.svg?branch=master)](https://coveralls.io/github/open-cli-tools/concurrently?branch=master) [![NPM Badge](https://nodei.co/npm/concurrently.png?downloads=true)](https://www.npmjs.com/package/concurrently) @@ -109,6 +109,26 @@ concurrently -n w: npm:watch-* concurrently -n w:js,w:css,w:node "npm run watch-js" "npm run watch-css" "npm run watch-node" ``` +Exclusion is also supported. Given the following scripts in package.json: +```javascript +{ + // ... + "scripts": { + "lint:js": "...", + "lint:ts": "...", + "lint:fix:js": "...", + "lint:fix:ts": "...", + // ... + } + // ... +} +``` +```bash +# Running only lint:js and lint:ts +# with lint:fix:js and lint:fix:ts excluded +concurrently "npm:lint:*(!fix)" +``` + Good frontend one-liner example [here](https://github.com/kimmobrunfeldt/dont-copy-paste-this-frontend-template/blob/5cd2bde719654941bdfc0a42c6f1b8e69ae79980/package.json#L9). Help: @@ -304,7 +324,7 @@ result.then(success, failure); ``` ### `Command` -An object that contains all information about a spawned command, and ways to interact with it. +An object that contains all information about a spawned command, and ways to interact with it.
It has the following properties: - `index`: the index of the command among all commands spawned. @@ -322,11 +342,11 @@ It has the following properties: - `timer`: an RxJS observable to the command's timing events (e.g. starting, stopping). - `close`: an RxJS observable to the command's close events. See [`CloseEvent`](#CloseEvent) for more information. -- `start()`: starts the command, setting up all +- `start()`: starts the command, setting up all - `kill([signal])`: kills the command, optionally specifying a signal (e.g. `SIGTERM`, `SIGKILL`, etc). ### `CloseEvent` -An object with information about a command's closing event. +An object with information about a command's closing event.
It contains the following properties: - `command`: a stripped down version of [`Command`](#command), including only `name`, `command`, `env` and `cwd` properties. diff --git a/bin/epilogue.ts b/bin/epilogue.ts index c489cc12..59a7ee82 100644 --- a/bin/epilogue.ts +++ b/bin/epilogue.ts @@ -49,6 +49,10 @@ const examples = [ { description: 'Shortened NPM run command with wildcard (make sure to wrap it in quotes!)', example: '$ $0 "npm:watch-*"', + }, + { + description: 'Exclude patterns so that between "lint:js" and "lint:fix:js", only "lint:js" is ran', + example: '$ $0 "npm:*(!fix)"' } ]; diff --git a/package-lock.json b/package-lock.json index 622cabd7..ec7091b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "concurrently", "version": "7.0.0", "license": "MIT", "dependencies": { diff --git a/src/command-parser/expand-npm-wildcard.spec.ts b/src/command-parser/expand-npm-wildcard.spec.ts index e914a350..cd16ae71 100644 --- a/src/command-parser/expand-npm-wildcard.spec.ts +++ b/src/command-parser/expand-npm-wildcard.spec.ts @@ -100,6 +100,22 @@ for (const npmCmd of ['npm', 'yarn', 'pnpm']) { ]); }); + it('allows negation', () => { + readPkg.mockReturnValue({ + scripts: { + 'lint:js': '', + 'lint:ts': '', + 'lint:fix:js': '', + 'lint:fix:ts': '', + } + }); + + expect(parser.parse(createCommandInfo(`${npmCmd} run lint:*(!fix)`))).toEqual([ + { name: 'js', command: `${npmCmd} run lint:js` }, + { name: 'ts', command: `${npmCmd} run lint:ts` }, + ]); + }); + it('caches scripts upon calls', () => { readPkg.mockReturnValue({}); parser.parse(createCommandInfo(`${npmCmd} run foo-*-baz qux`)); diff --git a/src/command-parser/expand-npm-wildcard.ts b/src/command-parser/expand-npm-wildcard.ts index f7128b61..8f6efe1b 100644 --- a/src/command-parser/expand-npm-wildcard.ts +++ b/src/command-parser/expand-npm-wildcard.ts @@ -3,6 +3,9 @@ import * as _ from 'lodash'; import { CommandInfo } from '../command'; import { CommandParser } from './command-parser'; + +const OMISSION = /\(!([^\)]+)\)/; + /** * Finds wildcards in npm/yarn/pnpm run commands and replaces them with all matching scripts in the * `package.json` file of the current directory. @@ -35,8 +38,10 @@ export class ExpandNpmWildcard implements CommandParser { this.scripts = Object.keys(this.readPackage().scripts || {}); } - const preWildcard = _.escapeRegExp(cmdName.substr(0, wildcardPosition)); - const postWildcard = _.escapeRegExp(cmdName.substr(wildcardPosition + 1)); + const omissionRegex = cmdName.match(OMISSION); + const cmdNameSansOmission = cmdName.replace(OMISSION, ''); + const preWildcard = _.escapeRegExp(cmdNameSansOmission.substr(0, wildcardPosition)); + const postWildcard = _.escapeRegExp(cmdNameSansOmission.substr(wildcardPosition + 1)); const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`); const currentName = commandInfo.name || ''; @@ -44,6 +49,14 @@ export class ExpandNpmWildcard implements CommandParser { .map(script => { const match = script.match(wildcardRegex); + if (omissionRegex) { + const toOmit = script.match(new RegExp(omissionRegex[1])); + + if (toOmit) { + return; + } + } + if (match) { return Object.assign({}, commandInfo, { command: `${npmCmd} run ${script}${args}`,