Atom: User-configurable icon-configs: Worth it?

Created on 22 Jul 2017  Â·  17Comments  Â·  Source: file-icons/atom

"What?"

I've opened this for discussion and feedback regarding a feature I've contemplated adding for a while now: the possibility for users to define their own icon-matching rules, which would greatly simplify the process of adding an icon to multiple paths. Moreover, it would give users an opportunity to replace filetypes they don't like or use with ones more relevant to their interests.

v2.0 introduced the ability to assign icons by customFileTypes, but this isn't an exhaustive solution for several reasons:

  1. It forces users to define new language-by-extension mappings for the sake of showing an icon.
    Fiddly at best, excessive at worst. Not to mention not every user wants the language-per-filetype association in their editor.

  2. The customFileTypes setting only accepts fixed strings for matching filetypes.
    E.g., php for matching *.php files, but not php[0-4] or even *.php. No globbing, no regex, and no directory-specific matching is possible. For any user looking to map icons by directory, it's back to the old-school CSS solution.

  3. The config setting itself is somewhat secluded.
    Even though it's been supported by Atom for a while, there's no corresponding panel in the Settings View, which means it isn't immediately obvious to everybody.

Our icon-config

I developed the config format intending to make it open-ended and extendable, but later decided it wouldn't be worth the "added complexity" (see 7b2f897 for my thoughts on that...).

Lately, however, I've been reconsidering. Users will still have their stylesheets, of course, and that will always take precedence over everything else, but being able to hook into the regex-powered monolith that's driving this package would give power-users a much cleaner alternative to stylesheet stuffing:

~coffee
# Unoriginal example:
"Obscure Templating Language":
icon: "mystery"
match: /mystery/.*?/templates\/.+.html?$/i
matchPath: true
colour: "medium-blue"
~

The above rule would add the mystery-icon and medium-blue classes to any html or htm file located in a descendant directory of a folder named mystery. Certainly not a common scenario, but we all know how excessive and ugly the equivalent Less code would need to be to achieve a similar effect.

Admittedly, another reason justifying user-configurable icon-configs is that since v2.0, styling icons for filetypes is much more cumbersome (sorry guys, it's a necessary evil). There's more copy+pasta of font-sizes, colours, font-families, etc... and adding icons by its raw codepoint isn't exactly fancy, either.

"So what's the freaking problem? Add it already!"

It's been my experience that all code boasts no more than two of three properties:

  • Writability: Power packed in a few keystrokes - Perl, awk, sed, shell-scripts, APL, etc
  • Readability: Clean, sensible and reader-friendly - Markdown, Python, etc
  • Regularity: The code is sane. Logical, well-structured, and enforces a pattern - C, Assembly, Lisp, Fortran, etc

Right, well... our config has a perfect balance of both writability and readability. Hairy regex notwithstanding.

It suffers in the regularity department: e.g., how many people can really follow the config's format? I often feel like I'm the only one who knows what the hell is going on in there. Truth be told, there's a lot that's happening, and it's difficult to explain how it unfolds to generate the compiled icon lists loaded at startup.

So my current reservations lie with... well, not knowing how to present this to the majority of users, and how to stress that this is more geared for hacker-type users familiar with regex, and not a common replacement for one's stylesheet....

Man, I hope this rambling crap's made sense.

/cc @DanBrooker
/cc @MiracleBlue - For reminding me about the unpleasantness of codepoint-copypasta
/cc @50Wliu - Because you're a hell of a lot better at making balanced, realistic decisions than I'll ever be

discuss enhancement

Most helpful comment

@Alhadis you really don't need my say so, this project is more yours than mine at this point. Do whatever you think is the right move.

All 17 comments

I think making customisable icons user friendly is going to be very difficult without extensive UI, so therefore it's going to tend to be config files or code addons.

Perhaps a solution for the less technical user is some examples/wiki where they can copy paste common substitutions

I think this is a cool feature on paper. Will I use it? Probably not. Will most people even be aware of it? Probably not. Are there any examples of people going "ugh, if only I could customize the file icons"?

Basically: will this be worth the upfront and maintenance costs?

Well, we certainly wouldn't be advertising it for casual use. And you're right: 90% of this package's users would hardly even notice, if not more. That still leaves potentially hundreds of hacker-type users who might gain mileage from it.

@DanBrooker It would definitely have to wait until the rest of the package's details are properly cleaned and documented. With "properly cleaned" being a task blocked on the _Eternal Five Pull Requests_, hereafter known as "The Eternal Five".

@50Wliu In the package's current state, it wouldn't be worth the complexity, but only because synchronous activation is necessary to patch packages at startup. Once that becomes a thing of the past, I can work on making everything async, which is guaranteed to have a tremendous reduction on startup time. But I digress...

It's good that I'm getting feedback now, rather than later. When I am in a position to be formalising more of the internals, it won't be changing without some damn good reasons.

Haaaaaaaah, I half-jokingly thought of documenting every "advanced" customisation topic in the form of a manpage, so only technically-inclined users will find it.

... hrrm, not a bad idea, actually. =) man 7 file-icons; guess I'll look for any excuse to write up a manual-page (because the world should seriously stop using Markdown for generating this shit, I swear to POD...)

