From feb74b246c65ce77e6f9833454bc72dda35a4395 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 30 Jan 2022 18:09:41 -0500 Subject: [PATCH 1/4] Support Exclude patterns. Resolves https://github.com/open-cli-tools/concurrently/issues/305 --- package-lock.json | 1 + src/command-parser/expand-npm-wildcard.spec.ts | 16 ++++++++++++++++ src/command-parser/expand-npm-wildcard.ts | 17 +++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) 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}`, From 0560675be27d17a693689bb47ef2df42f1e91d00 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 6 Feb 2022 18:14:44 -0500 Subject: [PATCH 2/4] Readme updates --- README.md | 30 ++++++++++++++++++++++++++---- bin/epilogue.ts | 4 ++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2a095775..15a8435d 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,28 @@ 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 +326,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 +344,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..51c76061 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)"' } ]; From 7ef31fadc0e69fb1f23624d043e4be584295d6f2 Mon Sep 17 00:00:00 2001 From: Gustavo Henke Date: Sat, 26 Feb 2022 11:50:17 +1100 Subject: [PATCH 3/4] fix indentation --- bin/epilogue.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/epilogue.ts b/bin/epilogue.ts index 51c76061..59a7ee82 100644 --- a/bin/epilogue.ts +++ b/bin/epilogue.ts @@ -51,8 +51,8 @@ const examples = [ 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)"' + description: 'Exclude patterns so that between "lint:js" and "lint:fix:js", only "lint:js" is ran', + example: '$ $0 "npm:*(!fix)"' } ]; From 1bab9bb26c3f19b3277d1bd9fef90a51e8a39ef6 Mon Sep 17 00:00:00 2001 From: Gustavo Henke Date: Sat, 26 Feb 2022 12:02:59 +1100 Subject: [PATCH 4/4] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 15a8435d..15e42a64 100644 --- a/README.md +++ b/README.md @@ -129,8 +129,6 @@ Exclusion is also supported. Given the following scripts in package.json: 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: @@ -326,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. @@ -348,7 +346,7 @@ It has the following properties: - `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.