Byte-compiled ChangeLog


My favourite all-purpose, extensible and customizable editor is Emacs. Mastering Emacs takes months, even years, and there is always a lot to discover. For example, I've just seen how Emacs tried to byte-compile a simple ChangeLog text document. Of course Emacs did what I asked to do it according to the rules defined in my .emacs.el.
So...

My dot emacs file is divided into .el pieces like this:

1
2
3
4
5
(load "~/.emacs/conf/env_internal.el")
(load "~/.emacs/conf/env_external.el")
(load "~/.emacs/conf/ui.el")
...
...

It's much easier to deal with functions grouped in different files rather than functions in one big .emacs.el.

This "trick" automatically byte-compiles .el files as they're saved:

1
2
3
4
5
6
7
(defun autocompile nil
  (interactive)
  (require 'bytecomp)
  (if (numberp (string-match ".el" buffer-file-name))
		(byte-compile-file (buffer-file-name))))

(add-hook 'after-save-hook 'autocompile)

It worked perfect for me, until once I was updating a single text-only ChangeLog file via Emacs. When I saved it, Emacs tried to byte-compile the file! That was weird.

The error should have not been in Emacs (that's true for 99.9% Emacs-related "bugs"), but somewhere in one of my configuration .el files. And probably there was something wrong with the byte-compile-on-save hook. The only function that could cause it was:

1
(if (numberp (string-match ".el" buffer-file-name))
string-match is a built-in function in `C source code'.
(string-match regexp string & optional start)

Returns the index of start of the first match for regexp in string, or nil.
Aha! string-match works with regexps! And I have the "." symbol in the pattern. But period is a special character in regexps:
`.' (Period)
is a special character that matches any single character except a
newline. Using concatenation, we can make regular expressions
like `a.b', which matches any three-character string that begins
with `a' and ends with `b'.

So, (string-match ".el" buffer-file-name) function call is wrong! For example:

1
(string-match ".el" "ChangeLog")
returns 4.

I had to use a backslash to quote that period, like this:

1
(string-match "\.el" "ChangeLog")

But somehow, that didn't work either. An additional documentation exploration has shown that

When you use regular expressions in a Lisp program, each `\' must be doubled


Finally, I wrote:

1
(string-match "\\.el" "ChangeLog")

And it worked! The result was nil. And the result for any file with .el extension was the start position of the ".el" string in file's name.

Here is the final version for automatic byte-compile when saving a file with .el extension:

1
2
3
4
5
6
7
8
(defun autocompile nil
  "compile itself if contains .el"
  (interactive)
  (require 'bytecomp)
  (if (numberp (string-match "\\.el" buffer-file-name))
		(byte-compile-file (buffer-file-name))))

(add-hook 'after-save-hook 'autocompile)

That was a funny problem and it took me about half an hour to deal with.
Emacs help helps :)

Leave a comment

Introduce yourself:
Comment: BB-codes
Captcha:
captcha