Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve task naming #834

Closed
wants to merge 2 commits into from
Closed

Conversation

jd20
Copy link

@jd20 jd20 commented Apr 5, 2020

A couple improvements to task naming:

  • For function commands, search for first occurrence of a filename argument, and strip from that point onwards.
  • For commands in general, strip common package runner prefixes (and their options): npm, npx, yarn (unless it would strip the entire command).
  • Drop the ellipsis from function commands, to be consistent with non-function commands.

Fixes: #828

Comment on lines +53 to +61
// 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
}
Copy link
Member

@iiroj iiroj Apr 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this. How will it format something like

(files) => `npm run test -- --update ${files.join(' ')}`

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'll format it as run test -- --update. Do you think it makes sense to special-case the run command? Or maybe in general it is going to be too difficult to properly handle package runner commands, without overcomplicating things?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it’s best to leave out stripping those. I’d imagine there’s always some reason to run via npm/yarn instead of directly, so better not hide it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I'll update the PR.

@iiroj
Copy link
Member

iiroj commented Apr 6, 2020

Looks nice, and a good improvement!

Let's just leave out the second bullet of stripping out prefixes to simplify code and not cause unexpected issues (users not recognizing the command).

@iiroj
Copy link
Member

iiroj commented Apr 6, 2020

It seems the path match doesn't quite work on Windows:

- LOG [Function] prettier --write [started]
- LOG [Function] prettier --write [completed]
+ LOG [Function] prettier --write C:\projects\lint-staged-test\AqocQtX4BMGjgyZNYR1jx\test.js [started]
+ LOG [Function] prettier --write C:\projects\lint-staged-test\AqocQtX4BMGjgyZNYR1jx\test.js [completed]

Appveyor logs

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fear this might not work as-is, since the task function can format files.

It might be necessary to do something like:

const fileBasenames = files.map(file => path.basename(file))
const indexOfFile = words.findIndex(word => fileBasenames.some(basename => word.includes(basename)))

to match only the basename (ie. file.js).

This is bound to have performance indications, however.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I also realized tokenizing by splitting on space isn't going to work properly either, if there are spaces inside the filename. Let me revise it a bit more, to try and handle the basename logic above. Is the function formatting files the reason Windows test is failing as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can’t say for sure, though I would think the files available in this method are normalized the same way; apparently not.

@iiroj
Copy link
Member

iiroj commented Apr 6, 2020

Maybe the simplest method would be to, for the string npm run test -- -u src/staged.js, to do:

  1. Get the os path separator from path.sep. Eg. /
  2. Split the command string from this and get the first part, eg npm run test -- -u src
  3. Split the above from the last space and get the first part, eg npm run test -- -u

It should also be try/catched to a short fallback if no path.sep is not found, so that the entire string would not end up in the console.

What do you think?

@jd20
Copy link
Author

jd20 commented Apr 7, 2020

Maybe the simplest method would be to, for the string npm run test -- -u src/staged.js, to do:

  1. Get the os path separator from path.sep. Eg. /
  2. Split the command string from this and get the first part, eg npm run test -- -u src
  3. Split the above from the last space and get the first part, eg npm run test -- -u

It should also be try/catched to a short fallback if no path.sep is not found, so that the entire string would not end up in the console.

What do you think?

Wouldn't that fail for commands with no path separators (staged files in same directory), as well as potentially strip out starting from a non-staged file, such as config?

I'm thinking to tokenize the command (taking quotes into account), then walk through each token, checking for the first one that matches to the staged set (can resolve and compare absolute paths, if we want to be certain it's same file). Then strip from that point onwards. I can optimize the check against the staged set, if we're concerned about perf.

@iiroj
Copy link
Member

iiroj commented Apr 7, 2020

@jd20 You are correct about the failing!

@fantapop
Copy link

@iiroj I'm interested in this as well. I'm Wondering if something simpler like being about to put in a manual override would be better. I'm also wondering why the command is getting cut off in so few characters? It seems like it could afford to go up to the width of the terminal.

@iiroj
Copy link
Member

iiroj commented Apr 27, 2020

@fantapop thanks for the terminal width suggestion! That seems like a pretty easy improvement.

EDIT: Custom names would also be possible, via a static method for example. This would be pretty advanced though:

/** Run eslint –-fix for all JSX files */
const fixJsxFilesTask = (files) =>
  `eslint --fix {files.filter(file => file.endsWith('.jsx')).join(' ')}`
/** Add custom name via the toString method */
fixJsxFilesTask.toString = (files) =>
  `Fix JSX files (matched ${files.length} files)`

module.exports = {
  '*': fixJsxFilesTask
}

@iiroj
Copy link
Member

iiroj commented May 20, 2020

I opened PR #865 which will always take the full length task title (for both "simple" and functional tasks), and then truncates it to the current terminal columns, minus the prefix padding length caused by listr2. This means the task title will be as long as possible to fit on a single line, and will be clipped with an ellipsis .

I'll close this PR since that should be a good enough solution.

@iiroj iiroj closed this May 20, 2020
@fantapop
Copy link

This solution is working great. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Functional tasks do not have meaningful name
3 participants