Journal

2018-11-19 Font-locking diff blocks in Org-mode

I sometimes miss a feature in Emacs where I could make a diff of two files (using Emacs built-in dired-diff command, bound to = in Dired, or abo-abo’s diff trick, which I have bound to e in Dired), but have the diff persist (as in, save it to a file). Technically, I can do this, of course, by just calling write-file and saving it to a file (preferably with a .diff extension so that it will open in Diff mode automatically), but sometimes I prefer to save things in my Org-mode file, along with my notes related to the project I’m working on.

It turns out that Org-mode has me covered, although there is one minor caveat here. I can say

#+begin_src diff
diff -ur /mem/aqq /mem/bum
--- /mem/aqq	2018-10-29 08:40:07.639993680 +0100
+++ /mem/bum	2018-10-29 08:40:15.329993584 +0100
@@ -1,3 +1,3 @@
 lorem
 ipsum
-dolor
+sit amet

Diff finished.  Mon Oct 29 08:40:20 2018
#+end_src

but if I edit this source block using C-c ' (org-edit-special) and then save it e.g. using C-c ' (org-edit-src-exit=), Org-mode enforces indentation of two spaces. This, however, fools Diff-mode’s font-locking features and I lose the coloring of the diff.

There is a way out of it, though. Either you can be careful not to run org-edit-special on the diff block, or you can set org-edit-src-content-indentation to 0.

I know that because I asked on the Org-mode mailing list, and I got a few helpful responses. Make sure to read them (and the docstrings of the mentioned variables) if that is of interest for you.

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

Comments on this page

2018-11-11 Poland gained independence 100 years ago

Today we again depart from the usual topics of my blog. We have a very important day today in Poland – one hundred years ago my country gained independence after more than a hundred years of political nonexistence.

Just imagine that. Three enemy countries tried really hard for about five generations to wipe out our country, our culture, even our language out.

They failed.

If you are a reader of my blog, please do me a small favor and try to find some good source about Polish history and spend some time reading that. Now. You will learn some fascinating stuff, which could make for quite a lot great books and/or movies (and indeed there are quite a few). In particular, you might want to find out the meaning of 966, 12 September 1683, 27 December 1918, or August 12–25, 1920, just to name a few events, some of them important not only to Poland, but also to Europe.

At such moments I am really proud to be a Pole.

CategoryEnglish, CategoryBlog

Comments on this page

2018-11-03 A few remarks about defining minor modes

Today’s post is extremely technical and niche, but I just wanted to share an interesting story I had a few days ago.

So I have this minor mode I defined, using the classical construction:

(defun cool-start ()
  "Start the cool-mode.")

(defun cool-stop ()
  "Stop the cool-mode.")

(define-minor-mode my-cool-minor-mode
  "Toggle a mode for doing cool stuff."
  :init-value nil
  :lighter " 8-)"
  (if my-cool-minor-mode
      (cool-start)
    (cool-stop)))

What I wanted to know is whether I could use the prefix argument to decide what to do when starting the mode. This seems a bit risky, since the prefix argument is already used to turn the mode on or off.

Actually, the documentation is a bit misleading on the treatment of the argument to my-cool-minor-mode command. Here an excerpt from what the Emacs manual says:

  • If you invoke the mode command directly with no prefix argument (either via ‘M-x’, or by binding it to a key and typing that key […]), that “toggles” the minor mode. The minor mode is turned on if it was off, and turned off if it was on.
  • If you invoke the mode command with a prefix argument, the minor mode is unconditionally turned off if that argument is zero or negative; otherwise, it is unconditionally turned on.
  • If the mode command is called via Lisp, the minor mode is unconditionally turned on if the argument is omitted or ‘nil’. This makes it easy to turn on a minor mode from a major mode’s mode hook […]. A non-‘nil’ argument is handled like an interactive prefix argument, as described above.

And here is a quote from the Elisp manual:

The toggle command takes one optional (prefix) argument. If called interactively with no argument it toggles the mode on or off. A positive prefix argument enables the mode, any other prefix argument disables it. From Lisp, an argument of ‘toggle’ toggles the mode, whereas an omitted or ‘nil’ argument enables the mode. This makes it easy to enable the minor mode in a major mode hook, for example. If DOC is ‘nil’, the macro supplies a default documentation string explaining the above.

