[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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”:
argument-pop
(input) pop the next space-delimited word or a
double quote delimited string argument from the argument
line. Backslashes may be used to escape double quotes or backslashes
inside double quoted strings.
argument-pop-rest
(input) return the remainder of the
argument line as a single string, leaving input empty
argument-pop-or-read
(input prompt &optional
completions) either pop an argument from the argument line, or if it
is empty use “prompt” to prompt the user for a value
argument-pop-rest-or-read
(input prompt &optional
completions) either return the remainder of the argument line as a
string, leaving input empty, or use “prompt” to prompt the user for
a value
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") |
Create a new type that can be used for command arguments. type can be any symbol.
When body is evaluated input is bound to the
argument-line. It is passed to argument-pop
,
argument-pop-rest
, etc. prompt is the prompt that should
be used when prompting the user for the argument.
(define-stumpwm-type :symbol (input prompt) (or (find-symbol (string-upcase (or (argument-pop input) ;; Whitespace messes up find-symbol. (string-trim " " (completing-read (current-screen) prompt ;; find all symbols in the ;; stumpwm package. (let (acc) (do-symbols (s (find-package "STUMPWM")) (push (string-downcase (symbol-name s)) acc)) acc))) (throw 'error "Abort."))) "STUMPWM") (throw 'error "Symbol not in STUMPWM package"))) (defcommand "symbol" (sym) ((:symbol "Pick a symbol: ")) (message "~a" (with-output-to-string (s) (describe sym s)))) |
This code creates a new type called :symbol
which finds the
symbol in the stumpwm package. The command symbol
uses it and
then describes the symbol.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on February 2, 2024 using texi2html 1.82.