Threads for susam

    1. 2

      As a reader, I don’t often care about the change history of an entire blog, but I do care about when a specific article was last updated. In fact, I care about exactly two things: when the article was first published and when it was last updated. These two details are usually sufficient. A detailed change history for the article would be a nice bonus but not essential. From reading this article, it seems like you are focusing more on the blog-level change history. Is that right?

      That being said, it’s your blog, and you should feel free to tweak, change, and update it however you see fit! Everyone has their own approach, and there’s no one-size-fits-all when it comes to maintaining a blog.

      Personally, I have my blog rendered using a Common Lisp program I wrote myself. While I don’t tweak it as often, I do support a mandatory publication date and an optional update date for posts. When a post undergoes too many updates, I prefer to write the change history manually at the bottom of the article in the following format:

      Update on DD Month YYYY: [followed by what was updated]

      It is a simple, low-tech approach, but it works for me.

      1. 1

        Yes I’m focusing on the blog level change. Also in my opinion version number has nothing do with the end consumer and is for more the devs. Coming to this implementation, I love tweaking stuff on my blog, I’m a relatively new programmer and thought of doing it as a fun project. I also wanted to add a small change log for each page and thus the main log acts as a base for it. I haven’t implemented it yet!

        P.S: I’m not sure why I’m receiving lot of hate comments for this article on my blog. The traffic has been predominantly from Lobsters. Did I write something to upset the community?

        1. 2

          Thanks for the clarification. Yes, it does make sense to have a blog-level version number for the devs.

          About your postscript remark, I can’t speak for the whole community but I found your post interesting. The 7 upvotes right now indicate that at least 5 others found it interesting too.

      2. 5

        Hello! Just catching up on the comments here. Thank you for all the kind words in this thread!

          1. 2

            Thanks for sharing this. This is an excellent article. Adding this to my reading list!

          2. 16

            I’m confused as to why an HTML blog would strain a server more than a plain text blog. Serving this text as HTML might, POSSIBLY, double the size from 1kb to 2kb. Killing off the favicon would be just as effective, maybe moreso, for saving server resources.

            1. 8

              I had assumed this was satire.

              Anyway it’s not even close to double I think. I wrote a 6 paragraph blog post, one with and one without html. The html was just

              <!DOCTYPE html>
              <html lang="en">
              <head>
                  <meta charset="UTF-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0">
                  <title>title</title>
              </head>
              <body>
              </body>
              

              Then <p> tags aroudn the actual text.

              The end result was just a 400 bytes smaller in plain text. But if you put links in you could click them etc etc.

              Also, txt in a browser is surely more likely to be deprecated over html

              1. 7

                Honestly, you’ve gone way overboard with the HTML there, too. You could drop the lang, the doctype, and the entire head block and it would work fine on 99.99% of browsers.

                1. 3

                  I think in HTML5 he could drop everything except the doctype and it would be valid, wouldn’t it?

                  1. 7

                    I think in HTML5 he could drop everything except the doctype and it would be valid, wouldn’t it?

                    The smallest “hello, world” HTML5 document I am able to write that passes both the Nu HTML Checker and tidy version 5.8.0 is the following one:

                    <!DOCTYPE html>
                    <html lang="en">
                    <title>Hello</title>
                    Hello, World!
                    

                    Anything less and the Nu HTML Checker emits a warning. Tidy output looks good for the above HTML, if we don’t mind the following warning about implicit tag:

                    $ tidy -q -e -omit minimal.html 
                    line 4 column 1 - Warning: inserting implicit <body>
                    
                  2. 1

                    Dropping the lang is bad for accessibility. Without the doctype it’s not valid standards mode HTML5. The charset is necessary if you have any non-ASCII characters. The viewport tag is needed for proper rendering on mobile.

                    1. 3

                      Dropping the lang is no worse for accessibility than just serving a txt file.

                      (I will go to my grave arguing that “lang” does nothing for accessibility, but I’ve lost that fight here already)

                      1. 1

                        Dropping the lang is bad for accessibility. Without the doctype it’s not valid standards mode HTML5. The charset is necessary if you have any non-ASCII characters. The viewport tag is needed for proper rendering on mobile.

                        • I’m not making html5, just serving txt files.
                        • I use BOM (byte order mask) in order to let the browser know that I’m using utf-8.
                        • You can use the reading mode of your browser to display the text fine.

                        I don’t think txt files are so much of a problem in term of accessibility (I mean you can configure your screen reader to change the spoken language).

                  3. 3

                    I created this txt blog for two reasons :

                    • I had a terrible connection at home (where my small “server” is located), and I wanted to write in english (which is not my first language). I wanted to submit those articles on websites like here or hn, which can bring a lot of people over my bad connection, and I wanted to have pages as small as possible (I already got a kiss of death on my internet box by a sudden hn popularity, it’s not cool for the readers nor for me).
                    • I argued with a friend that “you can start a blog within one minute”, and to prove I were right I executed and created the first txt file (I did this in a little bit over 10 minutes, I’m slow :/).

                    But I really like lightweight websites with html & css, and love to waste my time exploring funky lightweight designs from 1MB club (https://1mb.club/) :)

                    1. 17

                      To be clear, you should do what makes you happy, and if this is it, good on you. I just don’t think the savings are significant, for the tradeoffs.

                        1. 2

                          While I understand the spirit, you may be shooting yourself in the foot. If your intention is for people to read your articles, not just have the server serve them, you’d do well in improving the reader’s user experience just a bit. Plain text is just not great to read on desktop and on mobile it is unreadable (I mean literally unreadable because the font size is miniscule).

                          As it stands it’s a bit contradictory to care about readers not being able to see your website if it gets squeezed to death because when they are able they can’t read it anyway.

                          1. 3

                            I don’t really mind if no one is reading my articles. I have another blog (in french) at l3m.in, which is made of html, css and even some images.

                            I disagree on your take on mobile readability; the reading mode (at least on firefox, haven’t tried on another browser) handle txt files just fine :)

                          2. 2

                            Not as practical, but I also made https://1kb.club when I thought 1MB wasn’t extreme enough ;)

                            1. 2

                              Oh you’re the one behind 1kb.club! Thank you for your work, I love stumbling across your site from time to time and discover new websites!

                        2. 4

                          I am sorry, I really don’t understand what is so interesting about this? This is just the standard hello world program for DOS. What am I missing?

                          also, how did you make your first commit in 2003?

                          1. 2

                            It looks like this started as a blog post in 2003 (https://susam.net/programming-with-dos-debugger.html). If the code was imported to git from another VCS, it’d retain the timestamp. Git timestamps are normally taken from the system clock, but are fully client-side, and can be anything.

                            1. 4

                              That’s exactly what happened. Back in my university days, I ran a small intranet web portal on our university LAN and occasionally wrote simple technical articles for it. Back then, I would manually type in machine instructions into DEBUG.EXE to learn assembly. I wrote the blog post you referenced to share this learning method with my fellow students. For anyone wondering why I used DEBUG.EXE, it was simply what I had available back then, as I hadn’t yet discovered more sophisticated tools like NASM.

                              As for the Git commits, yes, they were imported from another version control system, CVS, if I recall correctly.

                            2. 2

                              You can edit commit dates https://stackoverflow.com/questions/454734/how-can-one-change-the-timestamp-of-an-old-commit-in-git. I betcha that’s when the author first did this and when adding it to git, edited the date to match the original file creation day.

                              I was goofing around with 16 bit assembly on DOS around that same time too. I didn’t have my own computer till…. I think it was 2002, and it was my mother’s old pentium 1 box she handed me down. The Windows API looked complicated but asm on DOS was nice and easy - it is nice to do a little setup block (mov ax, 13h; int 10h;) then write a few bytes and have stuff drawn on screen. And it performed well enough to have fun with! I did later figure out the Windows API (and nowadays I like a fair amount about it), but that same kind of pixel pushing was much slower there, so never quite the same as the good old dos vga asm.

                              good times. good times.

                            3. 6

                              Empty sequences evaluate to False: things like lists, tuples, sets, dicts, strings

                              dicts and sets are not sequences.

                              Everything else evaluates to True, unless they override the behavior via the __bool__() method.

                              This is incorrect, and in fact one of the reasons why calling len() is mostly not useful for this purpose: per Python’s data model

                              When [__bool__()] is not defined, __len__() is called, if it is defined, and the object is considered true if its result is nonzero.

                              It’s important to be conscious of this fallback, as you may want to have a len() but override bool explicitly to always be truthy. The elementtree API has that problem, where elements behave as lists (of their children), so they have a len() of 0 if empty, which leads to them being falsy. And thus

                              if doc.find(...):
                              

                              will fail if an element is found but has no children. It also triggers a warning because the behaviour is dubious and non-obvious, and thus a __bool__ was added for that purpose, but the behaviour was not changed for BC reasons. As a result, if you want to check if an ElementTree Element has no children you should check its len().

                              1. 1

                                This is incorrect, and in fact one of the reasons why calling len() is mostly not useful for this purpose: per Python’s data model

                                Confused. How does that mean len() ‘mostly not useful’? What ambiguity would break if len(mylist) == 0 ?

                                Looks pretty obvious to me that it will evaluate to false on empty lists and true on non empty lists.

                                That said, i don’t agree with article. I use the pythonic way because I am used to it and it’s the recommended way. But the whole thing of placing symbols of arbitrary data types inside boolean language constructs is practice that survives bizarrely at this day and age. Oddly, often times acclaimed by people that think type prefixes are the solution to all problems. It’s just a legacy that we don’t need. I don’t get this fixation on types on variable declaration and function signatures, while make if statements or other boolean operations a place where everything goes. It would certainly make logical sense to just allow for boolean values there?

                                1. 3

                                  Confused. How does that mean len() ‘mostly not useful’?

                                  Because as I quoted boolean tests will fallback to __len__ if there is no __bool__, so by calling len() explicitly all you’re doing is adding overhead. Hence doing so is mostly not useful, you will lose nothing by not doing it.

                                2. 1

                                  What do you mean by dicts and sets not being sequence? They are iterable in a well-defined order, or is there a more precise definition for a sequence in Python?

                                  1. 4

                                    From https://docs.python.org/3/glossary.html#term-sequence:

                                    sequence

                                    An iterable which supports efficient element access using integer indices via the __getitem__() special method and defines a __len__() method that returns the length of the sequence.

                                    A dict or a set object does not support element access using integer indices in general. In fact, the above glossary further elaborates this:

                                    Note that dict also supports __getitem__() and __len__(), but is considered a mapping rather than a sequence because the lookups use arbitrary hashable keys rather than integers.

                                    The following results are also worth noting:

                                    >>> from collections.abc import Iterable, Sequence
                                    >>> isinstance({'a': 'foo'}, Iterable)
                                    True
                                    >>> isinstance({'a': 'foo'}, Sequence)
                                    False
                                    >>> isinstance({10, 20}, Iterable)
                                    True
                                    >>> isinstance({10, 20}, Sequence)
                                    False
                                    
                                    1. 1

                                      Ah, thanks, that’s good to know! I guess I’ve always thought of iterable and sequence as being roughly the same, but this distinction is clear.

                                    2. 2

                                      sets are not ordered: “A set is an unordered collection with no duplicate elements.”. CPython uses the insertion order like dicts since 3.6, but Python 3.7 only made this behavior standard for dicts, so it is still an implementation detail for sets.

                                      1. 1

                                        Huh, that rings a bell, but I’d completely forgotten that detail.

                                  2. 25

                                    This article is incredible and what “falsehoods” articles should aspire to be.

                                    Btw it’s called UTC (Universal Time Coordinated? huh?)

                                    Ooh ooh I know this one! It’s a compromise between the English acronym UCT and the French acronym CUT.

                                    1. 4

                                      Yes! There is a nice FAQ about it on the NIST website here: https://www.nist.gov/pml/time-and-frequency-division/how-utcnist-related-coordinated-universal-time-utc-international. Quoting from there:

                                      In 1970, the Coordinated Universal Time system was devised by an international advisory group of technical experts within the International Telecommunication Union (ITU). The ITU felt it was best to designate a single abbreviation for use in all languages in order to minimize confusion. For example, in English the abbreviation for coordinated universal time would be CUT, while in French the abbreviation for “temps universel coordonné” would be TUC. To avoid appearing to favor any particular language, the abbreviation UTC was selected.

                                      1. 25

                                        Holy shit how did NIST (NIST!) manage to publish something so blatantly incorrect when they really ought to know better?!

                                        • UTC dates back to 1962. There have been two different definitions of UTC:

                                          • 1962-1971 was the “rubber seconds” era

                                            UTC was defined by a combination of a frequency correction, so that UTC seconds varied in length to roughly match the rate of UT2 (hence “rubber”) plus occasional phase adjustments on the order of 100ms to cope with mismatches between the UTC frequency and the earth’s wobble.

                                            One thing to keep in mind is how time was distributed in the 1960s: big fuck-off radio transmitters. The time signal was not just modulated onto a carrier wave: the carrier wave itself was a broadcast reference frequency. So when UTC had a rate adjustment, that meant engineers had to go out and retune and recalibrate several very serious high-power broadcast antennas. This was a colossal pain in the arse, which is one of the reasons UTC changed to fixed-length seconds in 1972.

                                          • 1972 onwards, UTC just uses coarse phase adjustments (known as leap seconds) and the somewhat finer 100ms correction is promulgated out of band as IERS Bulletin D.

                                          I can’t find a good reference to rubber-second UTC right now, but some time ago I wrote about falsely extending leapseconds back to the 1950s to make a simpler model of the 1958-1972 transition from UT2 to modern UTC. (I no longer think this is a good idea.)

                                        • UTC is a two-part abbreviation

                                          • UT is short for universal time

                                            Unlike a lot of abbreviations in this area it is not french. It dates back to the international meridian conference in 1884 which

                                            • chose the Greenwich Meridian;
                                            • defined Universal Time;
                                            • set the basis for time zones.

                                            The conference was convened by the United States, and Greenwich won mainly because the British Admiralty had the best and most widely-used maritime charts, and they were all based on Greenwich. And the USA wanted Greenwich to win because it was already the basis for the north american railway time zones.

                                          • UT is usually used with a suffix,

                                            • UT0 = apparent solar time

                                            • UT1 = simple mean solar time, UT0 plus the equation of time

                                            • UT2 = a more uniform version of mean solar time, what GMT was when the Greenwich Observatory was maintaining a mean solar time scale

                                            • UTC = universal time, but atomic, the “C” referring to the co-ordination between the british (first atomic clock and timescale), americans (helped calibrate the first atomic clock to define the atomic SI second; second atomic timescale), and french (bureau international de l’heure; third atomic timescale)

                                            The C is a suffix, following the old established scheme. It was not an ITU compromise, nor a linguistic compromise — and in 1970 the radio broadcast part of the ITU was still called the CCIR – the Comité Consultatif International pour la Radio.

                                        1. 6

                                          The C is a suffix, following the old established scheme.

                                          Well… yes, now it is! But how can you be 100% sure that this wasn’t a result of the said compromise? I mean I appreciate the interesting story and the facts you shared. But I can’t see anything in those facts that rule out the possibility of disagreement on the name. I mean the French could have still definitely demanded “TUC”. How do you know 100% there were no disagreements on the name?

                                          I guess what I’m asking is why I should take your word for it if I cannot take NIST’s word for it? I am not seeing any authoritative citations to back either claims.

                                          Yes… UTC has the same pattern as UT0, UT1, UT2 but that could be a consequence of the said compromise, not the other way around.

                                          1. 9

                                            I emailed Steve Allen and he was kind enough to reply and to let me share his response:

                                            The NIST statement is not true. It omits chunks of history. The history is hard to track because some of the omitted chunks were intentionally obscured by various individuals at various agencies including the NIST precursor NBS for political, legal, and diplomatic reasons.

                                            The first printed occurrence of UTC specified as the term used for documents written in English was by Bernard Guinot in Bulletin Horaire Series J Number 1 published in 1965. In his own memoir Guinot declined to take credit for the term saying that it had already been in use among the timekeeping community.

                                            UTC is akin to UT0, UT1, UT2 as had been defined by the English speaking astronomers in the timekeeping community. In the same sentence of Bulletin Horaire Guinot indicated that in French the term was TUC, akin to TU0, TU1, TU2 which had been used by astronomers writing in French.

                                            I have seen no evidence that any publication from members of the timekeeping community ever used the term CUT.

                                            I think the NIST statement is continuing the early practice of trying not to talk about how all of this happened because that would reveal strong disagreements and legal complications rather than give the idea that there was consensus.

                                            1. 5

                                              The best source I could find was Steve Allen’s history of UTC. Two relevant points on his timeline:

                                              TUC[BIH]/UTC[BIH] in 1964/1965

                                              […]

                                              On page 2 of [Series J, Number 1 of Bulletin Horaire,] Guinot wrote a definition in boldface print

                                              L’échelle intermédiaire TUC (UTC en anglais) sera appelée Temps Coordonné.

                                              This is the earliest known use of the term UTC in any publication.

                                              The bulletin did not make a clear choice of language for the abbreviation. There was not yet a clear precedent for using CUT “Coordinated Universal Time” (in English) nor TUC “Temps Universel Coordonné” (in French), nor UTC (following the pattern that Markowitz of the IAU had worked out with the time service bureaus for UT0, UT1, and UT2).

                                              The canonical ordering UTC is consistent with neither French nor English, but it is consistent with the UT0/UT1/UT2 nomenclature scheme. Despite the canonical ordering, it remains common even today to see usage where the letters are permuted (and worse misnomers such as Consolidated Universal Time, Universal Correlated Time, Universal Coordinating Time, Universal Time Calibrated, Universal Time Code, etc.).

                                              The next relevant point on the timeline:

                                              UTC in 1976-08/09

                                              The 16th General Assembly of the IAU in Grenoble produced Resolution No. 3 by Commissions 4 and 31 which recommended that the abbreviation UTC be used for all languages.

                                              This still doesn’t answer the question definitively but it gets us a bit closer. A lot of these discussions happened over written correspondence but I haven’t been able to find them online.

                                              This idea of a “compromise acronym” is repeated in other places. It’s a good story, either way.

                                              1. 8

                                                I’m at a conference rn, please stop nerd sniping me both of you

                                        2. 2

                                          I could appreciate a game mode where the percentages are hidden. (Probably that’s easier for you to build in an option than for me to try creating a user script that hides them.) I like the extra challenge of trying to get there by looking at the colors alone.

                                          1. 3

                                            The magic of javascript is that you can just redefine the running script! Paste this in the console:

                                             function addMove (r, g, b, rr, gg, bb, attempts) {
                                                    const dark = luminance(rr, gg, bb) < luminance(8, 8, 8)
                                                    const rgbHex = hex(rr, gg, bb)
                                                    const won = rr === r && gg === g && bb === b
                                                    const lPad = attempts < 10 ? '&nbsp;' : ''
                                                    const rPad = '&nbsp;'
                                                    let scored = score(r, g, b, rr, gg, bb)
                                                    const div = document.createElement('div')
                                                    scored = (scored < 10 ? '0' : '') + scored
                                                    div.style.background = rgbHex
                                                    div.style.color = dark ? '#fff' : '#000'
                                                    div.innerHTML = lPad + attempts + ') ' + rgbHex
                                                    log('input=' + rr + ',' + gg + ',' + bb + ' hex=' + rgbHex +
                                                        ' scored=' + scored + ' won=' + won)
                                                    if (won) {
                                                      div.innerHTML += ' (Splendid!)' + rPad
                                                      div.style.border = 'thin solid #' + (dark ? 'ccc' : '333')
                                                      win()
                                                    }
                                                    document.getElementById('result').prepend(div)
                                                    if (attempts === MAX_ATTEMPTS) {
                                                      halt()
                                                    }
                                                  }
                                            
                                            1. 2

                                              That’s lovely; hard to do on mobile, but anyways – with the hindsight of having been able to play it this way now, I can confirm, I find it a lot more interesting to play this way. So @susam I think it’s really worth adding a toggle for this! ;-)

                                              1. 2

                                                @steffahn A quick update on this topic. You can now play this game in expert mode by appending #x to the URL. Example: https://susam.net/myrgb.html#x

                                                Once again, thanks for this great suggestion!

                                                1. 1

                                                  Works great, thanks!

                                                2. 2

                                                  @steffahn Hiding the percentages with a toggle is a nice idea indeed. It will probably take me a while to make changes to this project but I will keep this in mind the next time I have some time to spare on this project. Thank you for the nice feedback!

                                            2. 1

                                              Interestingly, in ex (which today we mostly experience when we press : in vi), $ means the end of the buffer: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html#tag_20_40_13_02

                                              1. 5

                                                The $ in ex means the last line while addressing lines. Within basic regular expressions (BRE), it still means an anchor that matches the end of each string (effectively, each line of input). This is very likely influenced by its predecessor ed. In fact, ed influenced these choices in sed too. For example, all three commands below print the last line of /etc/hosts.

                                                echo '$p' | ed -s /etc/hosts
                                                echo '$p' | ex /etc/hosts
                                                sed -n '$p' /etc/hosts
                                                

                                                All three commands below print the second line while replacing the last three characters of the second line with the string “foo”.

                                                echo '2s/...$/foo/p' | ed -s /etc/hosts
                                                echo '2s/...$/foo/p' | ex /etc/hosts
                                                sed -n '2s/...$/foo/p' /etc/hosts
                                                

                                                It is possible to use both meanings of $ in the same command. For example, the following commands print the last line while replacing the last three characters of the last line with the string “foo”.

                                                echo '$s/...$/foo/p' | ed -s /etc/hosts
                                                echo '$s/...$/foo/p' | ex /etc/hosts
                                                sed -n '$s/...$/foo/p' /etc/hosts
                                                

                                                Quoting the relevant sections from the POSIX documents below.

                                                From https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html:

                                                The <dollar-sign> character ( ‘$’ ) shall address the last line of the edit buffer.

                                                From https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html:

                                                The character ‘$’ shall address the last line of the edit buffer.

                                                From https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html:

                                                An address is either a decimal number that counts input lines cumulatively across files, a ‘$’ character that addresses the last line of input, or a context address (which consists of a BRE, as described in Regular Expressions in sed, preceded and followed by a delimiter, usually a <slash>).

                                                Quoting from section 9.3.8 “BRE Expression Anchoring” of https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html:

                                                A <dollar-sign> ( ‘$’ ) shall be an anchor when used as the last character of an entire BRE. The implementation may treat a <dollar-sign> as an anchor when used as the last character of a subexpression. The <dollar-sign> shall anchor the expression (or optionally subexpression) to the end of the string being matched; the <dollar-sign> can be said to match the end-of-string following the last character.

                                                1. 1

                                                  Yes, sorry. I didn’t mean to imply that it didn’t mean EOL too. It’s just interesting to me that it means last-line in a line context.

                                              2. 20

                                                I feel pretty conflicted about the notion that moving from touching the keyboard to the mouse is a loss of focus.

                                                I bought the notion earlier of course when I was really getting into Vim, but then I seriously tried just using the mouse and I found that it didn’t really make that much of a difference for me. As a result, I find it hard to believe the idea that the ‘context switch’ is really that meaningful.

                                                Has anyone else had that experience?

                                                1. 26

                                                  I think it’s all about how the editor fits your brain. If it fits, great. If not, try something else. For me, vim’s keyboard focus is really enjoyable, and I think we’re more productive with things we like.

                                                  1. 4

                                                    I think I could get to the point where I reach for the mouse instinctively, but with vim I never think about vim, it’s like walking, and when I use something else, reaching for the mouse is only triggered by being snapped out of everything being pure muscle memory. I think it’s possible the mouse just becomes another motion, but it’s hard to actually imagine since it’s so far away.

                                                      1. 1

                                                        I disagree pretty strongly… Vim editing is a discipline, this is not something you will intuitively be good at, it takes months of labor to even be sort of okay at it.

                                                        There’s nothing inherently wrong with touching a mouse, but the combination of gross+fine motor control it requires necessarily means you are slowing down your interaction with the machine by at least an order of magnitude, and that increases the risk of being knocked out of the flow state.

                                                        Keyboard-driven development in Vim is the only time my editor has felt like an extension of my mind.

                                                        1. 2

                                                          I agree with that. Vim is a discipline, and takes a while to get proficient, with it’s rewards being cumulative over time.

                                                          My point about enjoying Vim is that I believe that is at the core of why I use it. There are many productive tools, but I stuck with Vim’s learning curve because I enjoyed it, because it fit my brain. Even though learning it was difficult, I was still enjoying the process of learning it, and I don’t think I would have continued to if I hadn’t. For example, I tried Emacs, and didn’t stick with it because it didn’t fit my brain as well, and hence I didn’t enjoy using it as much.

                                                      2. 13

                                                        Doesn’t make a big difference for me either, but I think Vim is more fun and feels less like work. Even if it isn’t actually any faster (for me at least), it’s just fun and satisfying to string together editing commands in a way that clicking and dragging isn’t. Tickles the brain just right.

                                                        1. 10

                                                          The keyboard feels more “deterministic” than the mouse because I don’t have to aim, I just, well, type the letters. Similarly, vim commands better reflect what I want than selecting the right number of characters with a mouse does. (E.g., if I want to delete a section of text, and I see the word “something” immediately after, I can use d/something. Lots of motions like that reflect how I think of the text I’m editing.)

                                                          1. 1

                                                            I like that idea, keyboard is digital, mouse is analog.

                                                          2. 7

                                                            When I’m at a desk, going for the mouse isn’t a terrible disruption. On a laptop? I hate fiddling with text using a trackpad. Maybe I’m just old, but it feels like working with oven mitts on. Not having to do that is invaluable. Having to use the trackpad (even the ThinkPad pointer) is a cognitive switch.

                                                            But, I’ve used Vim for decades. 20-something me, before Vim, might’ve felt differently.

                                                            1. 5

                                                              I could believe that the physical context switch—moving your hand from the keyboard to the mouse—has the potential to add some delay. But that’s only if you’re very proficient with the keyboard. If you want to move the cursor somewhere else in the document, but it takes you half a second to decide how to do that using the keyboard, you probably would’ve been better off just using the mouse.

                                                              I’ve been using Vim for 20 years, and while I’m comfortable using just the keyboard (when Vim is running in a terminal), I feel like I’m faster when I can also use the mouse (in MacVim).

                                                              1. 3

                                                                I agree. I HATE having to interrupt my thoughts to decide how to navigate in my editor. Whether that happens frequently is going to vary from person to person …

                                                                and I bet that almost everything mentioned in this discussion varies wildly from person to person. I don’t mean that it’s just a matter of taste. I expect there are interesting reasons for all the variation. The variation between people is the sort of thing I would expect to be very very complicated.

                                                              2. 4

                                                                I use the mouse with vim pretty heavily. I think the fact that it actually works pretty well in there is forgotten in a lot of these threads.

                                                                1. 4

                                                                  I don’t think it’s the movement between the keyboard and the mouse that causes a “loss of focus” or a “context switch”: it’s the mental shift from vim-command-mode to GUI-desktop-mode. These are two different ways of interacting with a computer. In another comment here, @susam describes how switching from Emacs to a different GUI application “disrupts the flow”. Again, I don’t think it’s really about keyboard versus mouse: I think it’s more about two different cohesive models for controlling a computer.

                                                                  I’ve used Vim for more than twenty years now and I think I’m pretty proficient at it. I don’t really think about how to control it, I just think of the change that I want to make to the text and my fingers automatically express that as Vim commands. The Vim command language is seared into my muscle memory. This has served me really well for a large part of my career, which I have spent using Vim and other teletype-terminal programs in tmux (and Screen before that).

                                                                  However, these days, I find that I have to use a lot of other GUI desktop applications too - I can’t live in tmux any more - and I find the context switches between Vim and the rest of my desktop really jarring. The same modal command language that used to keep me in the flow now disrupts my flow!

                                                                  So I recently decided to give up Vim and try a text editor that obeys the same modern desktop idioms as all the other GUI applications that I have to use for work. It’s taken me a few months to get used to it but I’m now glad that I made the switch: I no longer have to suffer jarring context switches every time I change between my text editor and my other tools.

                                                                  Just the other day, I found myself having to make a load of edits to a configuration file: this was just pure text editing work. I felt like I was going so slowly, constantly grabbing the mouse to select some text, then going back to the keyboard to type. It was the sort of thing that I could do in no time, almost without thinking, in Vim. So I thought I’d test that: I undid all my changes then used a screen recorder to time myself doing them all again. Then I undid them and recorded myself doing it in Vim. It wasn’t really a fair comparison - since I’d already done all the tasks twice by the time I did them again in Vim - but I thought it would be interesting to see how much faster I was in Vim anyway. To my surprise, when I checked the recordings I found that I was faster using the mouse!

                                                                  Anyway, different people will have different preferences, but I think it will also depend on the type of work that you’re doing. When I used to live in tmux, Vim was great. Now that I no longer have to work over SSH but I do have to use other GUI desktop applications, I prefer something else. I also found it interesting that my perception of my editing efficiency was quite different from the empirical measurements… but maybe that’s just me.

                                                                  1. 3

                                                                    Has anyone else had that experience?

                                                                    I do find it clumsy to context switch between keyboard-driven work and mouse-based work. Let me share a very recent example. Only yesterday, I was doing source code walkthrough of a new software project for someone else using my Emacs. I could do most of the code walkthrough merely by touch-typing on my keyboard.

                                                                    I could hop around to different sections of the source code (movement commands), search for files containing specific identifiers or strings (project commands), hop between files (buffer commands), start/restart Docker containers (M-x eshell), run arbitrary shell commands (M-x eshell again), create new files with experimental code to test out ideas, etc. all from within Emacs, using nothing but the keyboard with my fingers relaxed comfortably on the home row most of the time, touch-typing away as I command Emacs to assist me in navigating through the code and testing out ideas.

                                                                    But every once in a while, I would be forced to move my hand away from the keyboard to the mouse nearby in order to move the mouse pointer over to another GUI application to look up something. Each time I had to make this transition, it disrupted the “flow” and felt cumbersome, highlighting the disparity between the smooth keyboard-driven workflow within Emacs and the clumsy mouse-based navigation outside of it.

                                                                    While I appreciate that not everyone shares the same experience as mine, and that’s perfectly fine, for me, every time I have to take my hand off the keyboard to reach for the mouse, it feels like shifting from cruising smoothly on a wide-open motorway to suddenly navigating through a bustling, congested local road.

                                                                    1. 3

                                                                      I have the same experience. I don’t feel any loss of focus from switching.

                                                                      1. 3

                                                                        For me the Vim flow is very nice, however lately I’ve been coding in LispWorks and there is no Vim mode there. The lost productivity of that is not as much as I thought it would be and it’s easily offset by the added productivity of LispWorks, so maybe it was all in my head.

                                                                        1. 2

                                                                          The disruption one feels when moving one’s hand from the keyboard to the mouse depends on the distance to the mouse.

                                                                          I originally learned Vim at a workstation with a full-size keyboard and an external mouse. Moving my hand from the home row to the arrow keys already felt disruptive, and moving to the external mouse took even longer. I could clearly feel the advantage of Vim keybindings.

                                                                          Now I use a laptop with a 75% (compact tenkeyless) keyboard. Its arrow keys are much closer to the home row. The Mac laptop’s large trackpad is right below the keyboard (I use it mainly for scrolling or small cursor movements), and my external mouse is only a few inches from the keyboard’s arrow keys. That hardware difference is one reason I feel okay with using VS Code instead of Vim.

                                                                          1. 2

                                                                            I am an Emacs user rather than vim but for me a keyboard-only workflow makes a big difference. I think it has to do with the fact that I can do the keyboard operations almost automatically, as if my fingers are doing the task autonomously and without the interruption of a having to do a visual search for the right GUI element.

                                                                            And this applies to more than just coding. There is a reason people go out of their way to use keyboard-only window managers and to add keyboard navigation to web browsers.

                                                                            1. 2

                                                                              I’ve mostly had the opposite experience, but I suspect that it may be just habit forming. That is, when I use my mouse I am annoyed and slower, but I don’t know how much of that is that I am simply not practiced in doing it versus it inherently being less precise/slower.

                                                                              1. 1

                                                                                Sometimes coming at the question from a totally different angle can be illuminating. Consider this commentary from Adam Savage about his philosophy of shop organization and how it relates to flow-state. Very similar ideas there.

                                                                              2. 8

                                                                                But enter cal 1600 and we see the calendar of a leap year.

                                                                                Interestingly, this is probably not because the Gregorian leap-year calculation says so, but because the Gregorian leap-year calculation wasn’t used.

                                                                                The Julian leap-year calculation is year % 4 == 0, no exceptions, and England (and therefore most English speaking countries) switched from the Julian to Gregorian calendars on 1752-09-02. If you run cal 1752, you can see September 2 is followed immediately by September 14.

                                                                                However, the Gregorian calendar is called that because it’s named after its creator, Pope Gregory, and so different countries switched at different times depending on how well they got on with the Catholics. ncal -p will show the switchover dates for countries it knows about, with an asterisk marking the country it thinks you’re in. If you squint a bit, you can roughly group them into: Catholic countries, switching in 1582; Protestant countries, switching in the 1700s; Orthodox countries, switching in the 1900s. The last (on my computer’s ncal, anyway) is Turkey in 1926, when the new Republic of Turkey was sorting itself out.

                                                                                That’s why I said “probably” at the start there - since they’re writing in English, they’re probably in an English-speaking country and 1752 is the switchover. But if they’re living in a country that was very Catholic in the 1500s, 1600 might be presenting the Gregorian calendar after all.

                                                                                1. 3

                                                                                  Interestingly, this is probably not because the Gregorian leap-year calculation says so, but because the Gregorian leap-year calculation wasn’t used.

                                                                                  You are absolutely right. I don’t know how I missed this detail. In fact, a few years after I discovered the leap year test discussed in this post, I came across the switch from Julian to Gregorian calendar in cal 9 1752 while learning Unix. But somehow I overlooked that detail while writing this leap year test post. So thanks a lot for pointing this out. I will replace 1600 in this post with a better example soon.

                                                                                  By the way, I like how a C programming book taught me an important fact about calendar and a Unix book taught me an interesting fact about it.

                                                                                2. 4

                                                                                  This is a pretty good historical overview. He mentions how the original 8 colors for 3-bit color were black, primary additive (red, green, blue), primary subtractive (cyan, magenta, yellow), white. I have a vague feeling he is “psychologically projecting” more order onto that than was in the decision (yellow tended to be more brown than yellow..) – as partly shown by the weird numerical order. Does anyone know why they were ordered as they are? The (red, green, yellow, blue, magenta cyan) order never made sense to me.

                                                                                  EDIT: I mean, I can imagine backward compatibility with some early 1970s 2-bit (black, red, green, white) setup, with “yellow being closer to white than blue” being the “compatibility/visibility” part, but that is pure speculation / imagination.

                                                                                  1. 12

                                                                                    The (red, green, yellow, blue, magenta cyan) order never made sense to me.

                                                                                    Denoting the bits for blue, green, and red as BGR (respectively), we get:

                                                                                    Dec  Bin  Result
                                                                                    ---  ---  --------------------------
                                                                                      0  000  Black
                                                                                      1  001  Red
                                                                                      2  010  Green
                                                                                      3  011  Yellow (Red + Green)
                                                                                      4  100  Blue
                                                                                      5  101  Magenta (Red + Blue)
                                                                                      6  110  Cyan (Green + Blue)
                                                                                      7  111  White (Red + Green + Blue)
                                                                                    

                                                                                    A tiny shell command to quickly test the numbers on a modern terminal emulator:

                                                                                    for i in {0..7}; do tput setaf $i; printf "$i "; done; echo
                                                                                    

                                                                                    Most early monitors (at least all of the ones I came across) had special circuitry to reduce the green component for Red + Green, thus making the colour appear brown rather than yellow.

                                                                                    However, thanks to Color Graphics Adapter (CGA), IBM PC Logo, GW BASIC, QBASIC, etc. that I encountered in the 1990s, 1 is forever going to be blue to me, and similarly, 2 is green, 3 is cyan, 4 is red, and so on. CGA uses the least significant bit to represent blue, not red (i.e., decimal 1 = binary 001 = blue). I believe this ordering was built into the graphics adapters. For example if we wrote the bytes 41 01 (hexadecimal) directly to the video memory at the segmented address B800:0000, the monitor would show the letter A in blue colour at the top-left corner of the screen. But if we wrote the bytes 41 04 instead, we would get the letter A in red colour. As a result of this childhood bias for certain integers representing certain colours, it is a bit disconcerting to me that ANSI colour escape sequences use the least significant bit to represent red rather than blue.

                                                                                    1. 3

                                                                                      Aha! Bit-wise & additive decompositions. Now it makes quite a bit of sense { EDIT: UP to a perhaps the “bit significance endianness” of RGB you mention varying - and hey, maybe we’re lucky that only 2 orders happened in your life instead of worst case of 3!=6 :-) }.

                                                                                      THANK YOU, @susam!

                                                                                  2. 2

                                                                                    How do we now renumber all the items starting from 4) cat?

                                                                                    It’s good to know you can do this with replace but I’d tend to write the function in scratch and call it in a keyboard macro.

                                                                                    1. 2

                                                                                      For most repetitive editing tasks I prefer keyboard macros too (with or without writing a function). However for an example like this particular one, I prefer query-replace-regexp because both the regular expression pattern and the replacement text are concise enough to be typed out conveniently and quickly. Your comment made me wonder if this specific problem can be solved conveniently using keyboard macro too.

                                                                                      I’ll share the first solution that came to my mind. If I had decided to solve this with a keyboard macro, this is probably the first thing I would have done:

                                                                                      C-x 3          ; split window right
                                                                                      C-x b scr RET  ; switch to scratch buffer
                                                                                      
                                                                                      (defun decr ()
                                                                                        (interactive)
                                                                                        (insert (number-to-string
                                                                                                 (1- (string-to-number (car kill-ring))))))
                                                                                      
                                                                                      C-M-x          ; define the above function
                                                                                      C-x o          ; switch back to the window with text
                                                                                      C-s ### 4 RET  ; move point to a line to be worked on
                                                                                      
                                                                                      F3             ; start recording keyboard macro
                                                                                      
                                                                                      C-a            ; move point to beginning of line
                                                                                      M-f M-b M-d    ; kill the number
                                                                                      M-x decr RET   ; execute the function defined above
                                                                                      C-s ### RET    ; move point to next line to be worked on
                                                                                      
                                                                                      F4             ; stop recording keyboard macro
                                                                                      F4             ; call keyboard macro
                                                                                      F4             ; call keyboard macro
                                                                                      F4             ; call keyboard macro
                                                                                      C-0 F4         ; repeat keyboard macro until end of buffer
                                                                                      

                                                                                      [Screencast: https://youtu.be/QzKmmY2nV9s]

                                                                                      Did you have something similar in mind? Or do you have a simpler way of solving this using keyboard macros and a function?

                                                                                      1. 1

                                                                                        Yeah that’s pretty much what I’d do except I tend to use looking-at() and I call the macro with C-x e, then e repeatedly. Did not know about C-0 prefix!

                                                                                    2. 3

                                                                                      Congratulations on your projects. I played with the CFRS a bit.

                                                                                      My big question for you is how did you get users and attention for these projects. Did you have a following vefore hand? How did people find your projects?

                                                                                      1. 5

                                                                                        Thank you! I have a small following on Mastodon. I don’t think it played much role in getting attention for these projects. It appears to me that most of the attention to these projects came from Lobsters and HN. Usually when one of my personal tools evolve to a form that I feel it can be made public, I make a “show” post to share it with fellow programmers on these forums. For example, the “show” announcement for CFRS[] (well, its precursor CFR[] actually) was made here on Lobsters and here on HN .

                                                                                        Lobsters is a nice forum to show off hobby projects like this. Most new posts get a fair chance to be on the front page. The community here is quite supportive and the feedback is often very insightful and pertinent. On HN though, whether a post gets any attention depends a lot on timing since the posts there start out in the relatively obscure “new” section and if nobody finds the post interesting enough to upvote it within the first 30 to 60 minutes, it never makes it to the front page. In fact, in the specific example I shared in the previous paragraph, my post did not get enough upvotes to reach the front page when I posted it. Then a few days later, a moderator rescued the post via the second chance pool after which it did reach the front page and received good attention.

                                                                                      2. 13

                                                                                        Hello! This is a tiny project inspired by the very popular Tixy project. While Tixy supports JavaScript expressions to determine the size and colour of circles in a 16x16 grid, FXYT comes with its own tiny, stack-based language that is written in postfix notation. The input code is evaluated for each cell in a 256x256 grid and the result of evaluation defines the colour of each cell.

                                                                                        Some demos:

                                                                                        Visit https://github.com/susam/fxyt for more details.

                                                                                        1. 2

                                                                                          Thank you! I love everything postfix and concatenative.

                                                                                          On firefox android, I’m not seeing anything appear in the big box for these demos. I let each count up to about 90 seconds. Does it require more time, or an action on my part, or is it a browser compatibility thing, or an unexpected bug?

                                                                                          1. 3

                                                                                            It’s working for me on Firefox for Android (FF120). It’s not quite as snappy as it is on desktop, but it loads and animates and looks right.

                                                                                            1. 2

                                                                                              Oh hey, I tried it again, same phone, same browser tab, same everything, but this time it works! Thanks for the note.

                                                                                        2. 1

                                                                                          We know that b_a = 0 for distinct a,b in H because a and b are basis vectors.

                                                                                          The linear algebra in this post is a bit imprecise. Basis vectors need not be orthogonal but this article assumes they are.

                                                                                          1. 2

                                                                                            We know that b_a = 0 for distinct a, b in H because a and b are basis vectors.

                                                                                            The linear algebra in this post is a bit imprecise. Basis vectors need not be orthogonal but this article assumes they are.

                                                                                            It is not clear to me why you think that this article assumes orthogonal basis vectors. Regarding the part you quoted, i.e., b_a = 0, it follows directly from the properties of basis vectors alone.

                                                                                            Since b belongs to the vector space ℝ with basis ℋ, we can write b as unique finite linear combination of elements of ℋ. Therefore write

                                                                                                     b = sum_{a ∈ H} b_a ∙ a      (1)

                                                                                            where b_a ∈ ℚ and b_a ≠ 0. Now let

                                                                                                     b_a = 1 when b = a,

                                                                                                     b_a = 0 when b ≠ a.

                                                                                            This satisfies the equality in (1). Since the expansion of the RHS in (1) is unique, b_a = 0 must hold.

                                                                                            1. 1

                                                                                              Thanks for that, you are correct. I assumed b_a would be the projection of b onto a as it would be if they were orthogonal but that isn’t true generally.

                                                                                          2. 2

                                                                                            I use the command rg with the Emacs package dumb-jump. This is probably not the most popular way of using rg with Emacs but I have been quite happy with the results. All I need to do is package-install the dumb-jump package and configure the following hook:

                                                                                            (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
                                                                                            

                                                                                            Now the familiar Xref key sequences and commands work fine with it. For example, if I type M-. (or C-u M-.) to find definitions of an identifier in a Python project, dumb-jump runs a command like the following, processes the results, and displays the results in an Xref buffer.

                                                                                            rg --color never --no-heading --line-number -U --pcre2 --type py '\s*\bfoo\s*=[^=\n]+|def\s*foo\b\s*\(|class\s*foo\b\s*\(?' /path/to/git/project/
                                                                                            

                                                                                            Note how it automatically restricts the search to Python files and the current project directory. If no project directory is found, it defaults to the home directory.

                                                                                            It supports the silver searcher tool ag too which happens to be quite fast as well. If neither ag nor rg is found, it defaults to grep which as one would expect can be quite slow while searching the whole home directory.

                                                                                            1. 2

                                                                                              Addendum to my above comment: rg can be used quite easily with the project.el package too that comes out of the box. This is especially useful when we do not want a package like dumb-jump to perform smart things (ironical?) like restricting searches to a specific file type. We need to configure the following first otherwise it defaults to 'grep which can be quite slow on large directories:

                                                                                              (setq xref-search-program 'ripgrep)
                                                                                              

                                                                                              Then a project search with C-x p g foo RET ends up executing a command like the following on the current project directory:

                                                                                              rg -i --null -nH --no-heading --no-messages -g '!*/' -e foo
                                                                                              

                                                                                              The results are displayed in an Xref buffer again which in my opinion is the best thing about using Emacs with external search tools.

                                                                                              1. 2

                                                                                                wow, I really liked your solution, I did not know that how to configure project.el to default to ripgrep it definitely makes my life easier, I’ve never used dumb-jump before, but I bet it’s an interesting tool

                                                                                                thanks for sharing your experience

                                                                                            2. 16

                                                                                              Hello! I wrote this tiny software last night. This was written as a fun exercise. No practical usage is intended.

                                                                                              There are some demos available here: #0, #1, #2, #3, #4, #5, #6, #7.

                                                                                              More details and background about this software are available here: https://github.com/susam/cfr

                                                                                              If you end up creating some interesting demos, please share them!

                                                                                              1. 2

                                                                                                Very cool little language, and love the web based implementation.

                                                                                                A fun challenge is to try to golf a full canvas grid with 4x4 squares.

                                                                                                My first two attempts:

                                                                                                1. [[[[[[[[[[[[[[FFFFRR]]FFFF]]]]]][RRR]FFFFRR]]]]]]
                                                                                                2. [[[[[[[[[[[[[FFFFRR]RRRR]]]]]]FFFF]]]]]]
                                                                                                1. 1

                                                                                                  Seeing some of the examples here, it would be nice if you could add a button that would give people a link with the program URL encoded so that they could easily share their creations without requiring people to copy and paste.

                                                                                                  1. 1

                                                                                                    This works already! You can just put your code in the URL as an anchor (i.e. after the #). It’s just that lobsters mangles these.

                                                                                                    1. 2

                                                                                                      Thanks for closely observing how this tool works and for sharing these details. To work around the issue of mangled URLs while posting in forums like this, I have updated the tool to encode the input code in a simpler format that is going to be resistant to such mangling.

                                                                                                      Further the fragment identifier part of the URL is now updated live as we type code, so the URL is always in a form that can be distributed with others.

                                                                                                      Here is an example of a distributable link: https://susam.net/cfr.html#B15F2E7R2FBR3E6CE3

                                                                                                2. 1

                                                                                                  On mobile, there seems to be no way to run the program (I guess hitting enter on a keyboard will)?

                                                                                                  1. 1

                                                                                                    Just tired and I didn’t need to « run » anything, the canvas was being drawn on while I was adding instructions.

                                                                                                    1. 1

                                                                                                      The code executes automatically as we type each command. For example, if we enter FFFF, a column of cells are painted automatically as we type each F. However, the output may look too small on a mobile display.

                                                                                                      What happens, for example, when you enter [[[[FF]]]]? Do you see a column of painted cells that gets taller and taller as you type each closing ]?

                                                                                                      1. 3

                                                                                                        Ah, I pressed CFR and nothing appeared to happen (I didn’t know what was meant to happen, but I didn’t see anything that looked like drawing). I pressed C and R a few more times, but since they change colour and rotate, I didn’t see anything. If I press F a bunch of times, I see a line. It would be nice to have a little bit of text explaining what the things do. It made a lot more sense after reading the first paragraph of your readme.

                                                                                                    2. 2

                                                                                                      I first learnt about the <guid> element in RSS while validating my feed on https://validator.w3.org/feed/.

                                                                                                      For each <item> element that is missing the <guid> element, the validator complains like this:

                                                                                                      line 22, column 0: item should contain a guid element (3 occurrences) [help]

                                                                                                      The help link in the error message has this to say:

                                                                                                      It’s recommended that you provide the guid, and if possible make it a permalink. This enables aggregators to not repeat items, even if there have been editing changes.

                                                                                                      A frequently asked question about <guid>s is how do they compare to <link>s. Aren’t they the same thing? Yes, in some content systems, and no in others. In some systems, <link> is a permalink to a weblog item. However, in other systems, each <item> is a synopsis of a longer article, <link> points to the article, and <guid> is the permalink to the weblog entry.