Shortcuts in Emacs |
January 21st, 2016 |
| emacs, tech |
I keep my calendar as an html table, and every so often I go over it to move activities that have happened to the past. One could automate this completely, but I I like having an opportunity to review things and make fixes. So about five years ago I wrote a little function:
(defun move-to-past ()
(interactive)
(setq debug-on-error t)
(search-forward "<tr>")
(beginning-of-line)
(let ((mtp-killed-text
(delete-and-extract-region
(point)
(progn (forward-line 5)
(point)))))
(find-file "~/jtk/past.html")
(beginning-of-buffer)
(search-forward "<tr>")
(beginning-of-line)
(insert mtp-killed-text)))
This was easier than what I used to do: manually finding the line,
pressing ctrl+k ten times, opening past.html,
finding the right line, pressing ctrl+y. But it was still
kind of annoying: I needed to type meta-x then
move-to-p[tab][enter], and do this for each entry I was
moving. It wasn't so annoying that I couldn't stand it, but it was
irritating enough that I often put off moving things from
future.html to past.html for months at a time.
I wanted to make this easier to invoke, so that I could just press a simple keyboard shortcut and move the entry to the past. I had set shortcut keys before, like:
(global-set-key "\C-xg" 'goto-line)
This means I can type ctrl+g 53 and jump to line 53, which is
great. Except this is a global shortcut, and if I set a nice short
shortcut for move-to-past that would get in the way when I
was in other contexts. I needed to make something that only applied
to future.html, so I defined a new mode:
(define-derived-mode procsched-future-mode
html-mode
"ProcScheduleFuture")
So far, all this does is create procsched-future-mode, which
is just an alias for the mode for editing html.
Next we can define a shortcut that applies only to this mode:
(define-key procsched-future-mode-map
"\C-p" 'move-to-past)
Now if I'm in procsched-future-mode and press
ctrl+p, it will trigger move-to-past.
Manually enabling procsched-future-mode mode is annoying,
though, so I can set it to enable automatically for files named
future.html:
(add-to-list 'auto-mode-alist
'("future\\.html\\'"
.
procsched-future-mode))
Now whenever I'm in a context when I would want to press
ctrl+p for move-to-past it will just work, but
ctrl+p is still available for other uses in other contexts.
We can go a step farther, and define a few more useful things, so we
can easily delete entries or switch back from past to
future after moving something:
(defun delete-event ()
(interactive)
(setq debug-on-error t)
(search-forward "<tr>")
(beginning-of-line)
(delete-and-extract-region
(point)
(progn (forward-line 5)
(point))))
(defun switch-to-future ()
(interactive)
(setq debug-on-error t)
(switch-to-buffer "future.html"))
(define-derived-mode procsched-past-mode
html-mode
"ProcSchedulePast")
(define-key procsched-future-mode-map
"\C-o" 'delete-event)
(define-key procsched-past-mode-map
"\C-p" 'switch-to-future)
(add-to-list 'auto-mode-alist
'("past\\.html\\'"
.
procsched-past-mode))
Now I can press ctrl+p to move something to past,
then ctrl+p again to move back to future. Or I can
press ctrl+o to delete the event if it didn't actually
happen.
This has made updating future a lot easier, and I've been
doing a better job of updating it more often.
Comment via: google plus, facebook, r/emacs, substack