As you can see, from the Elisp manual it is not entirely clear whether you can supply numeric arguments from your code (obviously, you can’t supply a 'toggle argument interactively).

It turns out that the define-minor-mode macro defines the function responsible for turning the mode on and off, and does it in a pretty complicated way.

First of all, the macro contains this snippet:

(interactive (list (or current-prefix-arg 'toggle)))

which means that no argument (when called interactively) is precisely equivalent to an argument of 'toggle.

One of the next things that follow is this trick:

(,@setter
 (if (eq arg 'toggle)
     (not ,getter)
   ;; A nil argument also means ON now.
   (> (prefix-numeric-value arg) 0)))

Earlier, define-minor-mode sets setter to (setq <mode-name>) and getter to just <mode-name>. This is quite clever: getter is just the variable named after the mode, and setter is the beginning of the Elisp form setting that variable to some value. (In case you think this is too much abstraction, let me tell you that my account is a bit simplified: for global modes, for instance, both setter and getter are a bit different.)

As you can see from the trick above, my initial problem has an easy answer: yes, we can supply numerical arguments in Elisp code, in fact, supplying a negative argument is the only way to turn the mode off programmatically.

Knowing this, we may now tackle the initial question. Since any positive prefix argument means “turn the mode on”, can we use its actual value to do various stuff?

The answer is (of course) yes. We may do one of two things. First of all, our mode’s body may inspect current-prefix-arg. We also have another option, which is using arg. (This is what define-minor-mode macro calls the argument to the newly defined toggling function.) The latter is obviously much less clean (especially since it depends on an implementation detail that might be changed in another Emacs version), so let’s forget about it. (Actually, instead of using the arg symbol, it would probably be better to use something like Common Lisp’s gensym. Elisp does not have such a function. The cl package has cl-gensym, but understandably built-in features do not rely on cl.)

But this is not the end of the story. There are quite a few keyword arguments of define-minor-mode not mentioned in the docstring nor in the manual, and one of them is :extra-args. (Funny sidenote: this :extra-args keyword is only mentioned three times in the whole Emacs sources. One is the definition, which (according to git blame) is last touched by Stefan Monnier on 2012-06-10. The second one is in the use-hard-newlines minor mode, last touched by Stefan Monnier on 2001-10-30. The third one is commented out in global-font-lock-mode, with a commentary saying
What was this :extra-args thingy for? --Stef
last touched on 2009-09-13, by guess who.)

Here is how you can use it. The value after the :extra-args keyword should be an (unqouted) list which is just appended to the first argument of the function turning the mode on (i.e., the one which is the prefix argument when the mode command is called interactively). All these arguments (including the first one) are optional, and you can’t supply the :extra-args on an interactive call. You can, however, supply them from Elisp code. Here is an example.

(define-minor-mode my-cool-minor-mode
  "Toggle a mode for doing cool stuff."
  :init-value nil
  :lighter " 8-)"
  :extra-args (cool-arg-1 cool-arg-2)
  (if my-cool-minor-mode
      (progn
	(cool-start)
	(message "cool-arg-1: %s, cool-arg-2: %s" cool-arg-1 cool-arg-2))
      (cool-stop)))

Try saying e.g. M-: (my-cool-minor-mode 1 "this") to see how cool-arg-1 becomes "this" and cool-arg-2 becomes nil.

The last interesting tidbit I have about define-minor-mode is the default message of My-Cool minor mode enabled in current buffer. I noticed that when I put the message function in the mode starting code, this message stopped appearing. To understand why, at first I grepped the Emacs sources for the words “enabled” (2774 hits) and “disabled” (1324 hits). Hmmm. Then, I recalled the debug-on-message variable, and it turned out that my grepping was useless anyway. Here’s the thing (simplified a bit):

(message
 "Some-mode %sabled"
 (if mode-variable "en" "dis"))

Well, that made me cringe (especially that I have to deal a bit with i18n of software), but I admit that it is sweet in a way.

What’s more interesting is that the “enabled/disabled” message is indeed turned off if the code responsible for initializing (or shutting down) the mode provides its own message. This is done with the help of the current-message function, which returns whatever is currently shown in the echo area.

All in all, I only touched the surface. It you head to the file easy-mmode.el where all this code resides, you will find quite a few niceties (like about a dozen lines of code of the function easy-mmode-pretty-mode-name devoted only to the task of converting the symbol for the mode to a human-friendly version, using the mode lighter to infer capitalization!). This is yet another example of Emacs developers paying immense attention to details, even if there are a few questionable practices along the way. ;-)

CategoryEnglish, CategoryBlog, CategoryEmacs

Comments on this page

More...