Repository navigation
Print changed file names to stdout; add --null and --name-delimiter #724
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
Changes from all commits
0e16342
b8a7b49
bd04fb5
565b92f
8150175
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,20 +5,56 @@ font.red = font.green = font.gray = (str) => str; | |
|
|
||
| let config: any = null; | ||
|
|
||
| // Same path must not be reported twice (e.g. overlapping globs) | ||
| const reported = new Set(); | ||
|
|
||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No no no. We make sure we dont process the same file multiple times.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 8150175. Dropped |
||
| export const outputConfig = function (_config) { | ||
| config = _config; | ||
| reported.clear(); | ||
| if (config) { | ||
| config.changedNames = []; | ||
| } | ||
| }; | ||
|
|
||
| // Names of files changed in place go to stdout (like grep -l / gofmt -l / prettier --write). | ||
| // config.nameDelimiter is '\n' by default, '\0' with --null, or the custom --name-delimiter. | ||
| // A custom delimiter is joined between names only (no trailing delimiter); see flushChangedNames. | ||
| export const info = function (msg, data = '') { | ||
| if (config.quiet || config.quietTotal) { | ||
| return; | ||
| } | ||
| console.error(font.gray(msg), data); | ||
|
|
||
| const name = | ||
| '' === data || undefined === data || null === data ? String(msg) : String(msg) + data; | ||
| if (reported.has(name)) { | ||
| return; | ||
| } | ||
| reported.add(name); | ||
|
|
||
| if (config.nameDelimiterBetween) { | ||
| config.changedNames.push(name); | ||
| return; | ||
| } | ||
|
|
||
| process.stdout.write(name + config.nameDelimiter); | ||
| }; | ||
|
|
||
| // Write custom --name-delimiter names in one go (no delimiter after the last name) | ||
| export const flushChangedNames = function () { | ||
| if (config.quiet || config.quietTotal || !config.nameDelimiterBetween) { | ||
| return; | ||
| } | ||
| if (config.changedNames && config.changedNames.length) { | ||
| process.stdout.write(config.changedNames.join(config.nameDelimiter)); | ||
| } | ||
| }; | ||
|
|
||
| // Verbose chatter stays on stderr (errors, --verbose, --debug) | ||
| export const chat = function (msg, data = '') { | ||
| if (config.verbose) { | ||
| info(msg, data); | ||
| if (!(config.quiet || config.quietTotal)) { | ||
| console.error(font.gray(msg), data); | ||
| } | ||
| } else { | ||
| debug(msg + ' ' + data); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import {describe, test, expect} from 'bun:test'; | ||
| import fs from 'fs'; | ||
| import path from 'path'; | ||
| import {rr} from './helper.js'; | ||
|
|
||
| describe('--absolute-path', () => { | ||
| test('prints the full path of each changed file', async () => { | ||
| fs.mkdirSync('docs'); | ||
| fs.writeFileSync('docs/a.md', 'foo'); | ||
| const result = await rr('o', 'x', { | ||
| includeGlob: ['docs/*.md'], | ||
| absolutePath: true, | ||
| }); | ||
| expect(result.out).toBe(path.normalize(path.join(process.cwd(), 'docs/a.md')) + '\n'); | ||
| expect(result.err).toBe(''); | ||
| expect(fs.readFileSync('docs/a.md', 'utf8')).toBe('fxx'); | ||
| }); | ||
|
|
||
| test('is not the default: the path is printed the way it was given', async () => { | ||
| fs.mkdirSync('docs'); | ||
| fs.writeFileSync('docs/a.md', 'foo'); | ||
| const result = await rr('o', 'x', {includeGlob: ['docs/*.md']}); | ||
| expect(result.out).toBe('docs/a.md\n'); | ||
| expect(result.err).toBe(''); | ||
| }); | ||
|
|
||
| test('still respects --quiet', async () => { | ||
| fs.writeFileSync('my.file', 'foobar'); | ||
| expect( | ||
| await rr('o', 'x', {includeGlob: ['my.file'], absolutePath: true, quiet: true}) | ||
| ).toEqual({out: '', err: '', exit: null}); | ||
| }); | ||
|
|
||
| test('works with --null', async () => { | ||
| fs.writeFileSync('my.file', 'foobar'); | ||
| const full = path.normalize(path.join(process.cwd(), 'my.file')); | ||
| const result = await rr('o', 'x', { | ||
| includeGlob: ['my.file'], | ||
| absolutePath: true, | ||
| null: true, | ||
| }); | ||
| expect(result.out).toBe(full + '\0'); | ||
| }); | ||
|
|
||
| test('works with --name-delimiter on several files', async () => { | ||
| ['a', 'b'].forEach((name) => fs.writeFileSync(name + '.file', 'foo')); | ||
| const a = path.normalize(path.join(process.cwd(), 'a.file')); | ||
| const b = path.normalize(path.join(process.cwd(), 'b.file')); | ||
| const result = await rr('o', 'x', { | ||
| includeGlob: ['*.file'], | ||
| absolutePath: true, | ||
| nameDelimiter: '|', | ||
| }); | ||
| expect(result.out).toBe(a + '|' + b); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we putting this in a try catch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kept only around
unescapeString, same as the replacement — invalid sequences like\x4need a clean error instead of a stack trace. Fixed in 8150175.