Blog

For the English part of the blog, see Content AND Presentation.

2025-02-10 Running one own's commands

One of the common complaints of Emacs users is “I defined this cool little command to make my life easier and then I forgot to use it”. Well, I found one way to help with that. Every Emacs function, variable and macro somehow knows in what file it was defined, so in theory it shouldn’t be too difficult to know which functions were defined, say, in the user’s init file. Then, I could create a special version of execute-extended-command (usually bound to M-x) which could only run commands defined in the user’s init file.

It turns out that the practice is slightly more complex. One complication is that some users employ Org mode to load things on startup. For example, I have this in my init.el:

(org-babel-load-file "~/.emacs.d/init-file.org")

This means that my commands are not really defined in ~/.emacs.d/init.el, but in ~/.emacs.d/init-file.el instead. This means that I can’t just use user-init-file to get the name of the file to look for “my” commands in. Also, it was not obvious for me at first where to look for the filename where a function was defined. I even asked about it on the Emacs mailing list, and after a few hours I got the answer I needed: the load-history variable. (Interestingly, I could have found this variable myself. I looked into Emacs sources and I managed to find the symbol-file function. Had I checked it in the Elisp reference, I would probably notice that load-history is described in the same section. That is a good lesson for the future – when looking for a function, variable or macro I need, I can check the reference’s sections corresponding to related functions, variables or macros.)

Anyway, once I know about load-history, it is very easy to get the list of all commands defined in a given file.

(defcustom my-command-file user-init-file
  "File to look for commands in `execute-my-command'.")

