help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Lisp refactoring puzzle


From: PJ Weisberg
Subject: Re: Lisp refactoring puzzle
Date: Thu, 29 Mar 2012 18:51:14 -0700

On Tue, Jul 5, 2011 at 11:54 AM, Sean McAfee <eefacm@gmail.com> wrote:
> I use EMMS (Emacs Multi Media System) a lot, and I have the following
> key mappings set up to easily skip around inside large MP3s:
>
> (global-set-key [(super left)]
>                (lambda () (interactive) (emms-seek -7)))
> (global-set-key [(super meta left)]
>                (lambda () (interactive) (emms-seek -60)))
> (global-set-key [(super meta control left)]
>                (lambda () (interactive) (emms-seek -360)))
>
> ...and likewise for the right arrow key, with positive arguments to
> emms-seek.
>
> These mappings are of course repetitive, and so a while back I wrote
> some code to set them up.  As I became more familiar with the loop
> macro, I refined the code several times, until I got what I have today:
>
> (defconst skip-intervals '((7 . super) (60 . meta) (360 . control)))
>
> (loop for (magnitude . modifier) in skip-intervals
>      collecting modifier into modifiers
>      do (loop for key in '(right left)
>               and delta = magnitude then (- magnitude)
>               do (global-set-key
>                    (vector (append modifiers (list key)))
>                    `(lambda () (interactive) (emms-seek ,delta)))))
>
> This is fairly elegant, but I'm disappointed that it doesn't really save
> me any lines of code over just writing out the mappings by hand.
>
> Can anyone suggest a more compact/elegant way to establish these
> mappings?

You're trying to outsmart yourself.  Refactoring isn't about trying to
fit all your logic into as few bytes of code as possible.  Your first
set of three calls to `global-set-key' make it obvious exactly what
the code is doing.  I had to stare at that loop for a minute before I
realized what the "collecting" part was trying to accomplish.

On the other hand, my brain won't ever let me leave a "how do you do
X?" question alone, so I went ahead anyway and wrote what I think is a
clearer way of doing what you're doing above.

(let ((skip-intervals '((7 . "s") (60 . "s-M") (360 . "s-M-C")))
      (directions '(("left" . -1) ("right" . 1))))

  (loop for (magnitude . modifier) in skip-intervals do
        (loop for (direction . sign) in directions do
              (global-set-key (read-kbd-macro (format "%s-<%s>"
modifier direction))
                              (lambda () (interactive) (emms-seek (*
sign magnitude)))))))


-PJ

Gehm's Corollary to Clark's Law: Any technology distinguishable from
magic is insufficiently advanced.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]