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