(defun my-commands ()
  "A list of all commands defined in `my-command-file'."
  (seq-reduce
   (lambda (acc elt)
     (if (and (consp elt)
              (eq (car elt) 'defun)
              (commandp (cdr elt)))
         (cons (cdr elt) acc)
       acc))
   (alist-get my-command-file load-history nil nil #'string=)
   ()))

(After I wrote this, I learned about the file-loadhist-lookup function, which might simplify the above code a tiny bit, but I decided it’s not worth it to change it.)

Like I said above, I keep my commands in a separate place, so I can do this instead.

(setq my-command-file (expand-file-name "init-file.el" user-emacs-directory))

Since load-history contains absolute filenames, I decided to use expand-file-name and user-emacs-directory so that I can just give Emacs the name of “my command file” and not bother with typing (or copying) the absolute path to it; your mileage may vary.

Now, to run a command but with autocompletion restricted to “my commands” only it is enough to temporarily bind read-extended-command-predicate.

(defun execute-my-command (prefix-arg)
  "Execute a command found defined `my-command-file'."
  (interactive "P")
  (let* ((my-commands (my-commands))
         (read-extended-command-predicate
          (lambda (command buffer)
            (memq command my-commands))))
    (execute-extended-command prefix-arg)))

(global-set-key (kbd "s-X") #'execute-my-command)

I also bind my-commands to the result of evaluating (my-commands) (neatly using the fact that Elisp is a Lisp-2) so that the list of “my commands” is only created once per using execute-my-command. Finally, I bind it to s-X (that is, super + shift + X) and that’s it.

A bit ironically, the only remaining issue is to remember to use execute-my-command instead of the usual execute-extended-command (M-x)… Still, it’s way easier to remember one command than over a hundred of them (I indeed have that many commands defined in my init file!).

As usual, Emacs turned out to be a really great environment for people like me who like to tinker with their configs and the ways they use their computer. Not that I’m surprised!

CategoryEnglish, CategoryBlog, CategoryEmacs

Comments on this page

2025-02-01 ketchup.el

A few years ago I wrote tomato.el, which I’ve been using ever since on a daily basis. I was not always happy with it, though. The main issue I had with it is that the 25 minute intervals seemed a little bit too rigid. Oftentimes I heard a ding meaning that a tomato has just ended, and I take a short break, which disrupted my flow. Other times the short break became a bit longer and my productivity plunged. Also, it was not rare that I finished some task and saw that only, say, 18 minutes passed, so what do I do for the next 7 so that I don’t “lose” my tomato?

Some time ago, someone pointed me to an absolutely fascinating article about a concept called Third time, which really resonated with me. It also mentioned how the Pomodoro technique is worse than you might think, and even if I didn’t arrive at the exact same points, I fully agree with that criticism. To reiterate my last example, I often worked on some task A for some time – say 40 minutes – and then switched immediately to some task B, spending 10 minutes on it before taking a break. This means that I clocked just one “tomato” even though I worked for 50 minutes and “deserved” two. (I usually solved this by not clocking out of task A, which gave me the two tomatoes, but that corrupted my clock data. This was not as bad as it seems – when many of my tasks take several hours, discrepancy on the order of minutes is not really a problem, but it still bothered me a tiny bit.)

The most intriguing here is the fact that I independently devised a system very close to the “Third time” concept. I have intended to blog about it for a long time (I made an Emacs tool to help me with that about 6 years ago!), but my code still a bit buggy, so it will probably have to wait some time until I resolve its issues.

In the meantime, I decided to stop using tomato.el and introduce a new system. Instead of 25-minute chunks, it uses 5-minute ones, so the most I can “lose” if I clock out early is 4 minutes, not 24. (Since I’m going to use small pieces of a “tomato” instead of the whole ones, I decided that ketchup.el is a great name!) Of course, I still want something to incentivize me to work in longer intervals and not take a 1-minute break after each 5 minutes of work – that would be ridiculous. Here is my idea. Instead of counting “pomodoros” or “tomatoes” in Beeminder, I’m going to count abstract “points” based on these 5-minute chunks. However, the amount of points is not a linear function of the time spent working. Spending N minutes productively translates to floor(N/5)*(1+floor(N/25)) points. In other words, every 5-minute chunk is worth one point plus the number of points equal to the number of full 25-minute chunks. This way, working for a full 25-minute period still gives me a nice bonus, but stopping after 24 minutes is not worthless, either. Also, if I’m in the flow and don’t stop working after 25 minutes, but work for, say, 30 or 35, that is “better” than working for 25, taking a break and then working for the additional 5 or 10 minutes.

Initially, I thought to make this function a bit more complicated and explicitly “punish” (by awarding fewer points) continuous intervals of work of more than, say, 50 minutes. The idea is that I should take breaks and not sit down for prolonged periods of time. However, I hardly ever do that, because every now and again I need to go to the toilet, or make myself some tea, or something like that, so I figured I don’t need additional incentives for that anyway. (Case in point: I downloaded my Beeminder data for the goal I have for my daily job for several years. I had over 28 thousand datapoints – meaning 28k+ stretches of work – and only 22 of them were 90 minutes or longer.)

Interestingly, just changing the code for tomato.el so that another number of points is sent to Beeminder is not enough to achieve what I want. The first change I needed was that I no longer want notifications about some interval passing – the whole point is that I don’t want my flow to be disrupted. From now on, the plan is to work for how long it’s needed, not in rigid, 25-minute stretches. Another change is that I now need to tell Emacs that some tasks should not be awarded points. For example, I have some “tasks” for the few videogames I play, with a “do-less” Beeminder goal attached. They are mostly casual games I spend no more than 10-15 minutes on at a time. When using tomato.el, that was not a problem – in the (very rare) case of playing for 25 minutes or more, I just deleted the Beeminder datapoint manually. Now that would definitely not scale – playing for 5 or 7 or 10 minutes is something I do much more often. I decided to add another Org property, called just ketchup, which must be set to a non-empty string for the respective headline to be eligible for “ketchup points”. (Of course, this property is inherited throughout the Org file structure.)

And that’s if for today. I started a new Beeminder goal for the “ketchup points”, with a conservative slope for now, to see how it goes.

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

Comments on this page

2025-01-27 org-use-sub-superscripts

Today I have a short tip which is very niche, but potentially useful to some people. At least, it’s very useful for me. ;-)

I have a big Org file with work-related notes. This means that it contains lots of code snippets (mostly SQL, sometimes Bash or JavaScript). It also means that non-code notes often contain references to identifiers.

Being a Lisper, I obviously like my identifiers to be kebab-case. Of course, you can’t use those in SQL or JS, so in those languages I’m stuck with snake. (I hate camelCase and its ilk with passion, although Emacs can make them just a bit more palatable.)

This poses a minor but annoying problem. Surrounding each and every identifier with ~ to mark it as “code” is very inconvenient, especially when I want to copy them to the kill ring. On the other hand, if I don’t do that, I get a result looking like this:

snake case identifier.png

The reason is obvious – Org mode tries to be helpful and treats _ as introducing a subscript.

I thought that I almost never use actual subscripts in my Org documents, so why not turn this feature off? Initially I thought of a very quick and dirty hack, namely redefining the face Org mode ues to show sub- and superscripts. I learned that it is just the general face used for LaTeX fragments, so changing it might be too drastic a step. I looked at the manual, though, and was pleasantly surprised. It turns out that there is an easy way to disable treating characters or words after _ as subscripts. You just need to set the org-use-sub-superscripts option. Go read the relevant section to learn what are the possible values and how to set it up globally or only for a single Org file.

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

Comments on this page

More...