I’ve been blogging since 2005, but posts from 2005–10 have not been imported to the current iteration of my website.

Recently I have become curious about the Gemini Project and the content that people have made available to be retrieved over the gemini:// protocol. I’m not convinced by the arguments for not just using http, and mostly it’s just that I typically find more things that I am interested in casually reading through on people’s gemlogs than I would on, say, reddit, and similar aggregators. But presumably advocates of gemini:// and the text/gemini format would argue that it’s various respects in which it differs from the web that makes geminispace conducive to the production of the sort of content you find there. So I’m remaining open minded about the possibility that having a completely separate protocol is important, and not just an annoyance because rss2email doesn’t work and I had to spend time writing gmi2email.

I now have a games console at home for the first time in some years, which I bought in response to the ongoing pandemic, and one thing that I have noticed is that using it feels like being offline in a way that playing games on a regular computer never would. It has a WiFi connection but it doesn’t have a web browser, and I am glad that using it provides an opportunity to be disconnected from the usual streams of information. And perhaps something similar ought to be said in favour of how the Gemini project does not just use http. There is, perhaps, a positive psychological effect induced by making the boundary between text/gemini and the web as hard as it is made by using gemini:// rather than http.

Something about which I find myself much more sceptical is how the specification for gemini:// and text/gemini is not extensible. Advocates of Gemini have this idea that they can’t include, say, a version number in the protocol, because the extensibility of the web is what has led to the problems they think it has, so they want to make it impossible. Now on the one hand perhaps the people behind Gemini are in the best position that anyone is in to come up with a spec which they will finalise and render effectively unchangeable, because a lot of them have been using Gopher for decades, and so they have enough experience to be able to say exactly what Gopher is missing, and be confident that they’ve not missed anything. But on the other hand, Gemini is one technological piece in attempts to make a version of the Internet which is healthier for humans – the so-called “small Internet” movement – and maybe there will be new ideas about how the small Internet should be which would benefit from a new version of the Gemini specification. So it seems risky to lock-in to one version.

Comments on Hacker News.

Posted Sun 31 Jan 2021 19:21:48 UTC Tags:

Update 5/ii/2021: It turns out that C-x z not repeating complex commands was an upstream bug introduced in Emacs 22, and is now fixed in the development branch of Emacs 28. So the following code is only interesting to users of Emacs 22 to 27.

In Emacs, you can use C-x z to repeat the last command you input, and subsequently you can keep tapping the ‘z’ key to execute that command again and again. If the command took minibuffer input, however, you’ll be asked for that input again. For example, suppose you type M-z : to delete through the next colon character. If you want to keep going and delete through the next few colons, you would need to use C-x z : z : z : etc. which is pretty inconvenient. So there’s also C-x ESC ESC RET or C-x M-: RET, which will repeat the last command which took minibuffer input, as if you’d given it the same minibuffer input. So you could use M-z : C-x M-: RET C-x M-: RET etc., but then you might as well just keep typing M-z : over and over. It’s also quite inconvenient to have to remember whether you need to use C-x z or C-x M-: RET.

I wanted to come up with a single command which would choose the correct repetition method. It turns out it’s a bit involved, but here’s what I came up with. You can use this under the GPL-3 or any later version published by the FSF. Assumes lexical binding is turned on for the file you have this in.

;; Adapted from `repeat-complex-command' as of November 2020
(autoload 'repeat-message "repeat")
(defun spw/repeat-complex-command-immediately (arg)
  "Like `repeat-complex-command' followed immediately by RET."
  (interactive "p")
  (if-let ((newcmd (nth (1- arg) command-history)))
        (add-to-history 'command-history newcmd)
        (repeat-message "Repeating %S" newcmd)
        (apply #'funcall-interactively
               (car newcmd)
               (mapcar (lambda (e) (eval e t)) (cdr newcmd))))
    (if command-history
        (error "Argument %d is beyond length of command history" arg)
      (error "There are no previous complex commands to repeat"))))