Ahhh damn it I missed out on this one just barely! Damn my tonsillitis! Sorry buddy! I have ideas and suggestions, though, if I ever stop my own tonsils from killing me, I must remember to share them with you.

No rush, spill your guts then! (So to speak...)

Get well soon!

I think this would be a useful feature, but honestly I'm not sure if it's worth you putting in the effort refactoring to make it possible. I would like knowing that I could customize it to this extent if I ever needed to, but I can't promise that I ever will, and I feel like that would be the case for most people.

I guess I say go for it if you want to but it probably doesn't need to be a huge priority.

This might be worth moving to an NPM module after all. See #641; @thisconnect suggested this should be published as a standalone Node module, which seemed a bit excessive to me at first... but the more I give it thought, the more sense it makes:

  1. It separates the package's main userbase from the hacker/power-user types. If users want to get their hands dirty, they can refer to the module's actual documentation.

  2. The config.cson file is repeatedly referred to as "the config CSON file", and it's driving me crazy. Having a name for the frigging thing like file-tome or something would make referencing my work a lot easier (I admit the namelessness of the file has kinda bugged me for a while, because "config" could mean virtually frikkin' anything until you opened it).

  3. The amount of data accumulated in the "FileTome" is already huge. Node developers could be using that to their advantage for front-end work, and some poor bastard already took it on himself to take the compiled version and make it loadable by a browser.

  4. Moving this to a module would also clean up the mess in the package's lib directory... specifically, the logic dedicated to compiling the icon definitions into readable JavaScript.

Alright, here's the roadmap for 2018:

1․ Publish to npm

There's simply too much good stuff locked up in config.cson, and it's only reasonable to assume it's going to keep growing in the amount of information it contains. Because of how closely file-icons tracks updates made to GitHub's Linguist, we'll always have a wealth of format-related data of potential use outside Atom.

2․ The data stays here Screw that. Time to make this portable!

UPDATE: Changed my mind, largely due to the unpredictable hostility of apm and recent shit-fighting with npm (which has major DWIM issues). See my comment further down the page.

I'm reluctant to move the config to its own repository, because file-icons is already split into 3 or 4 separate repositories as it is. Heck, it's already confusing to contributors on where to send a PR to have a new icon added.

What I'm considering is publishing file-icons to NPM under the name file-icons itself. This sly hack will depend on the generosity of @basarat to transfer ownership of the currently-registered file-icons package (which... actually seems to be "officially" registered as fileicons instead, sans hyphen). Once transferred, we can leverage .npmignore and export-ignore attributes to filter Atom and NPM-specific files, respectively.

There shouldn't be any compatibility issues here, but given APM and NPM's flaky histories, I can't be certain. @50Wliu, I'm paging you in case you know of a time when homogenous package registrations has caused complications in the past, or something. E.g., APM downloading the package tarball from NPM instead of atom.io, or something to that effect.

3․ Replace .icondb.js with a compact binary representation

Reading, parsing and evaluating a huge-ass array isn't an efficient way of loading the package's database. Doing a single-pass evaluation of a bytestream with full control over serialisation and hash tables presents an interesting opportunity to improve performance. The reduction in filesize and elimination of hideous but inevitable diff-noise make this a tempting solution.

Obviously, the format will need to be very well-documented if it has any hope of making sense to future maintainers, which I wholeheartedly hope to do. Along with everything else I've yet to finish doing for this package which I'm behind on.

@DanBrooker You have the final say on what I can and can't do, so it's up to you to give the green light.

There have been issues in the past with apm attempting to install the react package from npm instead of from apm. I also found atom/apm#742.

@Alhadis you really don't need my say so, this project is more yours than mine at this point. Do whatever you think is the right move.

Excellent, thanks. :grinning:

@50Wliu That shouldn't be a problem then, because the problem appears to be the fault of having an NPM dependency of the same name as the Atom package requiring it.

We won't be adding another dependency; in fact, this package doesn't even have to know that an NPM-hosted subset of its codebase even exists. It's simply a case of selective publication made possible only through stupid luck.

Guys, I'm gonna do a full rewrite of the package, now that we're in a position to make everything async. It won't be Atom-specific: it'll be a set of Node modules (albeit monolithic in nature). I'm still a far ways off from starting work on it (I'm still wrapping up some lingering existing projects...), but we'd be looking at something like this:

  • atom-fs: Re-engineered to be a general-purpose Node library for filesystem interaction. Its name can therefore be considered short for "Atomic filesystem", rather than "Atom's filesystem".

  • [file-icons-core]: Basically, most of lib/service with editor-specific logic ripped out and left in this repository. I originally planned on "dual-publishing" this repo to NPM under the same file-icons name, but recent shit-fighting with apm and npm has left me reluctant to try any "tricks" concerning release publication.

  • file-icons-db: Uncertain if the config.cson file and its compiler should be separated from file-icons-core, or bundled with it. I'm currently leaning towards the latter. However, given the complexity of a custom binary format and the code to compile it from CSON, it might benefit from being a standalone library. Thoughts?

It goes without saying, but no breaking changes will be made that require action from users or package authors. 😉 The only change anybody might notice is that icons are displayed asynchronously, rather than blocking the event loop. This is probably the biggest contributor to the package's sluggish startup time (which has always been a thorn in my side).

@DanBrooker I'm assuming VS Code supports NPM modules being loaded as dependencies, right? If so, keeping the VS Code plugin in-sync will be orders of magnitudes easier. 😉

Also, does anybody know if Sublime Text uses NPM modules? Or if any other editors might benefit from this?

@Alhadis I think VSCode does, but the current solution exports a lists of file extensions and icons using a js script so an npm module would work nicely

I've taken a few stabs at refactoring the code to be async (or at least portable), but so much of it is heavily tied to the DOM (not to mention much of the code is still reliant on synchronous execution). Basically, I'm concerned about breaking shit: the codebase is already delicate as it is...

Still tossing up how I'm gonna approach this. 😞

Alright. Gonna close this, because it's just one part of a much bigger picture:

file-icons needs to evolve. Our huge-ass filetype database and sophisticated matching logic is wasted on a single editor. No more unofficial ports or wonky reimplementations. We need to do this properly. Plain ol' JavaScript, powering a build chain for compiling both fonts and editor-specific icon lists, tailoring it to the limitations of the platform in question. The work I've done will obviously need to be extensible, so the question _"should we build on this package's config format?"_ becomes redundant and obvious.

@DanBrooker I've created a file-icons org on NPM, which gives us a scope for publishing modules with names symmetrical to GitHub:

~js
const iconTables = require("@file-icons/db"); // => https://github.com/file-icons/db
const {Strategy} = require("@file-icons/core"); // => https://github.com/file-icons/core
~

Let me know what your NPM username is (if any) and I'll add you to the org. =)

Was this page helpful?
0 / 5 - 0 ratings