DoReMi

These are some libraries that use or define Do Re Mi functions:

Topics discussed here:

See Also:

Direct Manipulation for Emacs

Are you old enough to remember coming across a keyboard with repeating keys for the first time – where you could hold down a key and have it repeat? Of course not! We’re talking electric, as opposed to manual, typewriters here. Well, I’ve been there. Magic it was. Let’s just say that “the repeating key” is the muse for this page.

In user-interface design, direct manipulation is a good thing. It means you can grab something and manipulate it directly, without going through a bunch of commands, menus, dialog boxes, and so on. Things like handles on graphic objects that let you move, turn, scale, twist and reshape the objects provide interaction that is more immediate – less mediated by interface junk.

I (DrewAdams) have written library doremi.el, which is a start in the direction of more direct manipulation for some of the things we do in Emacs. More specifically, it provides a command, ‘doremi’, that you can use to define other commands that let you use the arrow keys (or other keys) and/or the mouse wheel to make incremental changes to things. Howzat? By the old “repeating key” trick, Grasshopper…

Need: Easily Access Ordered Values

You want to change the background color of your frames, so you find some way to display the various color choices, then you choose a color that you like, and use it in Emacs. When choosing, if you need to do the displaying in Emacs itself, then you have to change the frame background color, then change it again, etc. until you find one you like. Likewise, for other changes like font size or face choice.

You could of course write some Emacs-Lisp code that displays a complete palette – as in ‘list-faces-display’ – and perhaps add some code that lets you choose an item from the palette. ColorPalette is an example of this. This palette/dialog-box/menu approach is in common use. Do Re Mi, however, sets out in a different direction (but could usefully be combined with such an approach in some cases).

There are lots of such adjustments that you might want to make, to customize things. There are other adjustments that you might want to make more regularly, such as resizing frames or zooming font size. And then there are choices that you want to make, without adjusting (changing) anything. Think of dials and sliders and such.

Think how easy it is to “zoom” a Web page to change the font size in Web browsers. In IE, for instance, you just hold Control while moving the mouse wheel to change the font size incrementally. Wouldn’t it be handy to be able to do that in Emacs? As another example, you can press and hold a mouse button on a scroll-bar arrow to move up or down a Web page. Why not press and hold a mouse button on an Emacs menu or toolbar button to dynamically adjust something?

All of these example “requirements” fall into the same category of dealing with a set of ordered values – choosing from the set or moving from one set element to another. When you zoom a font size with a mouse wheel, you’re just incrementally modifying the size. When you choose a color from a spectrum or palette, one way to do that is to incrementally modify the color from the current color, until you get what you want.

Solution: Do Re Mi (Fa So La Ti Do ...)

The ‘doremi’ command is just a start. The main aim is to suggest the kind of thing that can be done. This command lets you use the arrow keys and/or the mouse wheel to run up and down the scales, performing incremental adjustments of just about anything. You can press and hold arrow keys or rotate the mouse wheel to dynamically adjust any property. (Other keys can be substituted for the arrow keys.) Input mechanisms could easily be expanded to, say, allow incremental change by holding a mouse button pressed on a menu item or tool-bar button.

To test the idea out, and also to provide a few useful commands, I wrote libraries doremi-frm.el, doremi-cmd.el, and thumb-frm.el, which provide commands that use the arrow keys and mouse wheel to change things incrementally or cycle through enumerations.

For example, these are some of the commands defined in doremi-frm.el and doremi-cmd.el :

You can also access these commands from the Text Properties menu. See FaceMenuPlus and facemenu+.el.
See also Icicles, commands ‘icicle-frame-bg’ and ‘icicle-frame-fg’, for similar commands, but which also support Completion, including regexp matching.
You can also access these commands from the Text Properties menu. In the case of the popup mouse menu, you can just point the mouse to text with a given face, to change that face (foreground or background) incrementally – no need to know the face name beforehand. See FaceMenuPlus and facemenu+.el.

doremi-frm.el also has some commands that don’t cycle:

When I say “choosing from a list”, above, that doesn’t sound very hot, does it? The important thing to keep in mind is that you see what you get while you’re choosing: the property value is applied as you choose. All you have to do is stop pressing the arrow key or stop turning the mouse wheel. Choosing and applying are the same act.

(La petite histoire -- In case you’re interested, here’s how the idea of Do Re Mi came to me. I had ‘C-M-’ up, down, left, and right arrow keys assigned to commands ‘shrink-frame’, ‘enlarge-frame’, ‘shrink-frame-horizontally’, and ‘enlarge-frame-horizontally’ from library frame-cmds.el. But then I saw a use for another command that could also be usefully bound to an arrow key to take advantage of press-and-hold for incremental change of some kind. And another. My key combinations with the arrow keys being limited, it occurred to me that I needed a KeySequence (Command) that would put me in a mode where the arrow keys would be temporarily bound to some (repeatable) action. Voila.)

How It Works

Do Re Mi generally works with numerical properties that can be incremented and decremented, and it works with properties that can take on one of a number of values. In fact, it is even more general than that: you can use it to associate nearly any function or pair of functions with the arrow keys and the mouse wheel.

Example properties include frame background color and font size. A property can be anything that is adjustable in any of these ways:

The arguments of ‘doremi’ are described next. This description is a bit hard to follow, but, below, there are simple examples of using ‘doremi’.

To define a command that uses the arrow keys and/or mouse wheel repeatedly to adjust or choose a value from an ordered set, you supply function ‘doremi’ with the following arguments:

    1. absolute – It takes a value as argument and sets some property to this value.
    2. relative – It is a “growth” function, which takes an increment as argument and incrementally adjusts the value of some property.
Note:
“Growth” function really means, here, that the function takes an increment as argument and does the incrementation (or whatever) itself. It is contrasted with an absolute ‘setter-fn’ that just uses a value that is incremented by ‘doremi’. The difference is which function does the incrementing, ‘setter-fn’ or ‘doremi’.
In case #1, the new property value must be returned by ‘setter-fn’, because it is used as the initial value for the next iteration. In case #2, the new property value should be returned by ‘setter-fn’, so that it can be echoed to the user.

For numerical properties (not enumerated choices), there are actually two levels of increment. For faster incrementation, you can use ‘doremi-boost-up-key’ and ‘doremi-boost-down-key’ (by default, these are ‘M-up’ and ‘M-down’). The incrementation is ‘doremi-boost-scale-factor’ times faster than for the unmodified arrow keys (actually, the key values of ‘doremi-up-key’ and ‘doremi-down-key’).

Note:
You are already used to traversing a sequence of items and choosing one of them, if you use MiniBuffer histories (‘M-n’, ‘M-p’). Minibuffer histories are generally not cyclic, however: when you get to the end, continuing doesn’t bring you back to the beginning. Icicles provides cyclic selection, using the arrow keys, of values that are displayed in the minibuffer (in addition to standard minibuffer histories via (‘M-n’ and ‘M-p’). For instance, it lets you cycle among the current set of buffers. This behavior is somewhat akin to the cycling in Do Re Mi, but only the single choice made is applied, whereas in Do Re Mi each choice is applied, in order. – See Icicles.

Got all that? A few Examples might help…;)

Examples

The examples here are in three sections, corresponding to the kinds of setter functions:

Incrementing/Decrementing Values Using Absolute Setter Functions

Here you go:

  (defun doremi-frame-height+ (&optional increment frame)
    "Change height of current frame incrementally."
    (interactive "p")
    (doremi (lambda (new-val) (set-frame-height frame new-val) new-val)
             (frame-height frame)
             (- increment)))  ; Reverse increment, so arrows correspond.

