Running Emacs Lisp On Several Files

Xah Lee as an instructive post on converting and scaling images with Emacs. Unlike him, I don’t often need to scale or convert even a single image, let alone many, but he does show an interesting technique to pass several files to an Elisp function. The idea is to use dired to mark the files you’re interested in and then use dired-get-marked-files to pass them to the function.

The template for performing some action on each of the marked files is

(defun process-each-file (files)
  "Perform an action on each file in list FILES."
  (interactive (list (dired-get-marked-files)))
  (mapc (lambda (f) (perform-action-on-file f)) files))

For example, if you want to perform perform-action-on-file on each JPG file you can use 【*..jpg in dired to mark all the JPG files and then call process-each-file.

The trick that makes this work is passing a list to the interactive declaration. I’ve written about that before. This is a handy technique that can often be used to advantage.

Posted in Programming | Tagged , | 8 Comments

Drawing Key Sequences In Emacs (Updated)

This is a sad story of my HTML ineptitude but one in which I eventually find the right solution. I’ve written several times (here, here, and here) about how I implemented Xah Lee’s trick of representing key sequences in a visual manner like this: 【⌘ Cmd+Tab

When I was first experimenting with the markup I used <key>...</key> tags to delimit the keys and added the appropriate bit of CSS with a key tag. That worked perfectly in my local testing but when I tried it out with the live blog it turned out that WordPress disappeared the <key> tags, presumably because it didn’t recognize them. After a bit of thinking, I came up with the <span class="key"> that I’ve been using ever since. That works well and the only complaint I have is that the markup for a complicated key sequence is pretty long and I tend to get problems when Emacs tries to split lines.

Then Aankhen asked why I wasn’t using <kbd>...</kbd> instead of the longer <span...> method. I replied that I’d originally used <key> but that WordPress eliminated them from the text. He explained to me (probably more politely than I deserved) that <key> isn’t an HTML tag but that <kbd> is. By this time I already knew that Lee used <kbd> but I had just assumed that he had made it up—just as I had made up <key>—and that it worked for him because he wasn’t using WordPress. So, I thought, I’ll just add a kbd tag to the CSS and both methods will work. Tested it locally and everything was fine. Added the kbd to the site CSS, ran a test and it didn’t work. I concluded that this was just more WordPress weirdness and gave up. Several weeks later it popped into my head that the reason it hadn’t worked was that my browser hadn’t reloaded the site’s style sheet when I changed it. Fortunately, I had left the change in so when I retried it, everything worked as expected.

I like the shorter <kbd> tags because they avoid the overly long markup sequences that were causing me a slight irritation. All that was left to do was to change prettify-key-sequence to use the new method. Here, for the record, is the new code

(defmacro key (k)
  "Convenience macro to generate a key sequence map entry
for \\[prettify-key-sequence]."
  `'(,k . ,(concat "@<kbd>" k "@</kbd>")))

(defun prettify-key-sequence (&optional omit-brackets)
  "Markup a key sequence for pretty display in HTML.
If OMIT-BRACKETS is non-null then don't include the key sequence brackets."
  (interactive "P")
  (let* ((seq (region-or-thing 'symbol))
         (key-seq (elt seq 0))
         (beg (elt seq 1))
         (end (elt seq 2))
         (key-seq-map (list (key "Ctrl") (key "Meta") (key "Shift") (key "Tab")
                            (key "Alt") (key "Esc") (key "Backspace")
                            (key "Enter") (key "Return") (key "Space")
                            (key "Delete") (key "F10") (key "F11")
                            (key "F12") (key "F2") (key "F3")
                            (key "F4") (key "F5") (key "F6") (key "F7")
                            (key "F8") (key "F9")
                            ;; Disambiguate F1
                            '("\\`F1" . "@<kbd>F1@</kbd>")
                            '("\\([^>]\\)F1" .
                              "\\1@<kbd>F1@</kbd>")
                            ;; Symbol on key
                            '("Opt" . "@<kbd>⌥ Opt@</kbd>")
                            '("Cmd" . "@<kbd>⌘ Cmd@</kbd>")
                            ;; Combining rules
                            '("\+\\(.\\) \\(.\\)\\'" .
                              "+@<kbd>\\1@</kbd> @<kbd>\\2@</kbd>")
                            '("\+\\(.\\) \\(.\\) " .
                              "+@<kbd>\\1@</kbd> @<kbd>\\2@</kbd> ")
                            '("\+\\(.\\) " .
                              "+@<kbd>\\1@</kbd> ")
                            '("\+\\(.\\)\\'" .
                              "+@<kbd>\\1@</kbd>"))))
    (mapc (lambda (m) (setq key-seq (replace-regexp-in-string
                                     (car m) (cdr m) key-seq t)))
          key-seq-map)
    ;; Single key
    (if (= (length key-seq) 1)
        (setq key-seq (concat "@<kbd>" key-seq "@</kbd>")))
    (delete-region beg end)
    (if omit-brackets
        (insert key-seq)
      (insert (concat "【" key-seq "】")))))
Posted in General | Tagged , | 1 Comment

Specifying Any Modifier Key In Emacs

A couple of weeks ago, I wrote about a Xah Lee post that, among other things, mentioned how to set the hyper and super keys for use with Emacs. Lee uses them a lot because he has a bunch of private functions that he wants to bind to key sequences and most of the convenient sequences that don’t involve hyper or super are already used. I don’t have that problem because I don’t have as many private functions and because, not being as fanatical about efficiency as Lee, I’m content to let smex find the private functions that I do use.

Nonetheless, it is sometimes useful to have a hyper or super key even if you haven’t dedicated some spare keys on your keyboard to them. It turns out that there is a way of causing a keystroke to be modified by the hyper or super key: just type 【Ctrl+x @ h】 and the next key will be modified by “hyper”. Similarly, typing 【Ctrl+x @ s】 will cause the next key to be modified by “super”. If you wanted to modify by both hyper and super you can type 【Ctrl+x @ h Ctrl+x @ s】.

Actually, the same trick works for any of the modifier keys. You can get a complete list by typing 【Ctrl+x @ Ctrl+h】 but here is a quick summary.

Summary

Key Sequence Modifier
Ctrl+x @ S Shift
Ctrl+x @ a Alt
Ctrl+x @ c Control
Ctrl+x @ h Hyper
Ctrl+x @ m Meta
Ctrl+x @ s Super
Posted in General | Tagged | Leave a comment

A History Of Unix

Warren Toomey has a great article on The Strange Birth and Long Life of Unix in the IEEE Sprectrum. Toomey runs the Unix Heritage Society that maintains a mailing list for those interested in Unix history and, most importantly, maintains a collection of all the publicly available Unix source code.

The outline of the story is well known. When AT&T withdrew from the Multics project, Ken Thompson, Dennis Ritchie, and some of the other Bell Labs researchers were left without the convenient, interactive, time sharing system that Multics had provided and set about to create their own. What is new to me is how much of a skunk works project this was. AT&T management felt that they had been burned with Multics and were dead set against any further OS research. Thompson experimented with some of his file system and OS ideas on the GE-645 that they’d used for their Multics work but realized that the 645 would soon go away so he abandoned his work. Then, of course, he found that storied PDP-7, ported his Space Travel game to it and opened the door to what would eventually result in Unix.

Toomey relates how early Unix was in many ways like the open source movement today. AT&T couldn’t sell Unix and their lawyers were afraid that offering any support could be interpreted as violating their consent decree so fixing bugs was up to the users. Eventually those were contributed back to AT&T and incorporated into new editions. Thompson apparently even smuggled bug fixes to the users through Usenix.

Toomey tells a great story of the early days of Unix and if, like me, you’re a Unix aficionado, you’ll want to give it a read. If you’re an open source enthusiast, you’ll want to read it to see how hard people had to work to share code and knowledge in the early days. All in all, a great read for anyone interested in computers.

Posted in General | Tagged | Leave a comment

emacs follow-mode

Xah Lee has a nice post on follow-mode. He describes how to take a wide frame, break it up into two or more horizontal windows, and then have the windows act as one large window into the buffer. That is, the end of the first window flows into the start of the second and so on. If you move the cursor off the end of a window it will move to the next window.

This isn’t something I want to do too often but it can sometimes be useful. I’ve seen people asking how to do this several times so Lee’s post is a valuable one. Fortunately, it’s easy to set up and once you do it, you will almost certainly remember how to do it in the future.

Posted in General | Tagged | 1 Comment

Publishers And DRM

Last week I wrote one of my semi-regular rants about the publishing industry and their bad choices. Yesterday, Charlie Stross, a prominent SF author (Accelerando, Glass House, Halting State, Rule 34, and others) wrote a provocative piece on publishers and DRM. Stross’s thesis is that the biggest threat to publishers is not piracy but Amazon.com.

