• Posts
  • RSS
  • ◂◂RSS
  • Contact

  • Shortcuts in Emacs

    January 21st, 2016
    emacs, tech  [html]
    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 "<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

    Recent posts on blogs I like:

    Willingness to look stupid

    People frequently1 think that I'm very stupid. I don't find this surprising, since I don't mind if other people think I'm stupid, which means that I don't adjust my behavior to avoid seeming stupid, which results in people thinking tha…

    via Posts on Dan Luu October 21, 2021

    Experiences in raising children in shared housing

    Sometimes I see posts about people’s hope to raise children in a group housing situation, and it often seems overly optimistic to me. In particular they seem to expect that there will be more shared childcare than I think should be expected. Today I talke…

    via The whole sky October 18, 2021

    EDT with updating double counts

    I recently got confused thinking about the following case: Calculator bet: I am offered the opportunity to bet on a mathematical statement X to which I initially assign 50% probability (perhaps X = 139926 is a quadratic residue modulo 314159). I have acce…

    via The sideways view October 12, 2021

    more     (via openring)


  • Posts
  • RSS
  • ◂◂RSS
  • Contact