(let (real-last-repeatable-command)
  (defun spw/repeat-or-repeat-complex-command-immediately ()
    "Call `repeat' or `spw/repeat-complex-command-immediately' as appropriate.

Note that no prefix argument is accepted because this has
different meanings for `repeat' and for
`spw/repeat-complex-command-immediately', so that might cause surprises."
    (if (eq last-repeatable-command this-command)
        (setq last-repeatable-command real-last-repeatable-command)
      (setq real-last-repeatable-command last-repeatable-command))
    (if (eq last-repeatable-command (caar command-history))
        (spw/repeat-complex-command-immediately 1)
      (repeat nil))))

;; `suspend-frame' is bound to both C-x C-z and C-z
(global-set-key "\C-z" #'spw/repeat-or-repeat-complex-command-immediately)
Posted Sun 08 Nov 2020 21:16:09 UTC Tags:

Marks and mark rings in GNU Emacs

I recently attempted to answer the question of whether experienced Emacs users should consider partially or fully disabling Transient Mark mode, which is (and should be) the default in modern GNU Emacs.

That blog post was meant to be as information-dense as I could make it, but now I’d like to describe the experience I have been having after switching to my custom pseudo-Transient Mark mode, which is labelled “mitigation #2” in my older post.

In summary: I feel like I’ve uncovered a whole editing paradigm lying just beneath the surface of the editor I’ve already been using for years. That is cool and enjoyable in itself, but I think it’s also helped me understand other design decisions about the basics of the Emacs UI better than before – in particular, the ideas behind how Emacs chooses where to display buffers, which were very frustrating to me in the past. I am now regularly using relatively obscure commands like C-x 4 C-o. I see it! It all makes sense now!

I would encourage everyone who has never used Emacs without Transient Mark mode to try turning it off for a while, either fully or partially, just to see what you can learn. It’s fascinating how it can come to seem more convenient and natural to pop the mark just to go back to the end of the current line after fixing up something earlier in the line, even though doing so requires pressing two modified keys instead of just C-e.


I was amused to learn some years ago that someone was trying to make Emacs work as an X11 window manager. I was amazed and impressed to learn, more recently, that the project is still going and a fair number of people are using it. Kudos! I suspect that the basic motivation for such projects is that Emacs is a virtual Lisp machine, and it has a certain way of managing visible windows, and people would like to be able to bring both of those to their X11 window management.

However, I am beginning to suspect that the intrinsic properties of Emacs buffers are tightly connected to the ways in which Emacs manages visible windows, and the intrinsic properties of Emacs buffers are at least as fundamental as its status as a virtual Lisp machine. Thus I am not convinced by the idea of trying to use Emacs’ ways of handling visible windows to handle windows which do not contain Emacs buffers. (but it’s certainly nice to learn it’s working out for others)

The more general point is this. Emacs buffers are as fundamental to Emacs as anything else is, so it seems unlikely to be particularly fruitful to move something typically done outside of Emacs into Emacs, unless that activity fits naturally into an Emacs buffer or buffers. Being suited to run on a virtual Lisp machine is not enough.

What could be more suited to an Emacs buffer, however, than a typical Unix command shell session? By this I mean things like running commands which produce text output, and piping this output between commands and into and out of files. Typically the commands one enters are sort of like tiny programs in themselves, even if there are no pipes involved, because you have to spend time determining just what options to pass to achieve what you want. It is great to have all your input and output available as ordinary buffer text, navigable just like all your other Emacs buffers.

Full screen text user interfaces, like top(1), are not the sort of thing I have in mind here. These are suited to terminal emulators, and an Emacs buffer makes a poor terminal emulator – what you end up with is a sort of terminal emulator emulator. Emacs buffers and terminal emulators are just different things.

These sorts of thoughts lead one to Eshell, the Emacs Shell. Quoting from its documentation:

The shell’s role is to make [system] functionality accessible to the user in an unformed state. Very roughly, it associates kernel functionality with textual commands, allowing the user to interact with the operating system via linguistic constructs. Process invocation is perhaps the most significant form this takes, using the kernel’s fork' andexec’ functions.

Emacs is … a user application, but it does make the functionality of the kernel accessible through an interpreted language – namely, Lisp. For that reason, there is little preventing Emacs from serving the same role as a modern shell. It too can manipulate the kernel in an unpredetermined way to cause system changes. All it’s missing is the shell-ish linguistic model.

Eshell has been working very well for me for the past month or so, for, at least, Debian packaging work, which is very command shell-oriented (think tools like dch(1)).

The other respects in which Eshell is tightly integrated with the rest of Emacs are icing on the cake. In particular, Eshell can transparently operate on remote hosts, using TRAMP. So when I need to execute commands on Debian’s ftp-master server to process package removal requests, I just cd /ssh:fasolo: in Eshell. Emacs takes care of disconnecting and connecting to the server when needed – there is no need to maintain a fragile SSH connection and a shell process (or anything else) running on the remote end.

Or I can cd /ssh:athena\|sudo:root@athena: to run commands as root on the webserver hosting this blog, and, again, the text of the session survives on my laptop, and may be continued at my leisure, no matter whether athena reboots, or I shut my laptop and open it up again the next morning. And of course you can easily edit files on the remote host.

Update 31/Jan/2021: I now find myself mostly using M-!, M-&, C-x p ! and C-x p & to run shell commands. It would seem that the “shell-ish linguistic model” is less important to the work that I do than I thought it was. Thus, I was getting even less out of running bash in terminal emulators than I thought. I still reach for Eshell for Debian packaging work, I think because tools like dch assume the shell linguistic model.

Posted Thu 23 Jul 2020 18:55:24 UTC

A little under two months ago I invested in an expensive ergonomic keyboard, a Kinesis Advantage 2, and set about figuring out how to use it most effectively with Emacs. The default layout for the keyboard is great for strong typists who control their computer mostly with their mouse, but less good for Emacs users, who are strong typists that control their computer mostly with their keyboard.

It took me several tries to figure out where to put the ctrl, alt, backspace, delete, return and spacebar keys, and aside from one forum post I ran into, I haven’t found anyone online who came up with anything much like what I’ve come up with, so I thought I should probably write up a blog post.

The mappings

  • The pairs of arrow keys under the first two fingers of each hand become ctrl and alt/meta keys. This way there is a ctrl and alt/meta key for each hand, to reduce the need for one-handed chording.

    I bought the keyboard expecting to have all modifier keys on my thumbs. However, (i) only the two large thumb keys can be pressed without lifting your hand away from the home row, or stretching in a way that’s not healthy; and (ii) only the outermost large thumb key can be comfortably held down as a modifier.

    It takes a little work to get used to using the third and fifth fingers of one hand to hold down both alt/meta and shift, for typing core Emacs commands like M-^ and M-@, but it does become natural to do so.

  • The arrow keys are moved to the four ctrl/alt/super keys which run along the top of the thumb key areas.

  • The outermost large thumb key of each hand becomes a spacebar. This means it is easy to type C-u C-SPC with the right hand while the left hand holds down control, and sequences like C-x C-SPC and C-a C-SPC C-e with the left hand with the right hand holding down control.

    It took me a while to realise that it is not wasteful to have two spacebars.

  • The inner large thumb keys become backspace and return.

  • The international key becomes delete.

    Rarely needed for Emacs users, as we have C-d, so initially I just had no delete key, but soon came to regret this when trying to edit text in web forms.

  • Caps Lock becomes Super, but remains caps lock on the keypad layer.

    See my rebindings for ordinary keyboards for some discussion of having just a single Super key.

Sequences of two modified keys on different halves of the keyboard

It is desirable to input sequences like C-x C-o without switching which hand is holding the control key. This requires one-handed chording, but this is trecherous when the modifier keys not under the thumbs, because you might need to press the modified key with the same finger that’s holding the modifier!

Fortunately, most or all sequences of two keys modified by ctrl or alt/meta, where each of the two modifier keys is typed by a different hand, begin with C-c, C-x or M-g, and the left hand can handle each of these on its own. This leaves the right hand completely free to hit the second modified key while the left hand continues to hold down the modifier.

My rebindings for ordinary keyboards

I have some rebindings to make Emacs usage more ergonomic on an ordinary keyboard. So far, my Kinesis Advantage setup is close enough to that setup that I’m not having difficulty switching back and forth from my laptop keyboard.

The main difference is for sequences of two modified keys on different halves of the keyboard – which of the two modified keys is easiest to type as a one-handed chord is different on the Kinesis Advantage than on my laptop keyboard. At this point, I’m executing these sequences without any special thought, and they’re rare enough that I don’t think I need to try to determine what would be the most ergonomic way to handle them.

Posted Thu 23 Jul 2020 16:44:27 UTC Tags:

I’ve been less good at taking adequate typing breaks during the lockdown and I’ve become concerned about how much chording my left hand does on its own during typical Emacs usage, with caps lock rebound to control, as I’ve had it for years.

I thought that now was as good a time as any to do something drastic about this. Here are my rebindings:

  • the keys on either side of the spacebar are control
  • the keys just outside of those are alt/meta
  • caps lock is Super, Windows or Command depending on OS
  • move any window manager keybindings which now become one handed left hand chords such that they are not.

Optional extras:

  • left control is caps lock
  • right control is the compose key.

This has the following advantages:

  • you can easily achieve this rebinding on GNU/Linux, Windows and macOS
  • almost every keyboard has enough keys near the spacebar to make it work, and it’s fine to have just one super key since it is not involved in any one handed chords
  • does not involve relying on the difference between tapping and releasing and holding a modifier key, which I find fragile
  • there are control and alt/meta keys available to both hands, so there is much less call for one-handed chording
  • control and alt/meta are pressed by the thumb, the strongest finger, so when one-handed chording does come up (e.g. C-x C-o without having to switch between control keys) it’s the least harmful form
    • my plan is to use the control/meta key available to the opposite hand for the first key of each sequence, and allow some one handed chording to complete the sequence.
      • Update 23/Jul/2020: I’ve found that I’m typing some of these sequences by performing a one-handed chord in order to type the second key, as planned, and others by performing a one-handed chord in order to type the first key. There are actually only a handful of these sequences, so it seems okay to have sequence-specific habits.
    • there is some temptation to use a curled up little finger on the new alt/meta key, I’m finding, but I’m trying to stop myself from doing that.

The main disadvantage, aside from an adjustment period when I feel that someone has inserted a massive marshmellow between me and my computer, is that Ctrl-Alt combinations are a bit difficult; in Emacs, C-M-SPC is hard to do without. However I think I’ve found a decent way to do it (thumb on control, curled ring finger on alt, possibly little finger on shift for Emacs’ infamous C-M-S-v standard binding). (Update 23/Jul/2020: this has been working out fine.)

Posted Fri 05 Jun 2020 16:21:48 UTC

Something I’ve found myself doing as the pandemic rolls on is picking out and (re-)reading through sections of the GNU Emacs manual and the GNU Emacs Lisp reference manual. This has got me (too) interested in some of the recent history of Emacs development, and I did some digging into archives of emacs-devel from 2008 (15M mbox) regarding the change to turn Transient Mark mode on by default and set mark-even-if-inactive to true by default in Emacs 23.1.

It’s not always clear which objections to turning on Transient Mark mode by default take into account the mark-even-if-inactive change. I think that turning on Transient Mark mode along with mark-even-if-inactive is a good default. The question that remains is whether the disadvantages of Transient Mark mode are significant enough that experienced Emacs users should consider altering Emacs’ default behaviour to mitigate them. Here’s one popular blog arguing for some mitigations.

How might Transient Mark mode be disadvantageous?

The suggestion is that it makes using the mark for navigation rather than for acting on regions less convenient:

  1. setting a mark just so you can jump back to it (i) is a distinct operation you have to think of separately; and (ii) requires two keypresses, C-SPC C-SPC, rather than just one keypress

  2. using exchange-point-and-mark activates the region, so to use it for navigation you need to use either C-u C-x C-x or C-x C-x C-g, neither of which are convenient to type, or else it will be difficult to set regions at the place you’ve just jumped to because you’ll already have one active.

There are two other disadvantages that people bring up which I am disregarding. The first is that it makes it harder for new users to learn useful ways in which to use the mark when it’s deactivated. This happened to me, but it can be mitigated without making any behavioural changes to Emacs. The second is that the visual highlighting of the region can be distracting. So far as I can tell, this is only a problem with exchange-point-and-mark, and it’s subsumed by the problem of that command actually activating the region. The rest of the time Emacs’ automatic deactivation of the region seems sufficient.

How might disabling Transient Mark mode be disadvantageous?

When Transient Mark mode is on, many commands will do something usefully different when the mark is active. The number of commands in Emacs which work this way is only going to increase now that Transient Mark mode is the default.

If you disable Transient Mark mode, then to use those features you need to temporarily activate Transient Mark mode. This can be fiddly and/or require a lot of keypresses, depending on exactly where you want to put the region.

Without being able to see the region, it might be harder to know where it is. Indeed, this is one of the main reasons for wanting Transient Mark mode to be the default, to avoid confusing new users. I don’t think this is likely to affect experienced Emacs users often, however, and on occasions when more precision is really needed, C-u C-x C-x will make the region visible. So I’m not counting this as a disadvantage.

How might we mitigate these two sets of disadvantages?

Here are the two middle grounds I’m considering.

Mitigation #1: Transient Mark mode, but hack C-x C-x behaviour

(defun spw/exchange-point-and-mark (arg)
  "Exchange point and mark, but reactivate mark a bit less often.

Specifically, invert the meaning of ARG in the case where
Transient Mark mode is on but the region is inactive."
  (interactive "P")
   (if (and transient-mark-mode (not mark-active))
       (not arg)
(global-set-key [remap exchange-point-and-mark] 'spw/exchange-point-and-mark)

We avoid turning Transient Mark mode off, but mitigate the second of the two disadvantages given above.

I can’t figure out why it was thought to be a good idea to make C-x C-x reactivate the mark and require C-u C-x C-x to use the action of exchanging point and mark as a means of navigation. There needs to a binding to reactivate the mark, but in roughly ten years of having Transient Mark mode turned on, I’ve found that the need to reactivate the mark doesn’t come up often, so the shorter and longer bindings seem the wrong way around. Not sure what I’m missing here.

Mitigation #2: disable Transient Mark mode, but enable it temporarily more often

(setq transient-mark-mode nil)
(defun spw/remap-mark-command (command &optional map)
  "Remap a mark-* command to temporarily activate Transient Mark mode."
  (let* ((cmd (symbol-name command))
         (fun (intern (concat "spw/" cmd)))
         (doc (concat "Call `"
                      "' and temporarily activate Transient Mark mode.")))
    (fset fun `(lambda ()
                 (call-interactively #',command)
    (if map
        (define-key map (vector 'remap command) fun)
      (global-set-key (vector 'remap command) fun))))

(dolist (command '(mark-word
  (spw/remap-mark-command command))
(with-eval-after-load 'org
  (spw/remap-mark-command 'org-mark-element org-mode-map)
  (spw/remap-mark-command 'org-mark-subtree org-mode-map))

;; sometimes a key to just activate the mark is wanted
(global-set-key "\M-i" (lambda () (interactive) (activate-mark)))
;; resettle the previous occupant
(global-set-key "\M-I" #'tab-to-tab-stop)

Here we remove both of the disadvantages of Transient Mark mode given above, and mitigate the main disadvantage of not activating Transient Mark mode by making it more convenient to activate it temporarily.

For example, this enables using C-M-SPC C-M-SPC M-( to wrap the following two function arguments in parentheses. And you can hit M-h a few times to mark some blocks of text or code, then operate on them with commands like M-% and C-/ which behave differently when the region is active.1

Comparing these mitigations

Both of these mitigations handle the second of the two disadvantages of Transient Mark mode given above. What remains, then, is

  1. under the effects of mitigation #1, how much of a barrier to using marks for navigational purposes is it to have to press C-SPC C-SPC instead of having a single binding, C-SPC, for all manual mark setting2

  2. under the effects of mitigation #2, how much of a barrier to taking advantage of commands which act differently when the region is active is it to have to temporarily enable Transient Mark mode with C-SPC C-SPC, M-i or one of the mark-* commands?

These are unknowns.3 So I’m going to have to experiment, I think, to determine which mitigation to use, if either. In particular, I don’t know whether it’s really significant that setting a mark for navigational purposes and for region marking purposes are distinct operations under mitigation #1.

My plan is to start with mitigation #2 because that has the additional advantage of allowing me to confirm or disconfirm my belief that not being able to see where the region is will only rarely get in my way.

Update 23/Jul/2020: A little less than two months later, mitigation #2 has worked out so well that I do not intend to try out mitigation #1. Transient Mark mode gets activated pretty much whenever it needs to be, mainly by means of M-h and C-M-SPC, and occasionally by C-SPC C-SPC or M-i, without much effort. I’ve been using marks for navigation effectively, except for struggling to set quite enough marks – I keep thinking “time to jump back … oh, once again, I failed to set a mark before coming here.” This seems a surmountable difficulty.

  1. The idea of making the mark-* commands activate the mark comes from an emacs-devel post by Stefan Monnier in the archives linked above.
  2. One remaining possibility I’m not considering is mitigation #1 plus binding something else to do the same as C-SPC C-SPC. I don’t believe there are any easily rebindable keys which are easier to type than typing C-SPC twice. And this does not deal with the two distinct mark-setting operations problem.
  3. Another way to look at this is the question of which of setting a mark for navigational purposes and activating a mark should get C-SPC and which should get C-SPC C-SPC.
Posted Sat 30 May 2020 22:55:25 UTC Tags:

I realised this week that for some years I have been applying Inbox Zero indiscriminately to all e-mail that I receive, but this does not make sense, and has some downsides.

My version of Inbox Zero works very well when applied to mail addressed directly to me, and for mail to certain mailing lists, where each post to the list might as well be addressed directly to me, in addition to the list. However, I also receive by e-mail the following things to which I now believe Inbox Zero should not be applied:

  • discussion lists like debian-devel, notmuch@notmuchmail.org, etc.

  • mail to aliases like ftpmaster@debian.org (except when that mail is in reply to mail written by me from that address)

  • automated notifications received via Debian team mailing lists, where I’m not solely responsible for the Debian package in question, such as notifications received via the Debian Perl Group’s mailing list

  • RSS feed articles supplied by my (years old but still going strong) rss2email cronjob.

I believe that applying Inbox Zero to these sorts of things is not only incorrect but is actually harming my engagement with these mediums. Let us distinguish

  1. processing e-mail – this means applying the Inbox Zero decision procedure to incoming messages, at set times during the day (I do it once, around 4pm)

  2. browsing and sometimes catching up RSS articles and list mail – looking through unread items, replying if I think I have something useful to say, leaving things for later, and occasionally marking all as read if I’ve not had time for that group of lists lately.

These should be kept apart. The easy case to see is why you shouldn’t apply the browsing/catching up approach to e-mail which should rather be processed – that’s just the original wisdom of Inbox Zero. And clearly you don’t want ever to have to resort to just marking all mail addressed directly to you as read.

What goes wrong, then, if you misapply the processing mentality to e-mail which should, rather, be browsed/caught up? Well, the core of Inbox Zero is deciding whether to read and reply to something right now, add it to your todo list to handle later, or decide the mail cannot be dealt with quickly but is not important enough to go on that todo list. If you apply this to RSS articles and discussion list mail, then the third option is basically ruled out, because almost nothing on mailing lists or on blogs that I follow is important enough to go on my list of Real Tasks. But then you’re faced with either reading the article/post right now, or discarding it. There is no option to leave the item marked as unread and then maybe come back to it, or postpone discarding it until you’ve decided to catch up the group. Applying Inbox Zero to discussion lists and RSS feeds creates a false sense of urgency.

I’ve realised that my implicit response to this has been reluctance to subscribe to new mailing lists and feeds, because I don’t have things set up to allow me to read them in a leisurely way. But then I’m missing out on discussions and writing that might be relevant and beneficial to me if I could only approach them when I’m in a frame of mind other than “time to get my inbox down to zero”.

This also means that subscribing to new mailing lists just in order to post something has an unreasonably high cost: introducing all mail on those lists into my Inbox Zero processing window.

So, what’s needed is to make the virtual folder views which I use to read new mail correspond cleanly to the distinction between mail to be processed and mail to be browsed. I.e. for each virtual folder it should be clear whether mail there is to be processed or to be browsed. Then I can continue to use my processing views once per day, and access the browsing views at leisure. (Indeed, I’ve created a keybinding to cycle through the new browsing views, and another to catch them up.)

As I mentioned, some list mail ought to be processed. For example, I want to process rather than browse the debian-policy mailing list, as one of the Policy Editors. With notmuch, it’s easy to include this mail in the relevant processing views (I’ve long had one processing view for weekdays and another for weekends).

Additionally, I’ve used a bit of Emacs Lisp to create a dynamic “uncategorised unread” view which catches mail to be browsed which (i) doesn’t show up in one of the other virtual folders for mail to be browsed, and (ii) doesn’t show up in one of the processing views. So now subscribing to a mailing list is cheap: mail will end up in the uncategorised view, and I can decide whether to leave it there for a low traffic list; create a new virtual folder for the list (trivial as it’s all just more Emacs Lisp, no actual moving of files required); or unsubscribe.

I’ve been experiencing nostalgia for my time in secondary school when my friends and I had all sorts of interesting stuff flowing into our mailstores, from RSS feeds to each other’s blogs where we’d post both our own content and links elsewhere, RSS feeds to stranger’s blogs, and e-mails sent to each other with links. We didn’t have to worry about processing anything back then, as our e-mail accounts were used for intellectual enrichment but not the completion of tasks. I think I can recapture something of that with my new virtual folders for browsing.

Posted Sun 03 May 2020 20:09:28 UTC Tags:

Before uploading stuff to Debian, I build in a clean chroot, and then run piuparts, autopkgtest and lintian. For some of my packages this can take around an hour on my laptop, which is fairly old. Normally I don’t mind waiting, but sometimes I want to put my laptop away, and then it would be good for things to be faster. It occurred to me that I could make use of my builds.sr.ht account to run these tests on more powerful hardware.

This build manifest seems to work:

  - https://salsa.debian.org/perl-team/modules/packages/libgit-annex-perl.git
  source: libgit-annex-perl
  quilt:  auto

image: debian/unstable
  - autopkgtest
  - devscripts
  - dgit
  - lintian
  - piuparts
  - sbuild
  - setup: |
      cd $source
      source_version=$(dpkg-parsechangelog -SVersion)
      echo "source_version=$source_version" >>~/.buildenv
      git deborig || origtargz
      sudo sbuild-createchroot --command-prefix=eatmydata --include=eatmydata unstable /srv/chroot/unstable-amd64-sbuild
      sudo sbuild-adduser $USER
  - build: |
      cd $source
      dgit --quilt=$quilt sbuild -d unstable --no-run-lintian
  - lintian: |
      lintian ${source}_${source_version}_multi.changes
  - piuparts: |
      sudo piuparts --no-eatmydata --schroot unstable-amd64-sbuild ${source}_${source_version}_multi.changes
  - autopkgtest: |
      autopkgtest ${source}_${source_version}_multi.changes -- schroot unstable-amd64-sbuild

And here’s my script.

Posted Fri 03 Apr 2020 17:47:07 UTC Tags:

Last summer I read chromatic’s Modern Perl, and was recommended to default to using Moo or Moose to define classes, rather than writing code to bless things into objecthood myself. At the time the project I was working on needed to avoid any dependencies outside of the Perl core, so I made a mental note of the advice, but didn’t learn how to use Moo or Moose. I do remember feeling like I was typing out a lot of boilerplate, and wishing I could use Moo or Moose to reduce that.

In recent weeks I’ve been working on a Perl distribution which can freely use non-core dependencies from CPAN, and so right from the start I used Moo to define my classes. It seemed like a no-brainer because it’s more declarative; it didn’t seem like there could be any disadvantages.

At one point, when writing a new class, I got stuck. I needed to call one of the object’s methods immediately after instantiation of the object. BUILDARGS is, roughly, the constructor for Moo/Moose classes, so I started there, but you don’t have access to the new object during BUILDARGS, so you can’t simply call its methods on it. So what I needed to do was change my design around so as to be more conformant to the Moo/Moose view of the world, such that the work of the method call could get done at the right time. I mustn’t have been in a frame of mind for that sort of thinking at the time because what I ended up doing was dropping Moo from the package and writing a constructor which called the method on the new object, after blessing the hash, but before returning a hashref to the caller.

This was my first experience of having the call to bless() not be the last line of my constructor, and I believe that this simple dislocation helped significantly improved my grip on core Perl 5 classes and objects: the point is that they’re not declarative—they’re collections of functionality to operate on encapsulated data, where the instantiation of that data, too, is a piece of functionality. I had been thinking about classes too declaratively, and this is why writing out constructors and accessors felt like boilerplate. Now writing those out feels like carefully setting down precisely what functionality for operating on the encapsulated data I want to expose. I also find core Perl 5 OO quite elegant (in fact I find pretty much everything about Perl 5 highly elegant, except of course for its dereferencing syntax; not sure why this opinion is so unpopular).

I then came across the Cor proposal and followed a link to this recent talk criticising Moo/Moose. The speaker, Tadeusz Sośnierz, argues that Moo/Moose implicitly encourages you to have an accessor for each and every piece of the encapsulated data in your class, which is bad OO. Sośnierz pointed out that if you take care to avoid generating all these accessors, while still having Moo/Moose store the arguments to the constructor provided by the user in the right places, you end up back with a new kind of boilerplate, which is Moo/Moose-specific, and arguably worse than what’s involved in defining core Perl 5 classes. So, he asks, if we are going to take care to avoid generating too many accessors, and thereby end up with boilerplate, what are we getting out of using Moo/Moose over just core Perl 5 OO? There is some functionality for typechecking and method signatures, and we have the ability to use roles instead of multiple-inheritance.

After watching Sośnierz talk, I have been rethinking about whether I should follow Modern Perl’s advice to default to using Moo/Moose to define new classes, because I want to avoid the problem of too many accessors. Considering the advantages of Moo/Moose Sośnierz ends up with at the end of his talk: I find the way that Perl provides parameters to subroutines and methods intuitive and flexible, and don’t see the need to build typechecking into that process—just throw some exceptions with croak() if the types aren’t right, before getting on with the business logic of the subroutine or method. Roles are a different matter. These are certainly an improvement on multiple inheritance. But there is Role::Tiny that you can use instead of Moo/Moose.

So for the time being it seems I should go back to blessing hashes, and that I should also get to grips with Role::Tiny. I don’t have a lot of experience with OO design, so can certainly imagine changing my mind about things like Perlish typechecking and subroutine signatures (I also don’t understand, yet, why some people find the convention of prefixing private methods and attributes with an underscore not to be sufficient—Cor wants to add attribute and method privacy to Perl). However, it seems sensible to avoid using things like Moo/Moose until I can be very clear in my own mind about what advantages using them is getting me. Bad OO with Moo/Moose seems worse than occasionally simplistic, occasionally tedious, but correct OO with the Perl 5 core.

Posted Tue 11 Feb 2020 16:23:38 UTC Tags:

There hasn’t been much activity lately, but no shortage of interesting and hopefully-accessible Debian Policy work. Do write to debian-policy@lists.debian.org if you’d like to participate but are struggling to figure out how.

Consensus has been reached and help is needed to write a patch:

#425523 Describe error unwind when unpacking a package fails

#452393 Clarify difference between required and important priorities

#582109 document triggers where appropriate

#592610 Clarify when Conflicts + Replaces et al are appropriate

#682347 mark ‘editor’ virtual package name as obsolete

#685506 copyright-format: new Files-Excluded field

#749826 [multiarch] please document the use of Multi-Arch field in debian/c…

#757760 please document build profiles

#770440 policy should mention systemd timers

#823256 Update maintscript arguments with dpkg >= 1.18.5

#905453 Policy does not include a section on NEWS.Debian files

#907051 Say much more about vendoring of libraries

Wording proposed, awaiting review from anyone and/or seconds by DDs:

#786470 [copyright-format] Add an optional “License-Grant” field

#919507 Policy contains no mention of /var/run/reboot-required

#920692 Packages must not install files or directories into /var/cache

#922654 Section 9.1.2 points to a wrong FHS section?

Posted Mon 02 Sep 2019 22:04:36 UTC Tags: