-
Notifications
You must be signed in to change notification settings - Fork 2.5k
feat: Allowing for wildcards in formatter exts #3753
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
base: dev
Are you sure you want to change the base?
Conversation
|
@OpeOginni I think it should just run both of them in that case. I was using a python codebase a while ago and we wanted to run pylint and black on any file edit + save, and then both would run and adjust the code |
|
Okay cool, the this fix should work. Ill do some more testing and maybe make some docs update as well? |
|
@OpeOginni I tested your changes but now formatters don't run in certain cases, ex: .test.ts won't be formatted. I don't think this should be fixed by just adding ".test.ts" to the array either. |
|
@rekram1-node Hmm thats weird, in this case is it that you didnt explicitly add |
|
@OpeOginni im talking about our defaults in formatter.ts But this would also apply to any existing users we dont wanna push breaking changes if we can help it. What do u think makes sense given that constraint? |
|
@rekram1-node Maybe, having a system that checks for any explicit extension combination such as Ig this way only users who want to make use of these specific formatter feature, will be given it, but if a normal user doesnt see the need (not in their config), formatting works as it did before? |
|
I guess we could also have some exclusion... Can we derive the behavior from how editors do this? I'm sure there is an existing UX for best practice if you can point to some examples of how other people do it we should follow one of those "standards" |
|
I tried to get a working logic async function getFormatter(ext: string, fullExt: string) {
const formatters = await state().then((x) => x.formatters)
const possibleFormatters = []
// Step 1: Collect all formatters that could apply to this file
// Include if: direct ext match OR wildcard pattern matches fullExt
for (const item of Object.values(formatters)) {
log.info("checking", { name: item.name, ext, fullExt })
const matches = item.extensions.some(pattern => {
if (pattern.includes("*") || pattern.includes("?")) {
return Wildcard.match(fullExt, pattern)
}
return pattern === ext
})
if (!matches) continue
if (!(await isEnabled(item))) continue
possibleFormatters.push(item)
}
// Step 2: Apply precedence - prefer formatters with explicit fullExt wildcard matches
// Strong: formatters with wildcard patterns that match fullExt (e.g., "*.test.ts")
// Weak: formatters that only match base ext (e.g., ".ts")
// If any strong matches exist, use only those; otherwise use all possible formatters
const strongFormatters = possibleFormatters.filter(formatter =>
formatter.extensions.some(pattern =>
(pattern.includes("*") || pattern.includes("?")) &&
Wildcard.match(fullExt, pattern)
)
)
if (strongFormatters.length) return strongFormatters
return possibleFormatters
}Let me know what you think? Ill try to check if any editor "standards" exists now. |
|
@rekram1-node Was looking at how it is handled by Biome and some prettier plugins, the new logic works, only thing we can add is some sort of "longest matching pattern wins" that Biome implements. In this case if two formatters have extensions as
But based on your answer here, I don't know if thats what we want. In the case of a user not having any wildcards at all, normal |
…and `How it Works`
feat: Allowing for wildcards in formatter extenstions, utilizing already existing Wildcards utils
Solved issue #3431
Tested with this config and it works
{ "$schema": "https://opencode.ai/config.json", "formatter": { "prettier": { "extensions": [".ts"], "command": ["npx", "prettier", "--write", "$FILE"], "enabled": true }, "biome": { "extensions": ["*.test.ts"], "command": ["npx", "@biomejs/biome", "format", "--write", "$FILE"], "enabled": true } } }@rekram1-node I want to ask,