diff --git a/lib/makeCmdTasks.js b/lib/makeCmdTasks.js index 2b1682f3c..0f3bdfa1e 100644 --- a/lib/makeCmdTasks.js +++ b/lib/makeCmdTasks.js @@ -27,25 +27,42 @@ module.exports = async function makeCmdTasks({ commands, files, gitDir, shell }) const resolvedArray = Array.isArray(resolved) ? resolved : [resolved] // Wrap non-array command as array for (const command of resolvedArray) { - let title = isFn ? '[Function]' : command + let title = isFn ? '[Function] ' : '' - if (isFn) { - // If the function linter didn't return string | string[] it won't work - // Do the validation here instead of `validateConfig` to skip evaluating the function multiple times - if (typeof command !== 'string') { - throw new Error( - createError( - title, - 'Function task should return a string or an array of strings', - resolved - ) + // If the function linter didn't return string | string[] it won't work + // Do the validation here instead of `validateConfig` to skip evaluating the function multiple times + if (isFn && typeof command !== 'string') { + throw new Error( + createError( + title.trim(), + 'Function task should return a string or an array of strings', + resolved ) + ) + } + + const words = command.trim().split(' ') // Tokenize the command into words + + if (isFn) { + const indexOfFile = words.findIndex(word => files.includes(word)) // index of first file in the command + if (indexOfFile >= 0) { + words.splice(indexOfFile) // Strip staged files from command } + } - const [startOfFn] = command.split(' ') - title += ` ${startOfFn} ...` // Append function name, like `[Function] eslint ...` + // For the title, strip package runner commands (npm/npx/yarn) from the beginning + if (words.length > 0 && ['npm', 'npx', 'yarn'].includes(words[0])) { + let idx = 1 + while (idx < words.length && (words[idx] === '' || words[idx].startsWith('-'))) { + idx += 1 // Remove any options to the package runner command + } + if (idx < words.length) { + words.splice(0, idx) // Make sure we don't strip the entire command + } } + title += words.join(' ') // Append formatted command, like `[Function] eslint` + cmdTasks.push({ title, command, diff --git a/test/makeCmdTasks.spec.js b/test/makeCmdTasks.spec.js index b88f290d4..e6e61ea38 100644 --- a/test/makeCmdTasks.spec.js +++ b/test/makeCmdTasks.spec.js @@ -61,7 +61,7 @@ describe('makeCmdTasks', () => { it('should work with function task returning a string', async () => { const res = await makeCmdTasks({ commands: () => 'test', gitDir, files: ['test.js'] }) expect(res.length).toBe(1) - expect(res[0].title).toEqual('[Function] test ...') + expect(res[0].title).toEqual('[Function] test') }) it('should work with function task returning array of string', async () => { @@ -71,8 +71,8 @@ describe('makeCmdTasks', () => { files: ['test.js'] }) expect(res.length).toBe(2) - expect(res[0].title).toEqual('[Function] test ...') - expect(res[1].title).toEqual('[Function] test2 ...') + expect(res[0].title).toEqual('[Function] test') + expect(res[1].title).toEqual('[Function] test2') }) it('should work with function task accepting arguments', async () => { @@ -82,8 +82,35 @@ describe('makeCmdTasks', () => { files: ['test.js', 'test2.js'] }) expect(res.length).toBe(2) - expect(res[0].title).toEqual('[Function] test ...') - expect(res[1].title).toEqual('[Function] test ...') + expect(res[0].title).toEqual('[Function] test') + expect(res[1].title).toEqual('[Function] test') + }) + + it('should strip arguments regardless of order', async () => { + const res = await makeCmdTasks({ + commands: filenames => `test ${filenames.reverse().join(' ')}`, + gitDir, + files: ['test.js', 'test2.js'] + }) + expect(res.length).toBe(1) + expect(res[0].title).toEqual('[Function] test') + }) + + it('should strip package runner commands', async () => { + const res = await makeCmdTasks({ + commands: [ + filenames => `yarn test -o --watch ${filenames[0]}`, + filenames => `npx --no-install test ${filenames[0]}`, + filenames => `npm --version ${filenames[0]}` + ], + gitDir, + files: ['test.js'] + }) + const [cmd1, cmd2, cmd3] = res + + expect(cmd1.title).toEqual('[Function] test -o --watch') + expect(cmd2.title).toEqual('[Function] test') + expect(cmd3.title).toEqual('[Function] npm --version') }) it('should work with array of mixed string and function tasks', async () => { @@ -93,17 +120,17 @@ describe('makeCmdTasks', () => { files: ['test.js', 'test2.js', 'test3.js'] }) expect(res.length).toBe(5) - expect(res[0].title).toEqual('[Function] test ...') + expect(res[0].title).toEqual('[Function] test') expect(res[1].title).toEqual('test2') - expect(res[2].title).toEqual('[Function] test ...') - expect(res[3].title).toEqual('[Function] test ...') - expect(res[4].title).toEqual('[Function] test ...') + expect(res[2].title).toEqual('[Function] test') + expect(res[3].title).toEqual('[Function] test') + expect(res[4].title).toEqual('[Function] test') }) it('should work with async function tasks', async () => { const res = await makeCmdTasks({ commands: async () => 'test', gitDir, files: ['test.js'] }) expect(res.length).toBe(1) - expect(res[0].title).toEqual('[Function] test ...') + expect(res[0].title).toEqual('[Function] test') }) it("should throw when function task doesn't return string | string[]", async () => { diff --git a/test/runAll.unmocked.spec.js b/test/runAll.unmocked.spec.js index 3a7a82217..617a1597a 100644 --- a/test/runAll.unmocked.spec.js +++ b/test/runAll.unmocked.spec.js @@ -770,8 +770,8 @@ describe('runAll', () => { LOG Preparing... [completed] LOG Running tasks... [started] LOG Running tasks for *.js [started] - LOG [Function] git ... [started] - LOG [Function] git ... [completed] + LOG [Function] git stash drop [started] + LOG [Function] git stash drop [completed] LOG Running tasks for *.js [completed] LOG Running tasks... [completed] LOG Applying modifications... [started] @@ -992,8 +992,8 @@ describe('runAll', () => { LOG Hiding unstaged changes to partially staged files... [completed] LOG Running tasks... [started] LOG Running tasks for *.js [started] - LOG [Function] prettier ... [started] - LOG [Function] prettier ... [completed] + LOG [Function] prettier --write [started] + LOG [Function] prettier --write [completed] LOG Running tasks for *.js [completed] LOG Running tasks... [completed] LOG Applying modifications... [started]