The ‘setter-fn’ argument sets a value, in this case, the frame height. It takes as argument the new value to set, and it also returns this value (so it can be used for the next round of iteration, if you continue to hold the arrow key or turn the mouse wheel).

The ‘init-val’ argument is the current frame height, (frame-height frame).

The sign of the ‘incr’ argument is reversed in this case, so that the up arrow (which by default “increases”) makes the frame bottom go up (making the frame shorter).

Piece of cake, no?

What would we have to change, to create a command that moves a frame left and right, instead of changing its height? The ‘setter-fn’ would be a function that sets the left frame-position parameter; it would still take the new value (a different kind of value) as argument and return this value. The ‘init-val’ would be the initial (current) frame position (left).

  (defun doremi-frame-horizontally+ (&optional increment frame)
    "Move current frame left/right incrementally."
    (interactive "P")
    (unless increment (setq increment (or increment 10))) ; 1 pixel is too small
    (setq frame (or frame (selected-frame)))
    ;; If frame left is off screen, start at screen edge (left = 0).
    (when (consp (frame-parameter frame 'left))
      (modify-frame-parameters frame '((left . 0))))
    (let ((doremi-up-key 'left)           ; Rebind, so keys are more intuitive for width.
          (doremi-boost-up-key 'M-left)
          (doremi-down-key 'right)
          (doremi-boost-down-key 'M-right))
      (doremi (lambda (new-val) (modify-frame-parameters frame (list (cons 'left new-val)))
                new-val)
              (frame-parameter frame 'left)
              (- increment)))             ; Reverse, so arrows correspond.
    (when (member (car unread-command-events)
                  (list doremi-up-key doremi-down-key
                        doremi-boost-up-key doremi-boost-down-key))
      (doremi-frame-vertically+ increment frame)))

Again, the increment is flipped here to make things more intuitive (left arrow moves the frame to the left).

Note:

  1. Ignore the last part of this definition for now: (when (member...) (doremi-frame-vertically+...))). What it does is let you use all four arrow keys to move the frame in any direction – see AllFourArrows.
  2. Dealing properly with frame position is a bit complicated here, because if the position is off the display then the ‘top’ and ‘left’ values are not integers, but lists. This example command just repositions the frame at the screen edge if it is initially off-screen. The actual doremi-frm.el commands `doremi-frame-horizontally+’ and `doremi-frame-vertically+’) are more complex and adjust for this. They wrap movement around the display borders: if a frame is moved off the display at the right, continuing to move it to the right brings it back onto the display at the left, and so on. To do this, they are not simple absolute setter functions that let ‘doremi’ increment simply; they are incremental growth functions (see IncrementorFunctions) that know how to increment a value such as (left + -300).

Incrementing/Decrementing Values Using Growth Functions

In IncrementingNumericalProperty, above, we used a setter function that set a value absolutely. Here, we use a relative setter function, which changes something (once) by applying an increment. Sometimes it’s easier to write (or reuse) such a function than trying to define a setter function that works absolutely.

Here’s another version of a frame-height adjuster:

  (defun doremi-frame-height-bis (&optional increment frame)
    "Change frame height incrementally."
    (interactive "p")
    (doremi (lambda (inc) (enlarge-frame inc frame) (frame-height frame))
             (frame-height frame)
             (- increment)
             t))   ; Non-nil means the setter-fn is a relative-growth function.

This assumes that you already have a function, enlarge-frame, that takes an increment and applies it to a frame, making its height incrementally bigger or smaller (once). In this case, all ‘doremi’ is doing is letting you reapply the growth function repeatedly.

Here’s a suitable enlarge-frame function, good for a one-shot growth (or shrink) change (this is from library frame-cmds.el):

  (defun enlarge-frame (&optional increment frame)
    (interactive "p")
    (set-frame-height frame (+ (frame-height frame) increment)))

In this case, there is no special reason to choose absolute or relative value setting – either will do fine. However, suppose you wanted to increase the font size? The font size is not recorded as a numerical quantity; it is a string value, recorded as part of the font name. In this case, ‘doremi’ cannot just increment the value numerically. So, a custom incremental growth function is called for – see library frame-cmds.el for command ‘enlarge-font’. (For the same reason, non-numerical ‘top’ and ‘left’ frame positions could be usefully dealt with using a relative value-setting version of ‘move-frame-horizontally’.)

I don’t include all the code here, but `doremi-bg+’ is another command that uses a growth function (‘doremi-increment-background-color’). It lets you progressively adjust the background color of a frame by incrementing its RGB (red ‘r’, green ‘g’, blue ‘b’) or HSV components (hue ‘h’, saturation ‘s’, value ‘v’. (Saturation is the “purity” of a color; value is its brightness.) There are also commands for adjusting each of these components separately. All of these commands are in library doremi-frm.el.

Note: CMY (cyan, magenta, yellow) is just the opposite of RGB – incrementing one decrements the other, and vice versa. For example, to increment yellow, just decrement blue.

Here is the core definition of command `doremi-bg+’:

  (defun doremi-bg+ (component &optional increment)
    "Change frame background color incrementally."
    (interactive "cAdjust red, green, blue, hue, saturation, or value? [rgbhsv]: \nP")
    (setq increment (if increment (prefix-numeric-value increment) 1))
    (doremi (lambda (inc) (doremi-increment-background-color component inc)
              (cdr (assq 'background-color (frame-parameters))))
            (cdr (assq 'background-color (frame-parameters)))
            increment
            t)
    (let ((next-component (pop unread-command-events)))
      (frame-update-face-colors (selected-frame)) ; update the way faces display
      (when (member next-component '(?r ?g ?b ?h ?s ?v))
        (doremi-bg+ next-component increment))))

The last part of this definition, (when (member…) (doremi-bg+…))), just lets you switch to a different color component (‘r’, ‘g’, ‘b’, ‘h’, ‘s’, ‘v’) on the fly, so you can change them all without having to call `doremi-bg+’ repeatedly. See AllFourArrows for an analogous treatment for moving frames using all four arrow keys.

Recall that the only difference between an incremental growth function and an absolute setter function is that the former does the incrementation itself, whereas the latter depends on ‘doremi’ to do the incrementation. Generally, absolute setter functions are simpler. You use incremental growth functions when one of the following is true:

In some cases, an incrementor function that you would like to use might not simply accept positive and negative increments, or you might anyway want to use two different incrementor functions: one for the up arrow and one for the down arrow. You do this by providing the second incrementor function as the ‘growth-fn’ argument. (To use only one incrementor function, you set argument ‘growth-fn’ to a non-nil, non-function value, such as ‘t’.)

In fact, you can use “incrementor” functions to do anything you like – they need not actually increment anything at all. They could provide “next” and “previous” values without working from an enumeration list or a numerical sequence. Such “successor” and “predecessor” functions could be as wild as a random value generator, or they could choose values in some unnaturally intelligent way! ;) You could use ‘call-last-kbd-macro’ as an “incrementor” function, using the arrow keys and mouse wheel to execute it repeatedly. Use your imagination…

Running Up and Down the Scale with Enumerations

The final category of property treated by ‘doremi’ consists of properties that can take on one of several values – an enumerated choice. That is, the values are not numerical (though they could be indexed and treated as numerical), but they belong to a sequence – an ordered set.

It’s convenient to make the sequence circular, so that when you fall off one end you climb right back onto the other end. This structure is called a ring in Emacs. Both library doremi.el and library doremi-frm.el use the ring-enhancement library ring+.el (see RingPlus).

Library ring+.el provides additional functionality to that in standard library ring.el, including function ‘convert-to-sequence’. That function lets Do Re Mi work with any Emacs-Lisp sequence structure (list, array, string, vector), by first converting it to a ring. Function `ring-insert+extend’ in ring+.el is used by Do Re Mi to let you insert new items in a ring without losing old ones – it is the basis of ‘doremi’ argument ‘allow-new-p’.

Here’s a simplified version of a command from doremi-cmd.el that cycles color themes. The ‘enum’ argument is a list, `doremi-color-themes+’, of commands that change the current color theme. The ‘init-val’ argument is one of the commands in the list. The setter function just calls one of these commands. That’s all there is to it. (See ColorTheme for more about color themes.)

  (defun doremi-color-themes+ ()
    "Successively cycle among color themes."
    (interactive)
    (doremi (lambda (newval) (funcall newval) newval) ; call a theme command
            (car (last my-color-themes))              ; start with last theme
            nil                                       ; ignored    
            nil                                       ; ignored
            doremi-color-themes))                     ; themes to cycle through

Here’s a command to cycle through a list of background colors, until you get the color you want. (You can then set this value as a customization option if you want to save it.) In this case, a list of all the available colors is the ‘enum’ argument: (x-defined-colors). The starting point is the current background color. The setter function just sets the background color (once).

  (defun doremi-bg-color-name+ ()
    "Successively cycle among background colors, choosing by name."
    (interactive)
    (let ((fr (selected-frame)))
      (doremi (lambda (newval) (set-background-color newval) newval)
              (frame-parameter fr 'background-color)
              nil                    ; ignored
              nil                    ; ignored
              (x-defined-colors)
              t)
      (frame-update-face-colors fr)))  ; update the way faces display with new bg

Now, (x-defined-colors) may not really be what you want here. Try it, and you will see that the order of the colors you scale through is not ideal. That’s because this list is sorted by name, not color component. A better approach is that taken by command `doremi-bg+’ and its derivatives – there, the RGB or HSV components of the background are incremented/decremented. See AdjustBgRgbHsv.

An approach similar to `doremi-bg-color-name+’ is needed for choosing a font (not just changing the font size), because we again are dealing with a set of discrete values, not just numbers. With a suitable command, you can play the scale of fonts, stopping when you get to the font note you like. Again, in this example, the list of fonts might not be in an ideal order. You can try using an enumeration list like (x-list-fonts "*") or (append w32-fixed-font-alist (list (generate-fontset-menu))) (on Windows), but a shorter list means a lot less running the scales.

  (defun doremi-font ()
    "Successively cycle among fonts, choosing by name
  Operates on the current frame. Cycled font list is (x-list-fonts \"*\")."
    (interactive)
    (doremi (lambda (newval) (set-frame-font newval) newval)
            (frame-parameter (selected-frame) 'font)
            nil                    ; ignored
            nil                    ; ignored
            (x-list-fonts "*")
            'extend)) ; add current font to the ring, if it's not in (x-list-fonts "*")

In general, the Do Re Mi approach is a good one for traversing lots of alternatives that can be ordered. On the other hand, if the set is very large and the choices are quite varied (little order), then it can be helpful to break the choices into smaller, ordered chunks (e.g. font family), and provide a Do Re Mi-style adjuster for each chunk, choosing a chunk from a menu.

A Ring of Frame Configurations

I fell into a burning ring of fire / I went down, down, down, and the frames went higher. / And it burns, burns, burns, the ring of fire, the ring of fire. – Johnny Cash

The Do Re Mi commands in doremi-frm.el let you cycle through various changes to frame properties. The commands are mentioned above. What if you want to undo one of those operations? For instance, you cycle through a load of fonts, and later decide to go back to the font you were using before. It would be nice to be able to get back in one operation, rather than re-cycling through the fonts again until you get to the one you had.

Or, suppose that you moved or resized frames using Do Re Mi commands. It would be useful to be able to get back to a previous frame configuration without going all around Robinson’s barn again.

That’s the motivation behind command `doremi-frame-configs+’. Each of the Do Re Mi frame commands memorizes the current frame configuration in a ring, ‘doremi-frame-config-ring’ (what, another ring?), and `doremi-frame-configs+’ is a Do Re Mi command that lets you cycle among those configurations. (This is beginning to sound incestuous…)

What’s more, besides saving the current frame configuration on ring ‘doremi-frame-config-ring’, each of the Do Re Mi frame commands saves it in the register ‘frame-config-register’, which has ‘C-l’ as its name. So, another way to get back to the previous frame configuration is to use ‘C-x r f C-l’ (jump to register ‘C-l’). And command ‘save-frame-config’ lets you save the current frame configuration to both the ‘frame-config-register’ and the ‘doremi-frame-config-ring’.

Chouette, non ?

Exercise: Make a Moving-Frame Movie

Just for fun, try it out:

  1. `M-x doremi-frame-horizontally+’ in some frame
  2. Use all four arrows [1] to move the frame all around your display.
  3. Stop playing around! Do ‘C-g’ or ‘C-f’ or something to stop fiddling with that frame.
  4. `M-x doremi-frame-configs+’ to “undo”, or replay, the frame movements you just recorded! Forward and backward, cycle as long as you like.

[1] Did I forget to mention that `doremi-frame-horizontally+’ and `doremi-frame-vertically+’ each let you do what the other does – that they each let you use all four arrows to move a frame in any direction? You can also use the mouse wheel to move any direction (just use an arrow to change between back & forth and up & down). See AllFourArrows for more on using all four arrows.

Similarly, you can use all four arrows to combine `doremi-frame-width+’ and `doremi-frame-height+’. And `doremi-bg+’, likewise, lets you change the color component (red, green, blue, hue, saturation, value) that you are adjusting, on the fly. Try making a “movie” using all of these commands.

So, How Does This Frame-Config Undo Stuff Work?

For the curious, this is how the current frame configuration is saved by each of the Do Re Mi frame functions:

  (mapcar 'doremi-push-frame-config-for-command
          '(doremi-bg+ doremi-bg-blue+ doremi-bg-brightness+ doremi-bg-color-name+
            doremi-bg-cyan+ doremi-bg-green+ doremi-bg-hue+ doremi-bg-magenta+
            doremi-bg-red+ doremi-bg-saturation+ doremi-bg-value+ doremi-bg-yellow+ 
            doremi-buffer-font-size+ doremi-fg+ doremi-fg-blue+
            doremi-fg-brightness+ doremi-fg-color-name+ doremi-fg-cyan+
            doremi-fg-green+ doremi-fg-hue+ doremi-fg-magenta+ doremi-fg-red+ 
            doremi-fg-saturation+ doremi-fg-value+ doremi-fg-yellow+ 
            doremi-face-bg+ doremi-face-fg+ doremi-font+ doremi-frame-font-size+
            doremi-frame-height+ doremi-frame-width+
            doremi-increment-background-color doremi-increment-face-bg-color
            doremi-increment-face-fg-color enlarge-font+
            doremi-frame-horizontally+ doremi-frame-vertically+
            doremi-undo-last-face-change+ doremi-undo-last-frame-color-change+))

(This is only done if user option ‘doremi-push-frame-config-for-cmds-flag’ is non-nil.)

Function ‘doremi-push-frame-config-for-command’ just wraps a command with code that saves the current frame configuration:

  (defun doremi-push-frame-config-for-command (command)
    "Advise COMMAND so that it saves frame configuration.
  You can restore previous frame configurations with \\[doremi-frame-configs+]."
    (eval
     `(defadvice ,command (around doremi-push-frame-config-for-command activate)
        "Saves frame configuration. You can restore previous frame configuration \
  with \\[doremi-frame-configs+]."
        (doremi-push-current-frame-config)
        (frame-configuration-to-register frame-config-register)
        ad-do-it   ; The COMMAND code is executed here.
        (when (interactive-p)
          (message
           (substitute-command-keys
             (format "Use `\\[jump-to-frame-config-register]' (`C-x r j %c') or \
  `\\[doremi-frame-configs+]' to restore frames as before (undo)." 
                     frame-config-register)))))))

Function ‘doremi-push-current-frame-config’ does just what it says – except that it doesn’t save the ‘buffer-list’ and ‘minibuffer’ frame properties, because they just get in the way: two otherwise equivalent frame configurations can have different settings for these properties, and we don’t care to notice those differences.

  (defun doremi-push-current-frame-config ()
    "Push the current frame configuration to `doremi-frame-config-ring'
  after removing frame parameters `buffer-list' and `minibuffer'."
    (let ((curr-conf (doremi-frame-config-wo-parameters (current-frame-configuration)
                                                 '(buffer-list minibuffer))))
      (unless (ring-member doremi-frame-config-ring curr-conf)
        (ring-insert doremi-frame-config-ring curr-conf))))

So, here at long last is the code for `doremi-frame-configs+’, which you can probably foresee by now:

  (defun doremi-frame-configs+ ()
    "Cycle among frame configurations recorded in `doremi-frame-config-ring'."
    (interactive)
    (doremi (lambda (newval)
              (set-frame-configuration (ring-next doremi-frame-config-ring newval))
              newval)
            (frame-config-wo-parameters (current-frame-configuration)
                                        '(buffer-list minibuffer))
            nil                      ; ignored
            nil                      ; ignored
            doremi-frame-config-ring ; this is the enumeration to cycle through
            t))                      ; extend doremi-frame-config-ring if it's full

As in the case of ‘doremi-push-current-frame-config’, the ‘init-val’ argument to ‘doremi’ here filters out the bothersome ‘buffer-list’ and ‘minibuffer’ properties from the current frame configuraton.

Macro Defines Commands & Adds Them to Menu

Library doremi-mac.el provides a macro, ‘define-doremi’, to make it even easier to define a ‘doremi-*’ command. You provide a command name suffix, a doc string, a command menu name, and the arguments to ‘doremi’ (except for ‘incr’), and the macro defines a ‘doremi-*’ command and adds it to a Do Re Mi menu.

Examples: Defining Frame Commands, Revisited

  (define-doremi frame-height+
    "Change height of current frame incrementally."        ; doc string
    "Set Frame Height"                                     ; command menu name
    (lambda (new-val)                                      ; setter function
      (set-frame-height (selected-frame) new-val) new-val)
    (frame-height (selected-frame)))                       ; initial value

This automatically defines a command `doremi-frame-height+’, adds a Do Re Mi menu to the menu-bar and adds the new command, with name Set Frame Height, to the menu.

The commands you define using the macro also call two hook functions, so they can do something before or after the call to ‘doremi’. For example, recall command `doremi-bg-color-name+’ (see ChoiceEnumeration). After calling ‘doremi’, it calls (frame-update-face-colors (selected-frame)) to update the way faces display with new background.

Here is how you can define such a command using ‘define-doremi’:

  (define-doremi bg-color-name
    "Successively cycle among background colors, choosing by name." ; doc string
    "Set Background Color"                                      ; command menu name
    (lambda (newval) (set-background-color newval) newval)      ; setter function
    (frame-parameter (selected-frame) 'background-color)        ; initial value
    nil                                                         ; ignored
    (x-defined-colors)                                          ; cycle enumeration
    t)                                                          ; add current color
  ;; The new command `doremi-bg-color-name+' runs this hook after running `doremi':
  (setq define-doremi-after-hook
        '(lambda () (frame-update-face-colors (selected-frame))))

The other hook function is – you guessed it – ‘define-doremi-before-hook’.

Here, BTW, is a screenshot of the Do Re Mi menu:

DrewsEmacsDoReMiMenu

Have fun!, and please post your extensions and modifications to this idea on the EmacsWiki. – DrewAdams


Possible Enhancements to Do Re Mi

YOUR IDEAS HERE – this space for rent.

This has now been done: you can now use all four arrows, and the mouse wheel, to manipulate things in two dimensions. The following pairs of commands, which use up/down and left/right arrows, now work together, so you can use all four arrows to move a frame around or change its dimensions:
    • `doremi-frame-horizontally+’ and `doremi-frame-vertically+
    • `doremi-frame-width+’ and `doremi-frame-height+
So why have two commands for moving, and two for resizing? Why not just a single, four-arrow command for each of the 2D operations moving and resizing? In effect, that’s what you do have, it’s just that you can start with either dimension. And each command in a pair is associated with a prompt letting you know which dimension you’re currently using. When one command of a pair “hands-off” to the other, the prompt switches from “Use left and right or mouse wheel to adjust value” to “Use up and down…” or vice versa.
How was this programmed? Actually, all I did was call the other command of each of these pairs, at the end of the first command, whenever the first command would otherwise be ended with the arrow appropriate for the other command. For example, if you “end” command `doremi-frame-width+’ with an up or down arrow, the last thing it does is call `doremi-frame-height+’. Simple, and a bit weird…
Here is the modified definition of `doremi-frame-width+. The only addition is the last few lines: when the ‘doremi’ command ends with an up or down arrow, we just call `doremi-frame-height+’. A similar change is made to the end of `doremi-frame-height+’, in order to call `doremi-frame-width+.
     (defun doremi-frame-width+ (&optional increment frame)
       "Change width of current frame incrementally."
       (interactive "p")
       (let ((doremi-up-key 'left)           ; Rebind, so keys are more intuitive for width.
             (doremi-boost-up-key 'M-left)
             (doremi-down-key 'right)
             (doremi-boost-down-key 'M-right))
         (doremi (lambda (new-val) (set-frame-width frame new-val) new-val)
                 (frame-width frame)
                 (- increment)))             ; Reverse, so arrows correspond.
       (when (member (car unread-command-events)
                     (list doremi-up-key doremi-down-key
                           doremi-boost-up-key doremi-boost-down-key))
         (doremi-frame-height+ increment frame)))
  • Provide buttons (menu items) in menus that act like up & down arrows. Useful if you’re already using the mouse to choose a menu action.
  • Combine ‘doremi’ with Emacs customize: 1) Have customize use ‘doremi’-style sliders/dials to define values on customize pages. 2) Provide a customize option to the ‘doremi’ command, to save a set value.
  • Use ‘doremi’ or similar direct-manipulation functions to define commands that use ‘doremi’: dynamically choose properties by pointing to them etc. Instead of looking up the function that sets the frame background color, provide a more direct interface that lets you construct a ‘doremi’ command just by pointing, selecting etc. All ‘doremi’ really needs to know is what access/modifier functions to use.
  • Provide a ‘setf’-like functionality for lots and lots of Emacs properties. That is, instead of having a zillion different ways to access and set properties, why not do what Common Lisp has done with ‘setf’? This is non-trivial, BTW. (This is getting off topic, but it’s related in spirit.)

Allow doremi-up-key, doremi-down-key, etc, to be lists (sets) of keys, any of which are accepted. This allows use with alternative hardware, such as FootSwitches or a GamePad, without removing it from the normal arrow keys. – JohnSturdy

Agreed. It’s on my todo list. I do that in Icicles, but haven’t gotten around to doing it for Do Re Mi also. Thx – DrewAdams
Done. Thanks for reminding me about this. – DrewAdams

Possible Applications of Do Re Mi

YOUR IDEAS HERE

Since you asked, I added `doremi-buffers+’ in library doremi-cmd.el. Here it is:
     (defun doremi-buffers+ ()
       "Successively cycle among existing buffers."
       (interactive)
       (doremi (lambda (newval) (switch-to-buffer newval 'norecord) newval)
               (current-buffer)
               nil
               nil
               (buffer-list)))
DrewAdams
  • Great! With the addition of not switching to “boring” buffers (most of the ones with names *like this* it could be really handy sometimes. For example, when doing visual diffs between several files when you do not want to use ediff. Btw, can I use left-right instead of up-down to switch? (yes I am too lazy to even scroll up on this page and find out… ☺ – MaDa
To get only “interesting” buffers, filter (buffer-list). If you (require 'cl), then you can use ‘delete-if-not’. Define your own ‘my-interesting-buffer-p’ to keep only buffers you want.
     (delete-if-not (lambda (buf) (my-interesting-buffer-p buf)) (buffer-list))
Elsewhere, I use a function ‘interesting-buffer-p’ that returns non-nil only for buffers that are live and whose names do not start with a space. (This is defined in library misc-fns.el.) You can modify this to also filter out buffers that start with ‘*’.
     (defun interesting-buffer-p (buffer)
       "Non-nil if BUFFER is a live buffer whose name does not start with SPC."
       (and buffer (setq buffer (live-buffer-name buffer)) ; Live buffer's name.
            (or (zerop (length buffer))      ; Not an empty name.
                (not (char-equal ?\  (aref buffer 0)))))) ; Starts with non-blank.
To use ‘left’ and ‘right’ instead of ‘up’ and ‘down’, follow the examples in the code. See ‘move-frame-horizontally’, above. All you need to do is bind variables ‘doremi-up-key’ and ‘doremi-down-key’ to keys (events) ‘left’ and ‘right’:
     (let ((doremi-up-key 'left)
           (doremi-boost-up-key 'M-left)
           (doremi-down-key 'right)
           (doremi-boost-down-key 'M-right))
      ...)
(Man, you are lazy! If you’re that lazy, you won’t play with the code to improve it. Get some exercise: scroll up, young man. ;))
BTW, if you like `doremi-buffers+’, check out SwBuff or Icicles. SwBuff also provides direct manipulation, and both SwBuff and Icicles give you various ways to include or exclude various buffers based, for example, on their names (regexp matching). – DrewAdams

Questions / Other Discussion

YOUR IDEAS HERE – this space for rent.

I played around a little and made a command for incrementing/decrementing the tab width:

    (defun doremi-tab-width (increment)
      "Change value of tab width incrementally."
      (interactive "p")
      (doremi (lambda (new-val)
                (setq tab-width (doremi-limit new-val 1 nil)))
              (or tab-width 8)
              increment))

By the way, since the arrow keys on my keyboard are broken after too much gaming, I want to use C-p and C-n to go “up” and “down”. I tried to customize doremi-up-key to C-p. While it shows up in the prompt, it doesn’t work.

Yes, that’s the idea (I had forgotten I’d defined ‘doremi-limit’). Just bind the keys as keyboard events (characters or symbols), in the command definition:

    (defun doremi-tab-width (increment)
      "Change value of tab width incrementally."
      (interactive "p")
      (let ((doremi-up-key          ?\C-p)
            (doremi-boost-up-key    ?\M-p)
            (doremi-down-key        ?\C-n)
            (doremi-boost-down-key  ?\M-n))
        (doremi (lambda (new-val)
                  (setq tab-width (doremi-limit new-val 1 nil)))
                (or tab-width 8)
                increment)))

That should work for you. Or if you want to customize the keys, so they are the same everywhere, then customize them to `?\C-p’, `?\C-n’, etc. However, try the latest doremi.el – there was a bug in the Customize type expected. It was expecting a symbol only, not a character or a symbol. Should be OK now; let me know, if not. – DrewAdams

That works, thank you for the help! This is a very useful tool when dealing with weirdly formatted files.

hi, thanks for your good tools - doremi. When I use M-x doremi-bg+, COMPONENT can only be r/g/b/h/s/v, can it be rgb or hsv? I think rgb or hsv can make me select color I like more quickly. another question, I found below statement in your many packages:

;;  Commands defined here:
;;
;;    `facemenu-mouse-menu', `facemenup-change-bg-of-face-at-mouse',
;;    `facemenup-change-bg-of-face-at-point',
;;
;;  Non-interactive functions defined here:
;;
;;    `facemenup-face-bg', `facemenup-face-fg',
;;    `facemenup-set-face-attribute-at--1',
;;    `facemenup-set-face-from-list'.
;;
;;  Internal variables defined here:
;;
;;    `facemenu-mouse-menu', `facemenup-err-mouse',
;;    `facemenup-err-point', `facemenup-highlight-menu',
;;    `facemenup-last-face-bg', `facemenup-last-face-changed',
;;    `facemenup-last-face-fg'.
;;
;;  Button types defined here:
;;
;;    `help-facemenu-edit-color', `help-facemenu-set-face'.

which package generate that? I could not find that.☺ I have found a package auto-document, but It only generate command and variable. – ahei

1. It’s unclear to me what you are asking – could you rephrase it or give an example? What do you mean by “can it be rgb or hsv?” Do you mean that you would like to increment all of the R, G, and B components (or all of the H, S, V components) together, in lock step? I don’t see that as very useful, but please describe the use case you have in mind.

I suppose you are aware that you can change the component you are incrementing at any time, without exiting the command. Just hit a different component indicator (‘r’, ‘g’, ‘b’, ‘h’, ‘s’, ‘v’) to start incrementing that component immediately. The same command invocation thus serves for any combination of components. But yes, each incrementation is of only one component.

2. I update those lists of defined things by hand – no big deal. ThierryVolpiatto has some code to do something similar automatically, but: (a) It is part of an unrelated library – AFAIK, he doesn’t want to break it out as a separate library, for some reason. (b) It clutters the Commentary (in a minor way) with begin…end indicators. (c) He doesn’t want the lists to be alphabetical. I suggested to Thierry that he create a small standalone library for this, and that he let users optionally sort each group, but he wasn’t interested.

In my case, I don’t mind updating the lists by hand – I do that when I check my most recent changes with ‘ediff’ to create a change-log entry. Doing it by hand is of course error prone, but it actually helps me wrt updating the change log. I do think a good tool would be helpful as an aid, however. – DrewAdams

1.

Do you mean that you would like to increment all of the R, G, and B components (or all of the H, S, V components) together, in lock step?

Yeah, I do mean that.

Just hit a different component indicator (‘r’, ‘g’, ‘b’, ‘h’, ‘s’, ‘v’) to start incrementing that component immediately. The same command invocation thus serves for any combination of components.

I think increment all of the R,G,B components (or all of the H, S, V components) together is useful as the way of you said above. ☺

2.

I update those lists of defined things by hand

First, I surprised when I heard that,☺, your package is so many. Second, but, I saw “lists of defined” in many packages on emacswiki, they all update it by hand? but those format so similar. – ahei

1. I don’t understand why you would want to increment all of H, S, V equally at the same time. What effect do you hope to get? What is the use case?

Incrementing (decrementing) all of R, G, B equally at the same time is essentially the same thing as incrementing (decrementing) the V component. If you are increasing the red, blue, and green light equally, then you are increasing the brightness.

I just don’t see the use case for such equal incrementing. If you convince me of a use case, I’ll consider it. Or you could define such a command yourself. Just look at the code defining `doremi-bg-blue+’ and `doremi-bg+’. Essentially, the code would call, in a single command invocation, ‘doremi-increment-background-color’ for each of the components you want to change.

2. I can’t speak for others. AFAIK, the only tool support for this is the code by ThierryVolpiatto that I mentioned. I believe I am the main one who includes such lists in EmacsLisp files. I was certainly the first, but perhaps there are some others now who have adopted the idea. In any case, I update the lists manually.

But as I said, most source-code changes are incremental, meaning minor changes to the lists. And I need to note the change (addition, removal, renaming) in my change log anyway. Updating source code involves many such housekeeping tasks; updating these lists is only a minor part of what’s involved. I do agree that this could be mechanized. Thierry made a good start, but he doesn’t want to break that code out as a separate library. If you are interested in a tool to do this, I suggest contacting Thierry. – DrewAdams

1. Incrementing (decrementing) all of R, G, B equally at the same time is essentially the same thing as incrementing (decrementing) the V component. If you are increasing the red, blue, and green light equally, then you are increasing the brightness. oh, I do not mean that, what I want is not increasing the red, blue, and green equally,is not equally. Increasing of R,G,B is not mean increasing R,G,B equally, it like moving cursor on the colors square, iterate all colors. Sorry for my poor english, ☹, could you understand my meaning?

2. There have command doremi-bg-color-name+ and doremi-face-bg+ in doremi, but do not have doremi-fg-color-name+, doremi-face-fg-color-name+, I think it’s useful, could you add it to doremi? – ahei

1. Good idea. I’ll do that.

2. I did that. Try the latest. You’ll also need the latest hexrgb.el. – DrewAdams

1. Thanks for you understanding, thanks for you doremi. ☺

2. When use doremi select color, I type “C-g” to abort color selecting, but it does not work, I think it is useful, what do you think about it? – ahei

(I moved your report about the Download link to EmacsWikiProblems. That page is reached by the ‘Problems’ link at the top of each wiki page.)

I’ll think about ‘C-g’. It seems like there was a reason why I didn’t do that, but I don’t remember what it was. Anyway, you also have ‘doremi-undo-last-frame-color-change’ and ‘doremi-undo-last-face-change’, as ways to undo changes. They let you bounce back and forth between the changed appearance and the previous one, to compare. And `doremi-frame-configs+’ lets you repeatedly undo other kinds of frame changes.

See above, on this page – search for ‘undo’. For some frame changes, you also have ‘C-x 5 2’, which will give you a copy of the frame without the changes. – DrewAdams

Well, it took a while, but I think I’ve done what you asked, both:

  • being able to increment more than one color component at a time, and
  • being able to use ‘C-g’ to cancel the current Do Re Mi command and return to the previous state.

The latter is not available for the ‘*-all-faces-*’ and ‘*-all-frames-*’ commands, because there is no single face or frame color to save and then restore. But it is available for the other commands.

Wrt multiple increments:

  • You can use ‘R’ to increment red, green, blue together, and ‘H’ to increment hue, saturation, value together. So the input choices are [rgbhsvRH]. As always, you can change from one to another on the fly at any time. When you change, the original increment value you input is reused.
  • You can use either a number or a list of 3 numbers (red, green, blue or hue, saturation, value) as the increment argument. If you use a number and you choose ‘R’ or ‘H’, then the number is used for each of the 3 components (rgb or hsv). If you use a list and you choose a single component [rgbhsv], then the corresponding list element is used.

Note: I renamed the commands that iterate, by appending a `+’, so it’s easier to distinguish them from the other commands in the library. I did the same thing in other libraries that define Do Re Mi commands: the suffix `+’ will by convention always mean an iterative incrementing/cycling command.

I also improved a few other things at the same time. Thanks for your suggestions. Hope the improvements help. – DrewAdams

Thanks for you doremi.

1. increment all of the R,G,B components (or all of the H, S, V components) together, that mean: select color use doremi like move point on color palette ground, from point to another point, iterate all color point on color palette ground.Your implemented is not my want, but I think that is also a good way to select color.I can not describe my meaning use my poor english clearly, you only use your wisdom to understand my meaning, ☺

2. C-g dose not work in doremi-bg-color-name+ and doremi-face-bg-color-name+. – ahei

I moved your palette.el reports to ColorPalette. They don’t belong here.

1a. There is no sense in having Do Re Mi iterate on the palette itself. The idea of Do Re Mi is that of direct manipulation: directly manipulate objects in-place, rather than needing recourse to a separate interface (e.g. a color palette). Here, the objects are frame and face attributes.

1b. You already have the ability to increment a color’s HSV components using the palette (without Do Re Mi). Simply hold down the Shift key while you move the cursor. The current color is then updated as you move. If you want to increment RGB components, then use ‘r’ or ‘R’, ‘g’ or ‘G’, ‘g’ or ‘G’, and then hit ‘RET’ to update the current color. (For RGB incrementing, there is no Shift shortcut to update the current-color swatch as you move, so just hit ‘RET’ when you want to update it.)

1c. You can pick up the starting color for a Do Re Mi command from anywhere, if you use palette.el or eyedropper.el – in particular, you can pick it up from the ColorPalette.

If you want to pick up a color from the palette to use as the starting point for a Do Re Mi background-color command, just hit ‘RET’, which is ‘pick-background-color’ (aka ‘palette-pick-background-at-point’). The Do Re Mi commands that increment a frame or face background color start with that picked-up color, if available. It is the value of variable ‘palette-picked-background’.

Similarly, you can use command ‘pick-foreground-color’ (it is not bound to a key) to pick up the foreground color, for use as the starting point in a Do Re Mi command that increments a frame or face foreground color. The color picked up is available as the value of ‘palette-picked-foreground’. – DrewAdams

2. Done. Thx. – Drew

   There is no sense in having '''Do Re Mi''' iterate on the palette itself.

um, I see, however, how can I to iterate all colors? color palette can do it, but it too slow. – ahei

I don’t know what you mean by “iterate all colors”. Be specific. How do you want to iterate colors? By name? By a particular color component? By some combination of components? Please describe what you mean. Start at the top level: what is it that you really want to do? Maybe you can do it with the palette or Do Re Mi; maybe you can’t. – DrewAdams

I thought you have understood my meanning.

increment all of the R,G,B components (or all of the H, S, V components) together, that mean: select color use doremi like move point on color palette ground, from point to another point, iterate all color point on color palette ground.That is my want.

If everything else fails, do you understand chinese? ☺ – ahei

No, sorry, wo bu dong zhong hua. ;-)

I guess you’re saying that you would like to, on the palette only, move from one color point to another, and have something (what?) change as you do that. Dunno if that’s what you mean, but if so I don’t see much point in it. As I said, the point of Do Re Mi is to act on something directly (and incrementally). I don’t see any gain in introducing the palette as an intermediary.

Unless you are interested only in seeing the current Do Re Mi color in the context of the palette, just to see where you are on it. Perhaps you mean that: show the current color’s location on the palette while you increment using a Do Re Mi color command. That would be possible, but I don’t know how interesting it would be.

Keep in mind that if we’re talking about Do Re Mi incrementing all components together, then the individual increment values must be communicated to the command. And that is done once and for all, up front, for a given command. So if you somehow mean driving that from the palette, I don’t understand.

I don’t mean to cut you off. I liked your first idea about incrementing the components together. So I’m sure you have lots of good ideas. I haven’t yet understood this one. It’s of course also the case that even if it’s a great idea I might not be interested or it might not be feasible or easy to implement. ;-) But if you want to try again to explain it, I’ll try to understand. Feel free to email me. – DrewAdams

☺ let us number color point on color palette, now color palette like this:

1  2  3  4  5
6  7  8  9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

my meaning is: how can I iterate colors on color palette from 1 to 25, increment with 1, that is 1,2,3,4,5,6,…,21,22,23,24,25. Use your color palette, I can do this, just put cursor to color point 1, and then hold down Shift key, then move cursor from 1 to 25, but, your color palette is slow when I start it every time, how can I do that in other way? Use doremi, I can iterate part of all colors, e.g. use doremi-bg+, then choose blue component, but It only iterate part color points, not all, maybe 2,7,12,17,22, also maybe 5,10,15 20,25, also may be 1,2,3,4,5 when use red component, also maybe 1,2,8,13,19,24,24 when use red,blue,green component together.

In a word, what I want is iterate all colors from 1 to 25, increment with 1. – ahei

You say in effect that you want to increment hue, but move down to the next ColorPalette row when you get to the end of the current row. I implemented something that I think corresponds to that. It increments hue, until hue hits its limit, then it decrements saturation once, and then begins incrementing hue again – and so on. This corresponds to moving across a ColorPalette row (hue) and doing that for each row in turn.

I’m not convinced this is very useful, but you have it, in any case. See commands `doremi-*-hue-stepping-saturation+’.

You need to be aware that hue, saturation, and value do not correspond in a simple way to the color coding that Emacs uses, which is RGB. In the ColorPalette, if you just increment red or just blue or just green, you will see how the cursor moves over the Hue x Saturation space — the movement is in some ways surprising. The relation between the two color spaces is not simple and not very intuitive. See the commentary in file palette.el for more information. – DrewAdams

It is a pity that you can not understand my meaning, I’ll try to explain it to you when I belive that you can understand, ☺. – ahei

Dunno what that means. It’s a pity that you (apparently) cannot say what you mean. What you said seems clear enough – clear diagram, no problem wrt English. But apparently it doesn’t correspond to what you were thinking.

AFAIK, I implemented just what you requested: “iterate colors on color palette from 1 to 25, increment with 1, that is 1,2,3,4,5,6,…,21,22,23,24,25”, where the numbers correspond to the palette colors as follows (your diagram):

1  2  3  4  5
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

1,2,3,4,5,6,…25 means incrementing hue (1,2,3…) until the end of a row (5), then incrementing saturation once to move to the next row (6), and then incrementing hue along that row (6,7,8…), and so on. That’s what you said you wanted, and that’s what I implemented. You can traverse all of the hue x saturation space in hue order first, saturation order second. You can do it forward or backward (25,24,23,…1). And you can use increments other than 1 (the default).

This enhancement meant adding 6 non-trivial functions, giving you commands for both foreground and background and for both frame and face colors. Your “spec” seems quite clear. If what you specified was not in fact what you really wanted, the fault lies with the specifier, I’m afraid — I don’t see another interpretation for your request statement.

You can implement the next YAGNI you think you need, yourself. – DrewAdams

1. I tried `doremi-*-hue-stepping-saturation+’, it is not traverse all of colors on palette, at least I can not get black and white color use `doremi-*-hue-stepping-saturation+’. My meaning is traverse all of colors on palette. Anyway, thanks for `doremi-*-hue-stepping-saturation+’.

2. If you think what I need is not mostly users need, at least is not you need, you need not to implement it, until you think it is useful or mostly users think it is userful.☺

Black and white are not in the hue x saturation palette – they are not in the sequence 1,2,3…25 that you requested. There are 3 color components. A plane space covers two components only — in this case, hue and saturation. Value (brightness) is covered in a separate panel of the ColorPalette. Wrt Do Re Mi, you can use `doremi-*-hue-stepping-saturation+’ to traverse the hue x saturation palette, as you requested, and you can use ‘doremi-*-value’ to brighten or darken a color whose hue and saturation you have chosen. – DrewAdams

oh, sorry, is my mistake, My meaning is traverse all of colors which include black and white color. You implement it use two commands, can it be only one command which traverse all of colors? – ahei

No. Already, this command not very useful, as I’ve said – it makes little sense to iterate blindly through thousands of colors with little change and little direction (guidance). IOW, it makes little sense to traverse everything, in sequence, instead of focusing and directing your color search intelligently.

The current command that you requested iterates over the entire hue x saturation space. In palette terms, that’s about 11500 colors. If you were to add saturation to that mix, then you would be iterating over well over a million colors — in the palette alone. With your preferred increment of 1, the Do Re Mi iteration would be longer still. That’s silly.

Do yourself a favor and learn to use the regular Do Re Mi commands in a focused manner: drive toward and around the colors you are really interested in in a more direct fashion, using a combination of hue, saturation, and value or red, green, and blue or all 6 at once.

In the palette, take advantage of the fact that colors are organized into separate spaces (palettes), and you have direct access to each individual color – no need to consider them one at a time, sequentially. If you want a light purple color, then go directly to it. When you want to hear a song, do you start up a single, gigantic tape of every song in your collection and simply wait until it gets round to playing the song you wanted to hear? No, you go directly to the one you want.

Guide your search for a particular color by using hue, saturation, and value separately and together in a coordinated way. It would be truly silly to simply increment blindly from 1,2,3…115000000. You can do better than that, and you already have the tools to do it. AFAICT, you are somehow missing the point. – DrewAdams

1. Increment 1 is only one of my examples, not I preferred, users can iterate all of colors with increment they like.

2. yeah, I also think palette is the best tools to choose color, is intuitive, but M-x palette and M-x facemenup-paste-to-face-fg-at-point is slow, and doremi-face-bg-color-name+ is fast, so I want use doremi to iterate all of colors.

1. It doesn’t matter much what the increment is, and Do Re Mi lets you boost the increment anyway using ‘M-’. The point is that it is pretty pointless to traverse the entire set of colors in a single order — any single order — at any speed. The point is to steer toward the color you want, instead of covering the whole field without any aim. Steering wheel = on-the-fly choice of component: [rgbhsvRH].

Change components at any time (I’m not sure you have understood that part), without exiting the command. Need the color to be a little redder? r: Add some red. Need it to be a little darker? v: Turn down the brightness. Need it to be a little paler? s: Turn down the saturation.

In the old days, we had to adjust the color on TVs occasionally. Do you think we had only one dial, which ran the gamut of all shades and saturations of all color hues? No, we had separate dials for hue, brightness, etc. And with Do Re Mi you have all of the dials combined in one command – just hit a different letter when you want to change dials.

2. Use Do Re Mi to iterate colors intelligently – aim. You can still iterate through all of the colors, using any of the Do Re Mi color commands. There is a color that you want somewhere in the middle of a big field. Use the steering wheel to get to it, instead of just mowing down the whole field systematically like a TV raster. – DrewAdams

Change components at any time (I'm not sure you have understood
that part) -- DrewAdams

I do understand it, and I also used it. but if I choose r component with increment 1000, and then I choose v component, then v component’s increment is also 1000, but increment 1000 is so large for v component. – ahei

That’s the purpose of option ‘doremi-RGB-increment-factor’ — see the doc for it (‘C-h v’). I customize it, myself, to 256. The value you use probably will depend on the kind of RGB color representations (how many hex digits per component) you work with. – DrewAdams

can you display current component using when doremi series commands is executing? – ahei

What do you mean – let you know whether you last hit ‘r’ or ‘h’, for instance, in case you forgot? For that, no, but you can just hit ‘r’ again, to be sure you’re incrementing red (or whatever). I don’t understand the problem. – DrewAdams

May be forget, maybe other, I think you display component users using is good for user, and I think this is easy to do for you.

For that, no, but you can just hit `r' again, to be sure you're
incrementing red (or whatever). -- DrewAdams

yeah, users can do that, but it’s so trouble for users. how do you think about it? – ahei

No, I don’t think it’s useful. You won’t forget within a few seconds what you just did. And you don’t need to remember, in any case: WYSIWYG. You hit a key based on what component you want to increase or decrease – it doesn’t matter which component you incremented in the past. All that counts is what the current color is (look at it) and what color you want (redder, darker, etc.). I see no use for a reminder of what component you were incrementing up till now. – DrewAdams

can you display current component using when doremi series
commands is executing? -- [[ahei]]

it doesn't matter which component you incremented in the past.
All that counts is what the current color is (look at it)
and what color you want (redder, darker, etc.).

I not mean display component users incremented in the past, I mean display component users using. – ahei

Sorry, not interested. When you press a key, you know what key it is. – DrewAdams

not only one key, you need press other keys (e.g. up, down) to increment, and then you may press other key to change component, and then press other keys to increment, and then repeat above. After change some components and press keys to increment, you may forget what component you using, users may forget. – ahei

I think my answer was clear. – DrewAdams

C-g does not affect color-themes+ – ahei

No idea what that means. If you want to report a bug, please provide a complete recipe, starting with emacs -Q. – DrewAdams

oh, I make a mistake, C-g does not affect doremi-color-themes+. – ahei

OK, I understand now. Your latest statements have nothing to do with the preceding discussion. It is far clearer if you just submit a bug report or enhancement request by email. This page has no structure supporting separate dialog threads etc., and it’s unlikely that others are very interested in some of the exchanges.

Anyway, wrt your enhancement request: try the latest. Note that there is no sure-fire way to restore everything after making a color-theme change. ‘C-g’ now does the same thing for `doremi-color-theme+’ that ColorTheme does when you choose pseudo-theme [Reset]. That “undo” is not always satisfactory, but it can be better than nothing.

FYI, I made the same ‘C-g’ change for `icicle-color-theme'. That Icicles command cycles themes like `doremi-color-theme+’, but it also lets you (1) use completion to choose themes; (2) filter the list of themes to pick from (regexp, substring, fuzzy match, etc.); (3) sort the list in various ways; and (4) pick themes in any order. – DrewAdams

I think you can delete our preceding discussion.

‘C-g’ work on ‘doremi-color-thems+’ now. icicle-color-theme do cycles completion, but it does not apply theme change, it only cycles completion, and I use: M-x icicle-color-theme color-theme-billw, it does not change my theme, it only flash and then restore my old theme immediately.

I wrote one article to introduce your icicles, doremi and color palette, ☺, at http://ahei.yo2.cn/icicles-doremi-palette.htm, ☺ — ahei

Please pick up the latest Icicles files and doremi-cmd.el. Should be OK now.

I took a look at the URL you posted (translated thanks to Google, so I didn’t understand everything ;-)). Just a minor comment: It is `menu-bar+’, not `menu-bar +’ (should be no space). Likewise for `facemenu+’. But maybe that is just a problem on the translated page – it also shows things like ‘facemenup -palette--face’, which I assume should be ‘facemenup-palette--face’.

Consider creating an EmacsWiki page (it could be short) that describes some of your config code, or at least points to your blog that shows that. This could be helpful for others. (And you can create an English version using Google translate.) Thx – DrewAdams

1. yeah, that’s the google translator’s problem.

2. I try your latest version of doremi and icicles,

emacs -Q
add all icicles files to load path
(require 'icicles)
M-x icy-mode
M-x icicle- and then type "TAB", I get message "Symbol's value as
variable is void: icicle-current-TAB-method"
M-x color-theme-aalto-dark and then type RET, I get message "Symbol's
value as variable is void: icicle-prefix-completion-is-basic-flag"

3. I’ll consider your suggestion.

ahei

It’s pretty clear to me that you have done something wrong. In particular, you apparently do not have all of the latest Icicles files. ‘icicle-current-TAB-method’ is defined in file icicles-var.el. And there is no variable ‘icicle-prefix-completion-is-basic-flag’, and no code uses such a variable.

Be sure that you are loading all of the latest Icicles files. If you then run into a problem, then please file a normal, complete bug report, using ‘M-x icicle-send-bug-report’. Provide a reproducible, step-by-step recipe, starting with emacs -Q, and provide your platform, Emacs version, and any other relevant info.

And please do not report Icicles, Color Palette, or any other problems that are unrelated to Do Re Mi on this page. Thx – DrewAdams

oh, sorry, my mistake, but I only have seen you update three files, icicles-opt.el, icicles-cmd.el, icicles-cmd1.el in RecentChanges page, the variable ‘icicle-prefix-completion-is-basic-flag’ is in previous version of icicles-fn.el, I do not know you updated it, and icicle-color-theme is work now after I update file icicles-fn.el. However, I thought when I press TAB after I execute M-x icicle-color-theme, it will apply theme like doremi-color-themes after I seen you said “That Icicles command cycles themes like `doremi-color-theme+’”, and if I use icicle-color-theme change my color theme, and later I use M-x icicle-color-theme, and type some letters, and then press ‘C-g’, icicles will restore my color theme. – ahei

Always pick up all of the Icicles source files. I often update files on an individual basis, but you need them all. If you want to see all changes in RecentChanges, then you need to click the links to show minor edits and rollbacks.

Icicles cycling is similar to Do Re Mi cycling, but it is also different. As I said, Icicles lets you skip candidates when cycling – you can access any candidates in any order. And it lets you filter the set of candidates to cycle. And sort it. And so on.

For Icicles cycling that acts on the candidates, use ‘C-next’, ‘C-down’, ‘C-prior’, or ‘C-up’. Without the ‘C-’ modifier you cycle without action on the candidates cycled. With modifiers ‘C-M-’ you cycle help on individual candidates. This is not particular to color themes – it is the way Icicles works in general. So instead of using ‘up’ and ‘down’, as in Do Re Mi, you can use ‘C-up’ and ‘C-down’. Or ‘C-prior’ and ‘C-next’, if you filter with a substring or regexp.

‘icicle-color-theme’ applies the candidate color theme. If you don’t quit with ‘C-g’ (two ‘C-g’s in this case), then the new theme stands. If you use ‘C-g’, then the original colors are restored. The same thing applies to ‘icicle-frame-bg’ and ‘icicle-frame-fg’, which are analogous to `doremi-bg-color-name+’ and `doremi-fg-color-name+’. – DrewAdams

OK, I see – ahei


See Also

The following pages discuss things that are in the spirit of DoReMi, even though they do not necessarily use the generic doremi commands. – Simon Nuttall


Lisp:doremi.el, Lisp:doremi-cmd.el, Lisp:doremi-frm.el, Lisp:doremi-mac.el, Lisp:facemenu+.el, Lisp:frame-cmds.el, Lisp:hexrgb.el, Lisp:menu-bar+.el, Lisp:ring+.el, Lisp:setup-keys.el, Lisp:thumb-frm.el, Lisp:zoom-frm.el

CategoryDisplay CategoryFrames CategoryCode CategoryFaces CategoryCommands CategoryCustomize CategoryWindows CategoryExtensions