|January 21st, 2016|
When I chose a text editor, nearly fifteen years ago, I chose emacs because I liked the idea of using something that was deeply customizable. While I didn't intend to start using that customization immediately, it seemed to me like it would be much more future-proof to learn something flexible. I've never actually used this very much, but a couple weeks ago I wrote a new mode for the first time, so I thought I'd write that up.
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 "
") (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 " ") (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 "
") (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.
- Contra Dance Unplugged
- Negative News
- Parenting and Happiness
- Objecting to Situations
- Make Your Giving Public