[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3 StumpWM Types

All command arguments must be of a defined “StumpWM type”. The following types are pre-defined:


A yes or no question returning T or NIL.


A lisp variable


A lisp function


A StumpWM command as a string.


A key sequence starting from *TOP-MAP*


An existing window number


An integer number


A string


A single key chord


An existing window’s name


A direction symbol. One of :UP :DOWN :LEFT :RIGHT


A gravity symbol. One of :center :top :right :bottom :left :top-right :top-left :bottom-right :bottom-left


An existing group


A frame


A shell command


The rest of the input yet to be parsed.


An existing StumpWM module

Additional types can be defined using the macro define-stumpwm-type. Emacs users who are accustomed to writing more complicated interactive declarations using "(interactive (list …))" forms will find that similar logic can be put into StumpWM type definitions. The macro is called like this:

(define-stumpwm-type :type-name (input prompt) body)

The keyword :type-name will then be available for use in defcommand macros. When commands are called, the bodies of these type definitions are called in turn to produce actual argument values.

Type definitions produce their value in one of several ways: by reading it from the argument line bound to a keystroke, by prompting the user to enter a value, or by generating it programmatically.

Within the body of the type definition, the argument “input” is bound to the argument line provided in the command string, and “prompt” to the string prompt provided in the defcommand form. The usual convention is to first check if an argument has been provided in “input” and, if it hasn’t, to prompt for it using “prompt”.

StumpWM provides several convenience functions for handling the value of “input”:

As an example, here’s a new type called :smart-direction. The existing :direction type simply asks for one of the four directions “left”, “right”, “up” or “down”, without checking to see if there’s a frame in that direction. Our new type, :smart-direction, will look around the current frame, and only allow the user to choose a direction in which another frame lies. If only one direction is possible it will return that automatically without troubling the user. It signals an error for invalid directions; it could alternately return a “nil” value in those cases, and let the command handle that.

(define-stumpwm-type :smart-direction (input prompt)
  (let ((valid-dirs
         (loop  ; gather all the directions in which there's a neighbouring frame
            with values = '(("up" :up)
                            ("down" :down)
                            ("left" :left)
                            ("right" :right))
            with frame-set =
              (group-frames (window-group (current-window)))
            for dir in values
            for neighbour = (neighbour
                             (second dir)
                             (window-frame (current-window)) frame-set)
            if (and neighbour (frame-window neighbour))
            collect dir))
        (arg (argument-pop input)))  ; store a possible argument
    (cond ((null valid-dirs)  ; no directions, bail out
           (throw 'error "No valid directions"))
          (arg  ; an arg was bound, but is it valid?
           (or (second (assoc arg valid-dirs :test #'string=))
               (throw 'error "Not a valid direction")))
          ((= 1 (length valid-dirs))  ; only one valid direction
           (second (car valid-dirs)))
          (t  ; multiple possibilities, prompt for direction
           (second (assoc (completing-read input prompt valid-dirs
                                           :require-match t)
                          valid-dirs :test #'string=))))))

(defcommand smarty (dir) ((:smart-direction "Pick a direction: "))
  ;; `dir' is a keyword here
  (message "You're going ~a" (string-downcase dir)))

(define-key *root-map* (kbd "R") "smarty right")

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated on January 28, 2024 using texi2html 1.82.