Amazon, says Stross, has already captured about 80% of the ebook retail market. That didn’t matter a short time ago when ebook sales amounted to about 1% of the publishing market but now ebooks account for somewhere between 20% and 40% of the market and we can, of course, expect that figure to continue growing rapidly. Meanwhile, Amazon is ruthless in the pressure it exerts on publishers for favorable pricing and discounts. This means that they can sell ebooks at very competitive prices and therefore strengthen their near monopoly while at the same time earning more money.

What’s this have to do with DRM? We all know the usual arguments against DRM:

  • It doesn’t stop piracy (at all).
  • It punishes and inconveniences honest buyers.
  • It tells the publishers’ customers that the publishers consider them criminals.
  • It can cause legitimately purchased material to become unavailable when resellers go out of business and abandon their authorization servers.
  • And on and on and on.

Now Stross has another argument against it. By insisting on DRM the publishers help Amazon lock in customers to the Kindle platform and therefore reinforce Amazon’s monopoly. This in turn gives Amazon the ability to demand more concessions from the publishers until they are forced out of business.

If publishers were smart, they’d get rid of DRM and maybe even offer customers who can demonstrate that they own an ebook with DRM an unencrypted copy of the book. That would, at one blow, eliminate Amazon’s lock in and perhaps—perhaps—help break Amazon’s strangle hold on the ebook market. Sadly, of course, the publishers aren’t smart and will doubtless continue to insist on DRM until it’s too late.

Actually, Stross says that many of the publishers do recognize this but that they are all now part of large media conglomerates with many levels of authority above them who most certainly do not understand publishing and its realities. That’s too bad because everyone—except maybe Amazon—is going to suffer from this shortsightedness. Customers will suffer from the inconvenience and lock in that DRM causes, and the publishers will suffer eventual extinction brought on by their continued bad choices.

Posted in General | Leave a comment

Emacs Markers

In a comment to my Emacs comment-box Revisited post, Aaron showed me a nice way to deal with the boundaries of expanding regions. Recall that in that post I wanted to pad the first line of a comment out to the fill column so that comment-box would draw the box across the whole width (more or less) of the window. The problem was that adding those blanks increased the size of the region so the character number of the end of the region was no longer correct. In my code that was easily fixed because I could use (point-max) to locate the end of the region since I had narrowed the buffer to the region.

Aaron’s way of handling this is nice because it feels less ad hoc and because it works for any position in the buffer not just the beginning or end. The idea is to use a marker to point at the end of the region. Conceptually, a marker is just like a position (that is a character index into the buffer) but it has the nice property that if you change the size of the buffer, the marker is adjusted when necessary. It’s as if you planted a flag at the position and the flag moves as the buffer expands or contracts.

Here’s what the revised code looks like

(defun jcs-comment-box (b e)
  "Draw a box comment around the region but arrange for the region
to extend to at least the fill column. Place the point after the
comment box."
  (interactive "r")
  (let ((e (copy-marker e t)))
    (goto-char b)
    (end-of-line)
    (insert-char ?  (- fill-column (current-column)))
    (comment-box b e 1)
    (goto-char e)
    (set-marker e nil)))

As you can see, I’ve replaced the with-region-or-buffer macro with the more sensible (interactive "r"). The copy-marker function will make a copy of an existing marker or if its first argument is a position it will make a marker with that offset. The (optional) second argument says that if text is added at the marker then move the marker ahead. A nil would say the leave the marker where it is. The (set-marker e nil) at the end of the function makes the marker point nowhere. It’s not strictly necessary but it lets Emacs stop worrying about keeping it updated as you further edit the buffer. As you can see, you can treat the marker just you would a position: you can use it as a position, move to it, and even do arithmetic on it.

Chapter 31 of the Emacs Lisp Manual explains markers further. It’s short and interesting so it’s worth a read if you like programming in Emacs Lisp.

Posted in Programming | Tagged | Leave a comment

Emacs Align Functions

Tim Visher has a new VimGolf in Emacs up. This time it’s a simple alignment problem using align-regexp, a function that we’ve talked about before. In this case he just used the simple align-regexp case and was done in about 6 keystrokes, much less than the 18 that the best Vim solution took.

It turns out the the align function, of which align-regexp is a special case, is very flexible. It will try to align the region or current group of text in a context dependent way. The action of align is specified by a set of rules that specify context (such as major mode), a regular expression, and some other attributes. The list of rules is in the variable align-rules-list. The documentation for that variable explains the various options and gives its current value. You can also pass in your own list of rules. The align-regexp function basically just prompts you for an ad hoc rule.

Unfortunately, the documentation isn’t very good and the rules can be quite complex. Visher mentions this page from the EmacsWiki that gives some examples but it is by no means a complete explanation. This is a very powerful function and I wish the documentation on it was better. Unfortunately it isn’t even mentioned in the Emacs manual.

