Open robertohuertasm opened 8 years ago
I would assume it would just require using a different matcher for when the file extension expression is a regexp?
Looking into it now (for about ~5 mins).
From what I can gather, the changes need to be done in [vscode-icons]((https://github.com/vscode-icons/vscode-icons) in iconGenerator.ts
defs[iconFolderDefinition] = {
iconPath: `${folderPath}${sts.iconSuffix}${iconFileExtension}`,
};
The iconFileExtension
should not be taken directly from the icon JSON config loaded but be calculated on match from expression (if detected to be an expression and not a simple file extension!)
L37:
const iconFileExtension = utils.fileFormatToString(current.format);
Should instead be sth like
const iconFileExtension = utils.firstExtensionMatch(current.format, iconExprMatches);
Should somehow use data gathered from the extensions
list (which should be able to take reg expressions or perhaps mappings of the form {"svg": "*.svg$")
current.extensions.forEach(extension => {
const key = extension;
names.folderNames[key] = iconFolderDefinition;
names.folderNamesExpanded[key] = iconOpenFolderDefinition;
light.folderNames[key] = hasLightVersion
? iconFolderLightDefinition
: iconFolderDefinition;
light.folderNamesExpanded[key] = hasLightVersion
? iconOpenFolderLightDefinition
: iconOpenFolderDefinition;
});
Instead should be sth like:
current.extensions.forEach(handleExtensionConfig)
function isSimpleExtension(extension) {
return typeof extension === 'string'
}
function isRegExprMappingExtension(extension) {
return typeof extension === 'object'
}
function handleExtensionConfig(extension) {
extension => {
if (isSimpleExtension(extension)) {
// old simple extension handler code
return
}
if (isRegExprMappingExtension(extension) {
// use regexp mapping to define more complex key entry to match on
return
}
console.error('BAD icon extension definition', extension)
// ignore bad entry?
}
The iconGenerator
tests then also need to be extended with such functionality, similar to:
it('new file extensions are included into the manifest', function() {
const custom = emptyFileCollection;
custom.supported.push({
icon: 'actionscript',
extensions: ['as'],
format: 'svg',
});
const json = iconGenerator.generateJson(custom, emptyFolderCollection);
const def = `${settings.manifestFilePrefix}actionscript`;
const ext = json.iconDefinitions[def];
expect(ext).to.exist;
expect(ext.iconPath).not.to.be.empty;
expect(json.fileExtensions['as']).to.be.equal(def);
});
To sth like:
custom.supported.push({
icon: 'actionscript',
extensions: [{as: ["y.as", "x.as"]}],
format: 'svg',
});
Or perhaps even taking regexp expr:
as: ["*.as"]
}, "bs", {
//...
}],
What do you guys think?
@deiga Why not define in your user settings:
"files.associations": {
"docker-compose.*.yml": "dockerfile",
"Dockerfile.*": "dockerfile"
},
@aeschli Great to see you can just define file associations. Not well documented I guess ;) Still I think vscode icons should be updated to support mappings of the sort I sketched out above.
@kristianmandrup the icons extensions must generate a final json with all mapped extensions, and that's what vscode will use in order to do the mappings. This is a well defined api and there's no support for regex at all. So trying to somehow convert a regex to all possible candidates that would match would be not feasible (imagine to have to provide matches for *.yml
)
As a temporal solution you have the one that @aeschli provided (which associates some files to a file type, so it wouldn't work for not supported language ids I guess) or you can use our customization options, which would allow you to associate any kind of extension to the icon you want (but still without the power of globs because the JSON that vscode expects doesn't support it - and hence this issue still stands).
@aeschli Awesome, didn't know that was possible!
Now we need to figure out how to build a system that wouldn't require custom rules for sensible defaults :)
I tried @aeschli suggestion with binary
and can't get it working. Is there a list of available files.associations
?
"files.associations": {
"*.{dist,disabled}": "binary"
},
+1
Is it dead ? is there no way to do this ?
I tried @aeschli suggestion with
binary
and can't get it working. Is there a list of availablefiles.associations
?"files.associations": { "*.{dist,disabled}": "binary" },
@muuvmuuv There is a list in the docs.
Could the directory also be exposed in the File Icon API? (Moved to new issue)
+1 Want to have different icons for python files *.py
and python tests test_*.py
+1
Because this should be a new issue.. I opened #136656 for anyone interested in support of folder/directory name in file association.
@aeschli is this still open in the backlog? Is there anything that can be done to help it along? It's been five and a half years. Is it likely to be done?
We have no plans for implementing this future. It doesn't go well with the current implementation of file icons based on matching CSS rules and would require a rewrite.
We have no plans for implementing this future. It doesn't go well with the current implementation of file icons based on matching CSS rules and would require a rewrite.
@aeschli Could be a way to specify the extension separator? For example see: https://github.com/PKief/vscode-material-icon-theme/issues/1598
A posible solution for that could be change the default separator '.' to another special character like '_' or '-'
It doesn't go well with the current implementation of file icons based on matching CSS rules and would require a rewrite.
Correct that file icon theme consumption and icon CSS class logic is separate:
File icons would probably suffer an FOUC if the two interacted, because the entire vscode-icons
file icon theme would be recomputed again for a simple action like a folder open.
(Take $n$ as the number of dot segments in a filename.)
There are two possible approaches and both need new data (1.
is super ugly IMHO and should be avoided):
.ext
, [class*=]
and :not([class*=])
that can match that glob. That can be formalised as some kind of algorithm, but the testing and maintainability cost would be high. Also *=
attribute selectors are brittle.webpack.dev.config.json
you'd have 16 relevant results..)We also would want **
to match $n>=1$-segment matching instead of $n>=0$
(So **
= *
, *.*
, *.*.*
)
Because otherwise we'd be increasing our big-O $N$ by $0.5$.
Proof of concept, $O(N)$ linear solution for getIconClasses.ts
:
// Prefix-matching coalescing globs and non-coalescing wildcard globs
function getIconClassesForSomeGlobs(name) {
// remove ellipsis + chars >=255 to defend against explosive combination
// https://github.com/microsoft/vscode/issues/116199
const dotSegments = name.slice(-255).replace(/\.\.+/g, '').split('.');
const lastDotIndex = dotSegments.length - 1;
const globs = [];
for (let i = 0; i < lastDotIndex; i++) {
const suffix = dotSegments.slice(0, i + 1);
suffix.push(i < lastDotIndex - 1 ? '**' : '*');
globs.push(suffix.join('.'));
const base = dotSegments.slice();
base.splice(i, 1, '*');
globs.push(base.join('.'));
}
return globs;
}
This is the $O(c^N), c = 2$ solution:
// All globs matching a file name, excluding globs with chained `*` segments
function getIconClassesForAllGlobs(name) {
// remove ellipsis + chars >=255 to defend against explosive combination
// https://github.com/microsoft/vscode/issues/116199
const dotSegments = name.slice(-255).replace(/\.\.+/g, '').split('.');
const globs = []
const bitmask = Math.pow(2, dotSegments.length) - 1;
for (let i = 0; i < bitmask; i++) {
let buffer = [];
for (let j = 0; j < dotSegments.length; j++) {
buffer.push(i & Math.pow(2, j) ? dotSegments[j] : '*');
}
globs[i] = buffer.join('.').replace(/(?<=\*)(?:\.\*)+/, '*'); // coalesce chained * filename segments into **
}
return globs;
}
@aeschli now that this is feasible - run this replit to see - there are two questions here:
iconLabel.ts
be able to generate data attributes? Then fileIconThemeData.ts
could do [data-glob~=glob]
. getIconClasses
function sending out 50+ selectors suffixed with -glob-file-icon
is not sane to me.getIconClassesForSomeGlobs
) is ideal and getIconClassesForAllGlobs isn't? The replit shows how the first function outputs a limited subset of the original.Noting here - filenames with 5 or more dot segments are consistently considered "weird" and we're not losing much with the $n < 5$ limit explained in https://github.com/microsoft/vscode/issues/12493#issuecomment-1382322653.
You must allow patterns on the icon issue.
I guess you think this can be achieved with extensions but there are exceptions. In Golang, test files must end with _test
. Click for detailed information.
Golang related test documentation:
I want to add a corresponding icon to my go files ending with_test
pattern. But vscode api doesn't accept a fileNames value like *_test
. We cannot achieve this with fileExtensions. Goland, an alternative to vscode, provides this. I think vscode should provide it too.
I'm open to feedback.
It is possible to do name._test.go
for now it seems, so fileExtensions works for Go. Doesn't work for test_*.py
in Python.
vscode-icons/vscode-icons#2754 explains that this use case has significant A11Y benefit for dyslexia.
As I understand it, we have (maybe past tense now) a significant blocker:
File icons would probably suffer an FOUC if the two interacted, because the entire
vscode-icons
file icon theme would be recomputed again for a simple action like a folder open.
My suggestion was to generate globs on the CSS service side, and those get targeted in file icon theme.. but this needs the assignee's input (plus core team has other work to do).
I threw together code for your use case still - see maybePushBasenameDashGlobs
function in the replit.
I've implemented the feature at #174286.
Please take a look at new spec - https://github.com/microsoft/vscode/pull/174286#issuecomment-1464506764 - and see if you have suggestions
The PR will probably be tested during the March or April 2023 iteration - when the assignee gets time.
Huge thanks to them for their early reviews also 👍
Also affected by this.
"material-icon-theme.files.associations": {
"tsconfig.*.json": "tsconfig"
},
"material-icon-theme.files.associations": {
"tsconfig.rollup.json": "tsconfig"
},
See vscode-icons #328
This will allow to support a very common scenario which is a filename with small variations depending on environments: