(or emacs irrelevant)

Time flies

This is the 15th post on this blog. Thankfully, no heart attacks after the 13th one or anything. So I'll commemorate it with a post on dealing with dates in calc.

How much time has passed since I started this blog?

  1. Open calc with C-x **:

    --- Emacs Calculator Mode ---
        .
    
  2. Enter 20 Dec 2014 with '<12 20 14RET:

    --- Emacs Calculator Mode ---
    1:  <Sat Dec 20, 2014>
        .
    
  3. Enter current time with tN:

    --- Emacs Calculator Mode ---
    2:  <Sat Dec 20, 2014>
    1:  <11:56:27am Sat Jan 3, 2015>
        .
    
  4. Subtract with -:

    --- Emacs Calculator Mode ---
    1:  -14.498044
        .
    

This means that, if I want to maintain my one-post-per-day streak, I still have half of a day to post this. Unfortunately, I have only an old version of the blog repository on this machine, and the current one is on a laptop at home. So I'll post this in the evening.

Did you know what 2015 looks like in binary?

In your current calc session,

  1. Enter 2015 SPC:

    --- Emacs Calculator Mode ---
    2:  -14.498044
    1:  2015
        .
    
  2. Switch to binary with d2:

    --- Emacs Calculator Mode ---
    2:  -2#1110.011111110111111111001111110001
    1:  2#11111011111
    .
    
  3. Wow, a palindrome. It's too spooky, switch back to decimal with d0:

    --- Emacs Calculator Mode ---
    2:  -14.498044
    1:  2015
        .
    

If you're new to calc, you'll probably wonder why you can't enter negative numbers with -. It can be done with _, just like in J. Find out more in the info; the interactive tutorial is absolutely excellent.

Wrap a region with a LaTeX environment

Prompted by this StackOverflow question, I wrote down a new package called latex-wrap. It's only a few hours old, but I like it a lot. I've grepped the sources of AUCTeX, and it doesn't seem to have this functionality.

Here's how it works

You start with an active region:

Homer
Marge
Bart
Lisa
Maggie 

After calling M-x latex-wrap-region and selecting enumerate from the list of environments (others being itemize, center etc.), you get this:

\begin{enumerate}
\item Homer
\item Marge
\item Bart
\item Lisa
\item Maggie 
\end{enumerate}

Let's mark everything, M-x latex-wrap-region, and select center:

\begin{center}
  \begin{enumerate}
  \item Homer
  \item Marge
  \item Bart
  \item Lisa
  \item Maggie
  \end{enumerate} 
\end{center}

As you can see, I want to make sure that it's possible to conveniently continue by always placing the point on the end of the last line of the inserted environment.

How it works with no active region

If (looking-back "^ *") is true, the current line is used as if it was the region. Otherwise, an empty environment is inserted after the current line.

Using the code

If you like the idea, you can check out the code at github and test it out. If you know of another package that already does this, do let me know, otherwise I'll post the package on MELPA soon. And if you have some ideas, or want to add a few environments that I forgot to mention to the list, just post an issue, I don't bite.

Three ansi-term tips

Tip #1

There's no reason not to have /bin/bash instead of /bin/sh as the default choice when you M-x term.

(setq explicit-shell-file-name "/bin/bash")

Tip #2

After you close the terminal, you get a useless buffer with no process. It's probably left there for you to have a history of what you did. I find it not useful, so here's a way to kill that buffer automatically:

(defun oleh-term-exec-hook ()
  (let* ((buff (current-buffer))
         (proc (get-buffer-process buff)))
    (set-process-sentinel
     proc
     `(lambda (process event)
        (if (string= event "finished\n")
            (kill-buffer ,buff))))))

(add-hook 'term-exec-hook 'oleh-term-exec-hook)

Tip #3

By default, C-y calls term's own yank, which is different from Emacs's yank. So, until recently, I was using S-<insert> to paste stuff into *term*. Here's a more ergonomic way:

(eval-after-load "term"
  '(define-key term-raw-map (kbd "C-c C-y") 'term-paste))

The keymap arms race

Sometimes new Emacs packages have to fight for their place in the sun, as all the good bindings and huge keymap areas are already taken by the older packages. This post will cover some practical problems that you may encounter when your package needs to be aware of another active package.

ace-window vs. helm

helm is a wonderful package, it's my goto-package when I need completion. All of the following packages use it:

But helm is super-greedy: once you're in the helm-minibuffer, there's no way out except either a successful completion or a cancel. But exiting the minibuffer for a short while may be useful. For instance, you could copy some text and yank it in the helm-minibuffer. The default minibuffer functions, as well as ido easily allow it.

I started to investigate into this when I got issue #15: Does not work with helm in minibuffer for ace-window. I checked it, and indeed you could not ace-window out of a helm-minibuffer. In fact, it was not possible to exit with other-window either. This looked like good news, since I had an inkling that it used to work at some point. So I checked out a year-old version of helm and it did work.

magit-bisect to the rescue!

It's very simple:

  1. Check out the master of helm
  2. Call magit-bisect-start and mark HEAD as bad
  3. magit will automatically check out a revision that is halfway between a bad state and the initial commit. Now I exit Emacs and try helm again to see if I can exit from the minibuffer. It's kind of lame to have to exit Emacs, but somehow I don't trust unload-feature to do the right thing. Anyway, if the thing works, move to helm's repository and call magit-bisect-good, otherwise call magit-bisect-bad.
  4. Continue this process until termination. I needed 10 iterations in this case.

The culprit commit was this one:

     (let* ((source (helm-get-current-source))
            (kmap (and (listp source) ; Check if source is empty.
                       (assoc-default 'keymap source))))
-      (when kmap (setq overriding-local-map kmap)))))
+      (when kmap (set-transient-map kmap)))))

the priority of maps

In Emacs, set-transient-map has priority over overriding-local-map, which was exactly what ace-window was using. It's also funny that ace-window used to work with helm for a week, since it was published on Mar 26 and helm switched to set-transient-map on Apr 2. And I found out that it's not working only now.

Here's what helm is using currently:

(if (fboundp 'set-transient-map)
    (set-transient-map it)
  (set-temporary-overlay-map it))

So I've amended ace-window with similar code. The way set-transient-map works, the last call to it overrides the previous one, so I thought that it would work out since ace-window is always called after helm.

It didn't work out, because helm adds the code that calls set-transient-map to post-command-hook. In the end, this finally worked:

(remove-hook 'post-command-hook 'helm--maybe-update-keymap)

lispy vs. SLIME and CIDER

I thought that enabling lispy-mode for slime-repl-mode and cider-repl-mode might be a good idea. Extra navigation options are always good, and the ability to call raise is just so useful.

For instance, you start with:

; SLIME 2014-11-28
CL-USER> (expt (expt 2 10) 3)
1073741824
CL-USER>  

With lispy-mode on you can:

  1. M-p to get the previous input
  2. f to move the cursor after (expt 2 10)
  3. r to raise (expt 2 10)

Here's the final state:

; SLIME 2014-11-28
CL-USER> (expt (expt 2 10) 3)
1073741824
CL-USER> (expt 2 10) 

But the problem was that SLIME has slime-repl-map-mode minor mode on that competes for lispy's shortcuts, and CIDER has something similar as well.

When two minor modes bind the same keys, which one wins?

The answer is the first one on minor-mode-map-alist. This function I've found on the wiki:

(defun lispy-raise-minor-mode (mode)
  "Make MODE the first on `minor-mode-map-alist'."
  (let ((x (assq mode minor-mode-map-alist)))
      (when x
        (setq minor-mode-map-alist
              (cons x (delq mode minor-mode-map-alist))))))

I didn't want lispy-mode to mess with minor-mode-map-alist too actively, so I went with this approach: if lispy-mode is called interactively, i.e. via a key binding or M-x, put it ahead:

(when (and lispy-mode (called-interactively-p 'any))
    (mapc #'lispy-raise-minor-mode
          (cons 'lispy-mode lispy-known-verbs)))

It's still a work in progress, currently only lispy's RET properly yields to call cider-repl-return and slime-repl-return respectively. I'll see if there are more key bindings that need to yield. Happy coding in the New Year!

Emacs Web Wowser (EWW) got ace-link

Emacs goodness incoming

I've discovered a nice Emacs-related blog - Content AND Presentation. Unlike The Axis of Eval, the blog that I mentioned yesterday, this one is pretty self-contained, i.e. it doesn't link to many external information sources. So I thought that it's perfect for trying EWW to read it.

Not so fast! Configure first.

For modes that don't require to self-insert (and even for some that do), I like to navigate with h/j/k/l as arrows. These arrows are on the home row, so navigation becomes a pleasant and relaxed experience. But for EWW I decided to add a little twist: if the point is in the first column, j/k will move down/up not by one line, but by one paragraph. This is great for concentration: I navigate to a paragraph, read it, navigate to the next one. The point shows me the paragraph that I'm reading, everything before the point I've already read. So every time I press j, I get a tiny warm feeling of accomplishment. I can also pair this with v, which I bind to recenter the current line to the top.

So here's what my key setup currently looks like:

(defun oleh-eww-hook ()
  (define-key eww-mode-map "j" 'oww-down)
  (define-key eww-mode-map "k" 'oww-up)
  (define-key eww-mode-map "l" 'forward-char)
  (define-key eww-mode-map "L" 'eww-back-url)
  (define-key eww-mode-map "h" 'backward-char)
  (define-key eww-mode-map "v" 'recenter-top-bottom)
  (define-key eww-mode-map "V" 'eww-view-source)
  (define-key eww-mode-map "m" 'eww-follow-link)
  (define-key eww-mode-map "a" 'move-beginning-of-line)
  (define-key eww-mode-map "e" 'move-end-of-line)
  (define-key eww-mode-map "o" 'ace-link-eww)
  (define-key eww-mode-map "y" 'eww))
(add-hook 'eww-mode-hook 'oleh-eww-hook)

As you see, I was careful to re-assign eww-back-url and eww-view-source - the commands that I've displaced from l and v. And here's the implementation of the arrows:

(defun oww-down (arg)
  (interactive "p")
  (if (bolp)
      (progn
        (forward-paragraph arg)
        (forward-line 1))
    (line-move arg)))

(defun oww-up (arg)
  (interactive "p")
  (if (bolp)
      (progn
        (forward-line -1)
        (backward-paragraph arg)
        (forward-line 1))
    (line-move (- arg))))

Cherry on the top

And while I was at it, I've added ace-link support for EWW. It was pretty easy, basically the same routine as for help-mode and info-mode. The only hard part was to figure out what part of the code keeps binding shr-save-contents to o, my preferred binding for ace-link. Turns out it was eww-link-keymap, and not shr-map. So here's the new key binding code:

(defun ace-link-setup-default ()
  "Setup the defualt shortcuts."
  (eval-after-load "info"
    '(define-key Info-mode-map "o" 'ace-link-info))
  (eval-after-load "help-mode"
    '(define-key help-mode-map "o" 'ace-link-help))
  (eval-after-load "eww"
    '(progn
      (define-key eww-link-keymap "o" 'ace-link-eww)
      (define-key eww-mode-map "o" 'ace-link-eww))))

If you haven't tried ace-link before, you can get it from MELPA. The minimal configuration that you need is this:

(ace-link-setup-default)

Here's the setup that I'm actually using:

(use-package ace-link
    :load-path "~/git/ace-link"
    :init (ace-link-setup-default))

I'm using it from my git folder since when I want to edit a project, I like to use smex's jump-to-definition.

And use-package is useful for the cases when my ~/git/ happens not to contain ace-link. In that case, instead of getting a debugger error on starting Emacs, I get only a polite "Could not load package ace-link" in my *Messages* buffer.