Posted in General | Tagged | 1 Comment

Emacs comment-box Revisited

Last week I wrote about Comment Boxes In Emacs and gave some examples of how the comment-box command provides an easy way to draw a box around a comment. The only problem is that I want the boxes to extend almost to the right hand margin. Instead of

##########################################
# get-cred -- Get the user's credentials #
##########################################
(defun get-cred ()
...)

I want

##########################################################################
# get-cred -- Get the user's credentials                                 #
##########################################################################
(defun get-cred ()
...)

One could argue, I suppose, that this adds nothing except some useless blanks to the file but I’ve always done it that way and as Henry Higgins might say, “I’ve grown accustomed to its face.” So, how to do it?

My idea was simple: pad the first line with blanks out to the fill column, and then call comment-box to draw the actual box. There’s nothing special about using the fill column as the right hand edge but it makes the function behave well for any size window.

I thought I’d knock off a quick bit of Elisp and be done. It didn’t work out that way. I kept getting a mysterious error that appeared to come from save-restriction (see the code below). After that lot of mucking about I discovered that the real problem was the call to comment-box. The documentation says that there’s an optional third argument to add extra space and, indeed, the beginning of the function is

(defun comment-box (beg end &optional arg)
...)

so I didn’t bother specifying the third argument. It turns out, though, that in the comment-box function we have this line

(comment-region beg end (+ comment-add arg))

so that the optional argument is always used. It works OK in the interactive case because the call to interactive is

(interactive "*r\np")

which causes the prefix argument to be passed to arg. When no prefix argument is specified, this results in a 1 being passed to arg so arg is never nil the way it is if you call comment-box from Elisp with only two arguments. That’s obviously a bug but it’s a small one. At least it’s a small one once you figure out what’s happening.

In any event, once I solved that problem it was easy to write the function:

(defun jcs-comment-box ()
  "Draw a box comment around the region but arrange for the region
to extend to at least the fill column. Place the point after the
comment box."
  (interactive)
  (with-region-or-buffer (b e)
    (save-restriction
      (narrow-to-region b e)
      (goto-char b)
      (end-of-line)
      (insert-char ?  (- fill-column (current-column)))
      (comment-box b (point-max) 1)
      (goto-char (point-max)))))

As you can see, we first move to the beginning of the first line, then to its end, and then we pad the line with blanks out to fill-column. A few comments on the rest of the code:

  • It would probably be easier to use
    (interactive "r")
    

    rather than the with-region-or-buffer macro but I write that almost automatically when I’m dealing with a possible region so I just kept it.

  • insert-char does nothing if the count is not positive so I didn’t have to worry about whether or not the first line already extended to or past the fill column.
  • Using the narrow-to-region function makes it really easy to move around the buffer and helps deal with the fact that I’m changing the size of the region as I go. This problem was described by Xah Lee.
  • Notice that even the narrow-to-region doesn’t completely insulate me from the effects of changing the buffer size. I have to use (point-max) as the end of the region (instead of b) in the call to comment-box because b no longer points to the end of the region.
Posted in Programming | Tagged | 2 Comments

Xah Lee On Inserting Brackets In Emacs

Xah Lee has an interesting post on inserting bracket pairs in Emacs. This is exactly the same thing that I did using Key Chord Mode as I described in this post. The difference is that Lee uses Elisp code directly and has a function for every imaginable pair of brackets. If you use a lot of brackets in your HTML, as he does, it’s worth while grabbing his code.

For guys like me who use mainly parentheses, square brackets, and the occasional pair of braces, the Key Chord Mode solution works well and is easier to implement. The only pairs I have implemented are the angle brackets for HTML tags and double quotes. I’d definitely do parentheses too except that the Paredit minor mode takes care of that for me.

Lee has 22 little functions to insert these pairs so you might wonder where he finds enough key sequences to bind to them. The answer is the hyper key. None of the standard Emacs functions use the hyper key (or at least don’t use it exclusively) so it’s an ideal modifier to use with private functions. The question for most people is: what key is the hyper key?

That depends on what type of system you’re using. Windows, OS X, and Linux can all be configured with a hyper key but the key and the configuration steps differ. Fortunately, Lee’s post has a section that shows you how to configure it for all three system types. To my mind, that section is probably the most valuable part of his post. If you’d like an extra modifier key, be sure to check it out. He also has a separate page on how to set up the hyper and super keys.

Posted in General | Tagged | Leave a comment