1. 13

    I couldn’t upvote this fast enough. The now-dominant consensus and ideology of UX, whatever we’re calling it, is making astonishing progress at destroying every shred of reasonable consistency and well-tested convention across every interface surface I can think of aside from, maybe, the terminal and CLI tooling.

    1. 5

      The now-dominant consensus and ideology of UX, whatever we’re calling it,

      That one is easy: if people know what they’re talking about, they call it HCI. If they don’t know what they’re talking about, they call it UX. It’s a great filter word. As soon as someone starts talking about UX, you immediately know that they have no understanding of cognitive psychology, won’t be able to cite any research to back up their assertions, and have are highly unlikely to have any opinions worth listening to.

      Good usability is hard. It’s a global optimisation problem. The worst thing that’s happened to software in the last two decades is the rise in people who think usability is an art and not a science.

      Anyone thinking of designing an interface (including an API, so pretty much anyone writing any software) should read The Humane Interface. Some of the things that Raskin says are a bit dated (for example, his discussion of Fitts’ Law doesn’t cover how the concepts apply to touchscreens) but most of them are still good guiding principles (especially Raskin’s First Law: a program may not harm a user’s data or, through inaction, allow a user’s data to come to harm).

      1. 5

        And any UI designer reading this will be so triggered they will raise their shields and never consider returning to the past.

        I doubt there’s an effective way of getting the point through that these modern UIs are garbage.

        1. 3

          CLI tooling is not exempt, either. See: a million node js tools that joyfully barf ANSI escape sequences or ‘reactive’ progress bars into their output, even when it’s not a TTY.

        1. 1

          I’ve had 3 Noppoo Choc, 2 Mid and 1 Mini, and a Mid has been my daily driver at work, the one I am currently using for the last 7 years. It’s the best mechanical keyboard I have ever owned, but my experience is not that vast. I might buy my coworker’s Ducky One, because it has a numpad and he wants to get something else anyway, but maybe I’m not enough of an keyboard aficionado to care that much - I prefer MX black but would like to try out reds for a prolonged time. That’s the important thing for me, blue is completely out and browns are ok for gaming.

          This list is still up to date: https://f5n.org/blog/2018/mechanical-keyboards/ but I backed https://www.kickstarter.com/projects/keyboardio/atreus and am waiting for the summr now.

          1. 1

            Haha nice, if I had a new backup keyboard I’d send you my Choc Pro for you to add to your collection.

            1. 1

              I have 2 noppoo choc’s (one brown and one blue), and while I absolutely love the layout, both have been acting up lately, with double (or triple) key activations. Blowing into the depressed switches with compressed air helps for a while, but then the glitching returns. ‘E’, ‘R’, ‘T’ and the space bar are the worst offenders.

              There seems to be an absolute death of compact mechanical keyboards with a short space bar (space bar should extend from beneath the ‘C’ key and end flush with the ‘M’ key). I would love a mechanical keyboard with the same layout as a thinkpad or dell xps: short spacebar and all F keys easily accessible without mode switches.

            1. 4

              What does the expression at the end mean?

              Looking at the manual it looks like | is Max/Or. I also saw that |/ is defined as “Max-Over”?

              1. 7

                It’s the K implementation of the algorithm above. Find the max of a list of numbers.

                1. 1

                  Ah, for some reason I thought it was a pun to the effect of “hah, you noobs”.

                2. 6

                  | is max. It’s also boolean or. If you wanted the minimum, it’d be &/, because & is min/boolean and.

                  The APLs have teased apart lots of common operations into atomic parts that combine cleanly, sometimes unpacking them further than other languages go. The single-argument form of & (“where”) is a good example:

                    &1 2 3
                  0 1 1 2 2 2
                  

                  It counts up, repeating each successive number based on the next number in the argument.

                    &5 5 5
                  0 0 0 0 0 1 1 1 1 1 2 2 2 2 2
                  

                  Okay, so that makes the pattern clearer. By why is that useful?

                    & 0 0 0 1 0 1 1 0 1 0
                  3 5 6 8
                  

                  Ah ha – “what are the offsets of the 1s?”

                    x:10?!1000    / draw 10 random numbers 0 to 999
                    x             / print them
                  379 998 594 106 191 686 123 845 495 700
                    x < 500       / what values are less than 500
                  1 0 0 1 1 0 1 0 1 0
                    x[&x<500]     / slice x by indices where x is less than 500
                  379 106 191 123 495
                  

                  So it combines with a conditional to become a sort of SELECT, but it also combines with other operators in a predictable way, and the implementation is straightforward.

                  1. 1

                    Thank you! I was stumped as to what the where usage of & is for. This is a great explanation.

                1. 5

                  I agree 100% with the author, and day-to-day I use my emacs color scheme that’s designed to emphasize the “information-dense” parts of code: function declarations (not callsites!) and comments.

                  One problem I see is that there are languages/methodologies out there that assume your editor will de-emphasize comments, for example. I think the case for minimalist syntax highlighting (or none whatsoever) can only be made in good faith in the case of information-dense languages/coding styles.

                  1. 7

                    Nix

                    1. 4

                      There is something to this the author did not point out. Typing faster is less frustrating than slow typing when you feel the flow. Faster typing enables faster use of tools, even if the mouse were occasionally involved.

                      Depending on your programming language and tools, faster typing allows you to “think out loud” in code and tests. It may even drive you to make the dev cycle faster.

                      Pair programming is more fun and efficient when you don’t spend time on slow typing, and eventually you may even talk while writing out the code, like a singing instrumentalist.

                      And in a lot of work, any task really isn’t that unique. Doodle some diagrams and start prototyping by typing fast.

                      Contemplate old code and fix it by typing fast.

                      Even if the seconds saved never amount to much real time, there’s an energy to it that should not be discounted.

                      1. 3

                        I agree with all your points – there is a certain energy that abounds when someone masters their tools and can operate with fluency in the physical world. I personally don’t think it should be a subject of controversy that proficient use of the primary computer input device makes one a more proficient user of the computer – it’s easier to get into a flow state, it’s easier to use tooling, and it’s easier to communicate with others.

                        If you’re a faster typist, you might find it easier to spare a couple seconds writing that email to a remote colleague that might just flip their day from bad to good. You might spare a couple seconds to comment that tricky bit of code before moving on. You might spare a couple seconds typing out repetitive test cases instead of DRYing them prematurely and making others cry when they have to add functionality. If typing feels like a slog, you’re going to be more stingy with written communication in general.

                        But, I also have a meta-comment about topics like this. People who aren’t fast typists will be the ones piping up in the comments about how typing speed doesn’t matter, and those who type well will say that it does matter. Confirmation bias is a thing, and ultimately I think it comes down to aesthetics. I know a couple of programmers who are atrocious typists—to the point that watching them type is painful—but are excellent at programming and ultimately very productive. Maybe they just don’t feel they need the ‘energy’ that comes with mastery of physical movement?

                        1. 3

                          These are some great additions to the discussion. Having less of that barrier as you said may also result in you being more likely to communicate when you otherwise wouldn’t have because it’d have been such a slow and tedious response as a slower typist. Stuff like this is very difficult to measure because essentially it all happens in the mind and perhaps unconsciously for many.

                          I also agree with the point about confirmation bias. Of course I say you should type faster because I do type relatively quick. My colleagues who type quick also say this. My colleagues who don’t type quite so fast tend towards finding it less important. Either way it could be post ad hoc rationalization.

                        2. 3

                          This is a great point and highlights how I feel, and I didn’t include it in the article!

                          For example; I find it very difficult to even get into a flow state when typing on my phone, where I probably get something like 50 WPM, simply because it feels so frustrating. Even talking to people on my phone via typing feels so frustrating I often can’t be bothered.

                          Whereas on a real keyboard, I’m far more likely to take the time to reply to people or write more complicated responses because that barrier is so much less existent.

                        1. 5

                          I knew bookmarklets were a thing, but never really considered them.

                          I just replaced a browser extension with one.

                          1. 3

                            Dotepub is a bookmarklet that generates epubs from webpages, which I use often to get away from the shiny computer screen and read blogs on my kindle.

                            It’s one of my favorite pieces of software.

                            I think bookmarklets are very underappreciated.

                            1. 2

                              One of my favorite bookmarklets is one that scans the page for text that looks like a base64 encoded image and replaces it with an img tag.

                              I use this to view screenshots from build failures on CI platforms like travis which don’t support artifacts (only text logs).

                            1. 5

                              Why advocate using rufo over RuboCop? I’ve never heard of rufo before this blog post, but RuboCop is almost a standard in Ruby lint tools at this point. In the same vein, Growl has long since been abandoned in favor of terminal-notifier, which uses macOS Notifications and doesn’t require a huge confusing paragraph telling you “NOT TO BUY GROWL (but here is the app store link anyway)”.

                              Additionally, I’m a huge advocate for using your package manager the way it was supposed to be used, and to that point, disagree with pinning dependencies unless it’s a fix for a package author not knowing how to distribute with SemVer. If you’re going to pin dependencies, why not just make a script instead of using those “big and bulky” tools like Yarn and Bundler? Loop over every gem and run gem install, loop over every NPM package and run npm add. There’s literally no point to using Yarn or Bundler if you’re just going to pin every dependency anyway. That’s the whole point of package managers, taking some of that work away from you so you don’t have to constantly think about patch version upgrades during your development process.

                              1. 2

                                I just switched to terminal-notifier and updated the article with it, removing the Growl part. I added a note to rubocop and plan to switching to it at some point when I feel the need. As for pinning dependencies, I added a note also that it can be a touchy subject and found a good article summarizing pro/cons of different strategy as for specifying versions: https://thoughtbot.com/blog/a-healthy-bundle.

                                Your comment is linked at some point in the article, thanks again.

                                1. 1

                                  Hey, thanks for reading and for your comments here. While I appreciate you taking the time to do so, the way you wrote the comment (tone, content) is not something I am used to. It’s not welcoming enough for me to be willing to engage in a conversation on the various items and feedback you gave.

                                  1. 2

                                    Hey, welcome to the site!

                                    While it’s often hard (given the low-bandwidth nature of textboxes-on-the-screen vs. in-person communication), please try to engage in conversation with an assumption of good faith. I’ve seen more than once that when both participants make the effort, the tone of the discussion turns pleasant despite an initial roughness and disagreement.

                                    Congrats on your first post! Keep them coming!

                                    *edit: typo

                                1. 4

                                  I really admire your work, @akkartik! I feel there is some conceptual overlap between mu and urbit (reboot of computing from ground-up, on top of purposely constrained primitives), but mu seems to be positioned firmly opposite urbit on the legibility & accessibility axis. I’m keeping my fingers crossed for its success.

                                  1. 1

                                    Usecase: User does not want to see colors on their terminal -> Disable colors in Terminal configuration

                                    Usecase: Program is not writing to a terminal -> Programs should check if stdout is a tty and check for existence of $TERM variable

                                    Is there something i miss? I don’t get the necessity for this.

                                    1. 6

                                      The article goes into this. Users might well want to explicity configure some tools (e.g. an editor) to output color, but don’t want to spammed with useless color output by a package manager.

                                      (I’m particularly irritated by command line tools whose color output was clearly not tested outside leet darkmode terminals.)

                                      1. 4

                                        (I’m particularly irritated by command line tools whose color output was clearly not tested outside leet darkmode terminals.)

                                        Thank goodness! Someone else who thinks the same thing.

                                        1. 3

                                          I think the term you want is “angry fruit salad”, and I quite concur. The people who choose default colours in terminal programs I use occasionally (but not often enough to bother with configuring) all seem to have a fetish for garish shrieking colours.

                                        2. 3

                                          I use eshell, and ansi-color codes aren’t always supported, but it’s not quite a dumb term either. I stumbled upon this link while trying to find a way to disable unnecessary color-codes being generated by apt (I know there are other ways, but I wanted to know if this was possible). If this were a pervasive standard, I would have a better experience with tools like these, by default.

                                          1. 1

                                            My predicament is similar: my main working terminal emulator is M-x shell, and some of the newer cli tools completely disregard the fact that it is pretty much a dumb terminal.

                                        1. 1

                                          Dialyzer in Elixir is less useful than in Erlang. Main culprit for me is the fact that Enum is a black hole for typing system 1. Types representing collections from Erlang stdlib can be all accept hints about stuff that is inside.

                                          1. 1

                                            Yes – and while this is true, it makes finding workflows where Dialyzer actually helps all the more important. We can always hope that the future will bring improvements in the area of Elixir, as systems get older and people come to appreciate the value of a type system during large refactorings.

                                            1. 1

                                              I would add to that, that the way structs work in Elixir (an Erlang map with a __struct__ field) basically disqualifies usage of some more sophisticated Dialyzer flags (like overspecs for instance). Nevertheless, there’s still a lot of value in maintaining correct typespecs and running Dialyzer on CI, despite steep learning curve.

                                            1. 3

                                              Another similar standard is NO_COLOR by @jcs of lobste.rs fame. I’m immensely sympathetic to the idea (I am opposed to both underhanded tracking and pointless fruit salad in my terminal), but the depressing fact is that most people don’t seem to care.

                                              1. 2

                                                I added a link to it on the site, thank you for the pointer!

                                              1. 16

                                                Some tips from personal experience:

                                                1. Make an ~/.emacs.d directory and put it in source control. Delete ~/.emacs (the file).
                                                2. Make a ~/.emacs.d/init.el, file with nothing in it. Make small changes, one by one, and see how they affect your workflow.
                                                3. Don’t make too many changes at once. Commit them to source control so you can reference them later on.
                                                4. When (and if) you start breaking up your configs, you’ll have the benefit of having them source-controlled in ~/.emacs.d.

                                                I’ve been using emacs for programming for ~7 years now. My config is here. I’ve mostly kept to vanilla emacs, my biggest flight of fancy is heavily relying on M-x shell as a regular, editable emacs buffer, kinda like the win panes in Acme. I use org-mode for basic project management and personal notes, but I don’t leverage any of the fancy agenda- tools, schedulers, etc. I also have my own color theme, which is available on melpa. I recommend making a theme as a way to get started with emacs packaging & melpa.

                                                Also, Sacha Chua is a great source for emacs stuff, both for beginners and advanced users.

                                                Good luck!

                                                1. 2

                                                  Make an ~/.emacs.d directory and put it in source control. Delete ~/.emacs (the file).

                                                  Alternately, if your .emacs file dates back to prior to support for .emacs.d/, then either: 1- make double dang sure that .emacs file is source-controlled, or 2- consider .emacs bankruptcy and fall back to my parent post’s advice.

                                                  1. 2

                                                    I follow very nearly the same approach, with one major exception.

                                                    On my work machine, I have both a .emacs and a ~/.emacs.d/init.el file. The vast bulk of my configuration is in the latter and versioned as you suggest. But the former wraps a call to (load "~/.emacs.d/init") with some machine-specific setup (secrets, adding network shares to paths, setting environment vars for local tools, etc.).

                                                    1. 1

                                                      awesome! I love the very minimal color scheme. I don’t like the dark mode themes and actually prefer white. Thanks for sharing the repo!

                                                      1. 1

                                                        Nice!, I also prefer minimal themes. Mine is here (although I prefer dark mode): https://git.sr.ht/~aerique/emacs-theme-aerique

                                                        Although, compared to yours my theme is already a little gaudy :-D

                                                        1. 1

                                                          I follow the above as well and I highly recommend it.

                                                        1. 10

                                                          I use Jekyll and Hugo but I’m constantly wrestling with them. Too many features. Too much magic. Too blog centric. They should be called “static blog generators”.

                                                          I dream of a “unified theory of static site generation” in which it would be as easy to host a blog as any other kind of content using a number of more generic primitives that give the user flexibility without creating complexity.

                                                          1. 2

                                                            I’m in the same boat as you. Older stuff done in Jekyll, newer stuff done in Hugo. Feels like I’m only using 10% of the available bells & whistles, but have to fight the other 90% trying to inject themselves into my workflow. I’m considering moving everything to soupault, which conceptually seems much more interesting than the rest of the pack.

                                                            1. 2

                                                              I use Hugo for my website, made everything from scratch. What are the things you found that are too blog-centric?

                                                              1. 3

                                                                That was about a year ago so I may be a bit rusty but basically I had a hierarchy of different kinds of contents + some cross cutting elements. I wanted control over how the different kinds of content are displayed in their index pages and needed multiple levels of nesting.

                                                                Hugo makes it easy to create lists of different kinds of content with the minimum flexibility required to produce a blog. But when I wanted more control over index pages, links to sub content and multiple levels of nesting I found it very difficult to use. I had to read a ton of resources, watch hours of video tutorial, and still couldn’t get it done exactly how I wanted it to be. I could have done it all in Django in 2 hours.

                                                              2. 1

                                                                I too use Hugo. Can be a bit overwhelming, i admit.

                                                                But may I suggest to use https://github.com/kaushalmodi/hugo-debugprint in your layout, so that while in devmode you can see all your page varables at the bottom of the page.

                                                                Has helped me a lot.

                                                                1. 1

                                                                  Thanks! I’ll give a try next time.

                                                              1. 13

                                                                I use Hakyll. It’s written in Haskell and is completely programmable. It’s actually more of a framework for writing static site generators. That said, there are example codebases that you can get started with. It supports all your desires.

                                                                1. 3

                                                                  I use Hakyll, too, but it’s complete overkill for me. And I’m not deep enough in Haskell any more to do much development on it, so I’ve been considering moving to something else.

                                                                  I still endorse Hakyll, fwiw, but its strength lies in either: 1- leveraging your existing Haskell knowledge, and/or 2- generating sites that are far more complex than most personal sites/blogs.

                                                                  1. 4

                                                                    I still endorse Hakyll, fwiw, but its strength lies in either: 1- leveraging your existing Haskell knowledge, and/or 2- generating sites that are far more complex than most personal sites/blogs

                                                                    It’s also fun to spend more time programming your blog than writing blog posts.

                                                                    1. 1

                                                                      i use hakyll and i’ve used it to also teach myself odd bits of haskell.

                                                                      i like how extensible it is, and i’ve occasionally used it to add various bits and pieces

                                                                      the main downside w.r.t. github is that you have to commit all the generated artefacts; which is definitely a shame.

                                                                      i’ve not done too much funky stuff with it; but on my companies website i’ve used it to build some (very simple) features, such as lists and specialised rss views, next/previous blog post buttons, etc.

                                                                      it’s not the most elegant code; but gets the job done.

                                                                      1. 1

                                                                        Late to the party, but you might be interested in rib.

                                                                        Why? Because by using rib, you will automatically learn Shake which it is built on top of. Compared to Hakyll, rib is relatively simple to use.

                                                                        Disclaimer: I’m the author. :-)

                                                                      2. 3

                                                                        hakyll here as well

                                                                        1. 2

                                                                          Great to see you’re blogging (again), Pavlo!

                                                                        2. 2
                                                                          1. 1

                                                                            Hakyll too. It’s simple if you only want to convert text into HTML, however, if you want something more advanced be prepared that you might spend more time figuring out how to implement this instead of writing.

                                                                            I’m also using supplementary python scripts and relying on external means (e.g. jupiter/emacs) to generate HTML too, I shared my setup here

                                                                          1. 1

                                                                            This was a solid read. While I might disagree about some minor choices here or there, I agree fully with the main theme of application layers only creating dependencies in one direction: inward.

                                                                            A part of me keeps wondering how many of these articles (which simply reiterate known practices) the Elixir community needs before they become common knowledge. It seems that the – admittedly young – ecosystem just hasn’t accumulated enough pain from bad architecture decisions to start looking for existing solutions to these problems.

                                                                            Here is a talk more-or-less making the same points, but with nice graphs & art references ;)

                                                                            1. 2

                                                                              A part of me keeps wondering how many of these articles (which simply reiterate known practices) the Elixir community needs before they become common knowledge

                                                                              At the risk of being a little snarky, a good number of folks in the Elixir community emigrated from the Ruby community where we had the same articles. If they didn’t find religion then, I’d be surprised if they did so now.

                                                                            1. 12

                                                                              I am surprised such a short article created such a large response (currently 18 comments plus mine).

                                                                              And I think it’s because the title is strongly polarizing (the default human behavior is to go without having to learn new things) and the post just throws in a personal list (from the author’s POV) of things someone should know, a memey photo, and an ending statement. Is that enough for being worthy of discussion?

                                                                              Obviously this like so many other topics has both a “it depends” and “we need both in the world” answer. So, why is this not being downvoted away?

                                                                              So please fellow Lobsteriañitos, don’t fall for these low effort, polarising and unresearched submissions. It’s there to trick you into, obviously, providing your take on the subject.

                                                                              1. 6

                                                                                I’m seeing a lot of blind leading the blind posts on here in the last couple of days. Flagging these as spam is taking far to long to have them removed.

                                                                                1. 8

                                                                                  This is coming from a particularly spammy account too. I am rather annoyed by the author spamming a load of low-quality posts in rapid succession — supposedly because this is how social media marketing is done or something — and using her sexuality to market herself as a programmer too.

                                                                                  https://www.instagram.com/p/BlYV1b-n8K9/?igshid=q1cw4umuiizt

                                                                                  Like, here’s a book, but also — what a coincidence — here’s my tits!

                                                                                  This is just bad.

                                                                                  1. 4

                                                                                    Yes, there used to be a time when this kind of stuff didn’t make it to the front page of lobsters, but the social media arms race never stops :\

                                                                                  2. 1

                                                                                    I wonder if there’s a case to remove or demote short posts in general. A short post isn’t necessarily low-information, and long posts can be mostly pointless fluff, but 80-90% of the time anything under 2,000 words isn’t worth reading (and wasn’t worth writing) for a technical audience like ours.

                                                                                    Not that it would be trivial to automate detecting the length of blog posts… I guess we could support a tag like ‘short’, & expect folks to tag in good faith.

                                                                                    In cases like OP, a 50k-word post on this subject would be interesting, and the author wrote a short paragraph instead because they hadn’t put more than a minute’s thought into the subject and could not have written a post worth reading. In fact, if the same author wrote 50k words on the same subject, the result would probably be more interesting even if the thesis didn’t change, simply because complications arise with that sort of depth. (I’d still consider OP to be wrong, but I would no longer consider the post a low-effort click-grab.)

                                                                                    1. 3

                                                                                      I semi-suggested a “low-info” flag a few months ago. I guess “off-topic” is a better catch-all

                                                                                      https://lobste.rs/s/nqntbn/ban_filter_submissions_from_twitter_com#c_dwuhdo

                                                                                      1. 4

                                                                                        I think a low-info flag is better, tbh. OP is a case in point: the post is on-topic – it just doesn’t say anything of value, because it’s not the product of more than a minute of thought or work. The ‘spam’ flag appears to be doing double-duty as a ‘low-info’ flag, though (as opposed to merely flagging self-promotion and promotion of products).

                                                                                        The reason I think the ‘short’ tag is valuable is that there’s difference of opinion about whether or not a blog post of this length can ever be interesting enough to justify a lobste.rs post. Some folks are going to want to filter out short posts entirely, weighing the value of their time over the miniscule chance that a short post will say something interesting. Obviously, other people have lower standards – at the time of this writing, even though it’s been downvoted & flagged as spam nearly 20 times, its ranking is positive. Those folks can have their cake – we could treat the ‘short’ tag the way we treat other tags of dubious average information content (like ‘rant’, ‘satire’, and ‘show’) and demote short posts by default, while allowing them to rise to the front page if they’re actually high-quality, and allowing folks like you and me to block them entirely.

                                                                                      2. 1

                                                                                        I don’t think it’s quite as simple as post length. Someone smart and worth listening to can distil a compelling idea even into 140 characters. The problem here really is that the author’s articles are just spammy garbage. The formula is transparent — offer up some programming-themed platitudes accompanied by emoji and a photo of the author trying to look cute. It’s particularly egregious when many of the author’s posts are tagged with some variation of the #girlswhocode theme. Like, is that helping any of the many women who want to be taken seriously in our field purely on the basis of their intellectual merit? Of course it isn’t. It’s plain harmful.

                                                                                        1. 2

                                                                                          Someone smart can write a good short post – on occasion. Even then, it’s rare. Most short blog posts are of a comparable quality to this one, even if they are by folks who usually write high-quality long posts.

                                                                                          I’m not recommending banning short posts, but tagging them so that folks who would like to avoid trudging through the swamps of low-quality content (or would like to temper their expectations upon encountering a juicy headline like this one) have better tools for avoiding wasting their time.

                                                                                    1. 3

                                                                                      That keyboard is a dream come true. That useless, huge spacebar, finally replaced with a bunch of thumb-accessible keys (an echo of the Canon Cat layout?).

                                                                                      1. 2

                                                                                        Oh I was already excited by this and hadn’t even noticed the space bar, great to see.

                                                                                      1. 1

                                                                                        I have light-background themes in all my applications, and when I need to work in a dark room (or in scant lighting), I have

                                                                                        xcalib -i -a
                                                                                        

                                                                                        bound to a launcher in my desktop panel. This simply inverts colors across the board, and is good enough for me.