User:Gwern/.stumpwmrc

Please note that I do not use Stumpwm and have not for years since the early alphas of Xmonad began development; this .stumpwmrc is almost certainly broken & outdated. You may find my xmonad.hs of interest.


 * -*-lisp-*-
 * .stumpwmrc --- my own Stumpwm customizations
 * Copyright (C) 2006 by gwern
 * Author: gwern 
 * License: public domain
 * Where: 
 * When: Time-stamp: "2007-01-28 22:04:22 gwern"
 * Keywords: local,customization,Stumpwm
 * Commentary: Modifies visual appearance of mode-line, input box, X windows; adds numerous key bindings
 * and heavily integrates Surfraw shortcuts. Includes some helper/utility functions.


 * Global variables;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 * Declare our default programs for certain things, and how visually things will look,
 * for the mode line, the input box, etc.
 * Declare our default programs for certain things, and how visually things will look,
 * for the mode line, the input box, etc.

(in-package :stumpwm)
 * Declare what this file is for.

(setf stumpwm::*debug-level* 10)
 * Stumpwm crashes or freezes too much. If we set the debug up to ludicoursly high levels, maybe we'll learn something.

(defparameter X-TERM "exec aterm -fn '-lispm-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*' -sh 15 -tr -trsb -cr yellow -pr green -bl +vb -ut +sr -sl 1000 +rv -fade 50 -fg white -bgtype scale -txttype true -bd black +sb -tint purple " "What shall be the command run when we want an X terminal?")
 * Variables
 * Terminals are important.(

(defun cat (&rest strings) "Concatenates strings, like the Unix command 'cat'. A shortcut for (concatenate 'string foo bar)."      (apply 'concatenate 'string strings))
 * I don't really want to be constantly typing "concatenate 'string" - this simplifies things.
 * Thanks to sabetts of #stumpwm

(defparameter X-TERM-BROWSER (cat X-TERM " -e elinks")  "We will want to open up our chosen CLI web browser in our chosen X terminal. What is it?")
 * Text browsers are good, too.

(defparameter X-WWW-BROWSER "exec firefox " "What GUI WWW browser shall we use?")
 * Yay for GUI web browsing!

(defparameter X-IMAGE-VIEWER "exec gqview " "Sometimes I like to look at images. We need some sort of client for that.")
 * Image viewers can be useful.

(setf *shell-program* (stumpwm::getenv "SHELL")) ;getenv is not exported
 * Set the default shell

(setf *focus-color* "green") (setf *unfocus-color* "black")
 * Window border colors

(set-font "-lispm-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*")
 * Set the font for the input box. I have a nifty Lisp machine font.

(setf *message-window-gravity* :bottom-right) (setf *input-window-gravity* :bottom-right)
 * Set the message and input box to the bottom right. This way it overlaps with mode-line.

(set-bg-color "black") (set-fg-color "lightgreen") (set-border-color "yellow")
 * Colors for the input box; these should fairly self-explanatory. 'set-fg-color' will change the color
 * of the font in the echo area, for example, and the background will be green,
 * and the rectangle's lines will be a thin yellow, of course.

(setf stumpwm:*screen-mode-line-format*     (list "%w|%g|" '(:eval (stumpwm:run-shell-command "date +%_I:%M:%S%p--%e-%a|tr -d [:cntrl:]" t))))
 * Specifically, I want mode line to display the result of having the shell create a string
 * of the concatenation of a space and the output of the 'date' program.

(defun update-mode-line "Update the mode-line sooner than usual."  (let ((screen (current-screen))) (when (screen-mode-line screen)     (redraw-mode-line-for (screen-mode-line screen) screen))))

#'update-mode-line :name "mode-line-updating" :thread (car (last (sb-thread:list-all-threads)))))
 * SBCL-specific; only runs if SBCL is running
 * Call update-mode-line in such and such a way. Borrowed from Luigi Panzeri.
 * 1) +sbcl (defparameter *mode-line-timer* (sb-ext:make-timer
 * Call a function given by the parameter every 30 seconds. This will increment the stuff in the mode-line.
 * 1) +sbcl (sb-ext:schedule-timer *mode-line-timer* 5 :repeat-interval 60 :absolute-p nil)

(setf *frame-number-map* "1234567890") ;doesn't seem to work right now
 * I just don't like zero indexing frames/windows. 0 is not next to 1
 * on the keyboard! See
 * 

(setf *mode-line-screen-position* :bottom)
 * Colors for the mode-line. Should be fairly self-explanatory.
 * "Where should the mode line be displayed? :top or :bottom."

(setf *mode-line-frame-position* :bottom)
 * "Where should the mode line be displayed? :top or :bottom."

(setf *mode-line-border-width* 0)
 * "How thick shall the mode line border be?"

(setf *mode-line-pad-x* 6)
 * "How much padding should be between the mode line text and the sides?"

(setf *mode-line-background-color* "black")
 * "Define mode line background color."

(setf *mode-line-foreground-color* "lightgreen")
 * "Define mode line foreground color."

(setf *mode-line-border-color* "lightyellow")
 * "Define mode line border color."

(setf (group-name (first (screen-groups (current-screen)))) "Firefox") (stumpwm::run-commands "gkill Emacs"		      "gnewbg Emacs") ;Remember, only one group exists by default
 * Call our first group Firefox, since that's what I usually use in it.


 * Functions, aliases, macros;;;;;;;;;;;;;;;;;;
 * Useful things. Usually defining new Stumpwm commands.
 * Useful things. Usually defining new Stumpwm commands.
 * Useful things. Usually defining new Stumpwm commands.

(defun shell-command (command) "Run a shell command and display output to screen. This must be used in a functional side-effects-free style! If a program does not exit of its own accord, Stumpwm might hang!"      (check-type command string)       (echo-string (current-screen) (run-shell-command command t)))

(define-stumpwm-command "shell-command" ((command :string "sh: " :string)) (check-type command string)  (shell-command command))

(define-stumpwm-command "conkeror"  (run-or-raise "firefox -chrome chrome://conkeror/content" :class "Firefox-bin"))
 * Leaving open the option to use Conkeror, a skin over Firefox.
 * Wish I could get sane tabbed browsing in it...

(define-stumpwm-command "show-battery"  (echo-string (current-screen) (run-shell-command "acpi" t)))
 * Query ACPI and show the battery's status.

(define-stumpwm-command "run-top"  (shell-command "top -b -n 1 -c -d 1"))
 * Briefly display a single frame from the top command and bind to a key.
 * Inspiration: 

(define-stumpwm-command "emacs"  (run-or-raise "emacs -T EMACS" :title "EMACS"))

(define-stumpwm-command "firefox"  (run-or-raise "firefox" :class "Firefox-bin"))

(define-stumpwm-command "image-viewer"  (run-or-raise X-IMAGE-VIEWER :class "Image-viewer"))

(define-stumpwm-command "quit"  (sb-ext:save-lisp-and-die "/home/gwern/bin/sbcl-stumpwm-core" :executable t :toplevel #'stumpwm:stumpwm))
 * Automatically dump a core file when we quit. .xinitrc will try to exec ~/bin/sbcl-stumpwm-core

(define-stumpwm-command "open-selection-browser"  (run-shell-command (cat X-WWW-BROWSER (get-x-selection))))
 * Web browsing commands
 * Get the X selection and order the GUI browser to open it. Presumably it is a HTTP address.

(define-stumpwm-command "wikipedia" ((search-string :string "wikipedia " :string)) (check-type search-string string)  (run-shell-command (cat "surfraw wikipedia " search-string)))
 * Ask user for a search string and search Wikipedia for it.

(define-stumpwm-command "wikipedia-selection"  (run-shell-command (cat "exec surfraw wikipedia " (get-x-selection))))
 * Get the X selection and search for it in Wikipedia.

(define-stumpwm-command "google" ((search-string :string "google " :string)) (check-type search-string string)  (run-shell-command (cat "surfraw google " search-string)))
 * Ask user for a search string and search Google for it.

(define-stumpwm-command "google-selection"  (run-shell-command (cat "exec surfraw google " (get-x-selection))))
 * Get the X selection and search for it through Google.

(define-stumpwm-command "wayback" ((search-string :string "wayback " :string)) (check-type search-string string)  (run-shell-command (cat "surfraw wayback " search-string)))
 * Ask user for a search string and search the Internet Archive/Wayback Machine for it.

(define-stumpwm-command "wayback-selection"  (run-shell-command (cat "exec surfraw wayback " (get-x-selection))))
 * Get the X selection (an HTTP address) and search for it in the Internet Archive.

(define-stumpwm-command "debpackages" ((search-string :string "debpackages " :string)) (check-type search-string string)  (run-shell-command (cat "surfraw debpackages " search-string)))
 * Ask user for a search string and look for a Debian package of the same name.

(define-stumpwm-command "debbugs" ((search-string :string "debbugs " :string)) (check-type search-string string)  (run-shell-command (cat "surfraw debbugs " search-string)))
 * Ask user for a search string and search the Debian BTS for a package of that name.


 * Startup programs;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 * What programs do we run on startup?
 * What programs do we run on startup?
 * What programs do we run on startup?

(screen-mode-line-mode (current-screen) t)
 * Great! Let's start mode-line for all screens!

(run-shell-command "xmodmap -quiet ~/.Xmodmap")
 * Do some key re-mapping; it is crucial that this get run first, because otherwise
 * the remapping later on of Insert and less to the prefix key simply will not work.

(run-shell-command "xrdb -load ~/.Xresources -quiet")
 * Apparently modifies some low-level GUI bits of X.

(run-shell-command "xsetroot -cursor_name left_ptr -gray -fg darkgreen -bg black -name root-window")
 * Change the background and pointer in X

(run-shell-command X-TERM)
 * Always good to have a shell

(run-shell-command "random-picture")
 * Have a nice, randomly selected image from my ~/pics directory made the root window background.
 * This is actually a shell script command; one needs the #!/bin/bash shebang in the shell script
 * or an explicit invocation of the shell, like "bash ~/bin/random-picture.sh".
 * (run-shell-command "bash xsetbg -border black -fork -type png -fit -onroot -fullscreen
 * ~/pics/`w=(*.png); n=${#w[@]}; echo ${w[RANDOM%n]}`") ;full version


 * This is an alternative- setting Electric Sheep as the background.
 * (run-shell-command "killall electricsheep 2>/dev/null; electricsheep --root 1 --nick gwern --zoom 1 --mplayer 1 --history 50")

(run-shell-command "unclutter -idle 1 -jitter 2 -root")
 * Run unclutter so the mouse hangs around no longer than needed.

(run-shell-command "xscreensaver-command -exit; killall xscreensaver 2>/dev/null; xscreensaver")
 * I use Xscreensaver as a screensaver. The first line makes sure any running Xscreensaver is killed.
 * The second run regardless of the success of the first & starts a background Xscreensaver daemon


 * Key binding;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 * Make the bindings more comfortable.
 * Make the bindings more comfortable.
 * Make the bindings more comfortable.

(set-prefix-key (kbd "<"))
 * Set the *prefix-key*. The main feature of note is the changing of
 * the escape sequence from 2 keys, C-t, to a single key,
 * and the mirroring of less with another key, so there are actually 2 equivalent escape keys.

(define-key *top-map* (kbd "Insert") '*root-map*) (define-key *root-map* (kbd "Insert") "next") ;;When in Stumpwm mode, act like hitting the prefix again would.
 * When not in Stumpwm mode, we want Insert to be bound to enter Stumpwm mode

(define-key *root-map* (kbd "&") "run-top")
 * You remember what run-top did, don't you? Defined in the functions section.

(define-key *root-map* (kbd "*") "show-battery")
 * Ditto for show-battery.

(define-key *root-map* (kbd "!") "shell-command")
 * Allow short displays of shell output. Don't run GUI programs through this! Overrides default.

(define-key *root-map* (kbd "b") (cat "colon " X-WWW-BROWSER " http://www.")) (define-key *root-map* (kbd "B") "open-selection-browser")
 * Browse somewhere with the GUI WWW browser.

(define-key *root-map* (kbd "C-s") (cat "colon " X-TERM " -e ssh "))
 * SSH somewhere in the default terminal.

(define-key *root-map* (kbd "X") (cat X-TERM "-e ssh -X root@127.0.0.1 aterm"))
 * More SSH.

(define-key *root-map* (kbd "c") X-TERM)
 * Terminals. S-c does a regular terminal, and S-C allows a single command.

(define-key *root-map* (kbd "C") (cat "colon " X-TERM " -e "))
 * S-C is supposed to ask for a command to run in a new terminal. So, we need the colon command,
 * combined with our default X terminal, and since that is Aterm, the option to run a command is '-e', so we need that as well.

(define-key *root-map* (kbd "d") "firefox") ;"firefox" is defined in functions
 * Firefox binding.

(define-key *root-map* (kbd "D") X-TERM-BROWSER)
 * Bindings for minimalistic CLI/GUI web browsers.

(define-key *root-map* (kbd "E") "exec emacsclient -a emacs -t EMACS") (define-key *root-map* (kbd "e") "emacs") ;"emacs" is defined in functions.
 * Shortcut for Emacs. Emacsclient is called, but it expects a filename.
 * This can be circumvented by instructing it to instead evaluate a Emacslisp expression -
 * the current one - says "open up a new frame on the current display device".
 * It has to be quoted or else sh will try to open up the lisp expression in a sub-shell
 * as a shell command. Neatly, if an Emacs isn't already running, then Emacsclient runs
 * $EDITOR, which points back to regular Emacs!

(define-key *root-map* (kbd "M-E") (cat "colon " X-TERM " -e nano"))
 * Shortcut for Nano

(define-key *root-map* (kbd "v") "image-viewer") ;;"image-viewer" is defined in functions.
 * Image viewer

(define-key *root-map* (kbd "s") "vsplit") (define-key *root-map* (kbd "S") "hsplit")
 * Apparently stump's default does something weird on my latop's screen. This should fix it.

(define-key *root-map* (kbd "x") "exec xpdf")
 * Binding for Xpdf

(define-key *root-map* (kbd "Print") "exec import -window root png:$HOME/xwd-$(date +%s)$$.png")
 * Make prtscreen work, as long as in command mode. "import" is an Imagemagick command.


 * 'Swounds, I'm gonna need a separate section just for Surfraw shortcuts.
 * Anyway, the model for these (thanks to aon) is to bind a key to "colon exec surfraw wikipedia "
 * (or whatever the site is) note the space. If the space isn't there, then the user will need to
 * manually add a space, which is not good. In the shell, one can omit the surfraw command, but
 * not in stumpwm, as stumpwm's PATH currently does not seem to include the directory with the elvi in it.
 * List of useful surfraw elvi follows:
 * amazon bbcnews cia cite cnn debbugs debcontents deblists deblogs debpackages debpts deja dmoz ebay etym
 * freshmeat google imdb rfc rhyme slashdot sourceforgen translate

(define-key *root-map* (kbd "t") "wikipedia") (define-key *root-map* (kbd "T") "wikipedia-selection")
 * Surfraw keybindings.

(define-key *root-map* (kbd "g") "google ") (define-key *root-map* (kbd "G") "google-selection")

(define-key *root-map* (kbd "y") "wayback ") (define-key *root-map* (kbd "Y") "wayback-selection")

(define-key *root-map* (kbd "u") "debbugs ") (define-key *root-map* (kbd "U") "debpackages ")


 * Groups;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 * Change various group things.
 * Change various group things.
 * Change various group things.


 * Refer to user.lisp
 * Currently, when one hits S-g, one enters group-mode, wherein the keys
 * are rebound to serve as group movement commands. I might want to change this.
 * (define-key (kbd "`") '*groups-map*)

(define-key *root-map* (kbd "~") "vgroups") (define-key *root-map* (kbd "quoteleft") "gprev")
 * Two quick and easy shortcuts - one to switch rapidly between groups and another to list them.
 * Anything more elaborate can be done by going through group-mode.

(defun move-emacs (window) "Move emacs to the Emacs group."       (if (string= (window-class window) "Emacs") (stumpwm::run-commands "gmove Emacs"))      (remove-hook stumpwm::*map-window-hook* 'move-emacs)       ) (stumpwm:add-hook *map-window-hook* 'move-emacs)
 * If the current window is Emacs, let's ban it to the Emacs group. This loses a bit of flexibility,
 * but it means startups will be more pleasant. The remove-hook should mean Emacs gets moved only once.
 * And yes, you do actually need a defun and a add-hook to guarantee sticking an application into a particular group.
 * TODO: generalize this

(stumpwm::run-commands "gselect Emacs" "emacs") ;;Because of the previous defun and hook, the emacs will be moved to the right group automatically
 * Automatically open up another virtual desktop; in a surprising show of originality, I will name it Emacs,
 * since that's what I usually use in it.

(load "/home/gwern/bin/paste.lisp")
 * Pasting;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 * Loads in some functions to allow multiple registers (think Emacs-style). Binds to numerical keys.
 * See 
 * Loads in some functions to allow multiple registers (think Emacs-style). Binds to numerical keys.
 * See 


 * I don't quite understand this stuff yet. It's ripped from Luigi Panzeri's .stumpwmrc, and he's doing some interesting stuff
 * which seems powerful but which I haven't yet figured out what it is doing, much less why.
 * ____
 * / ___|_ __ ___  _   _ _ __   ___
 * | | _| '__|/ _ \| | | | '_ \ / __|
 * | |_| | | | (_) | |_| | |_) |\__ \
 * \____|_|  \___/ \__,_| .__/ |___/
 * |_|

(defun find-group-by-name (name) (find name (screen-groups (current-screen)) :test #'string-equal :key #'group-name))

(defun place-windows-on-group (group &key class) (lambda (win) (when (string-equal (window-class win) class)    (move-window-to-group win group))))

(defun place-windows-on-frame (group frame &key class) (lambda (win) (when (string-equal (window-class win) class)    (move-window-to-group win group)     (setf (window-frame win) frame)     (echo-string (current-screen) (format nil "Window ~a placed in group ~a" (window-name win) (group-name group))))))
 * (sync-frame-windows group frame)

(defun horiz-split-frame-and-resize (group fraction) (horiz-split-frame group) (let ((frame (tile-group-current-frame group))) (resize-frame group                frame                 (truncate (* (- (* 2 fraction) 1) (frame-width frame)))                 'width)))

(defun vert-split-frame-and-resize (group fraction) (vert-split-frame group) (let ((frame (tile-group-current-frame group))) (resize-frame group                frame                 (truncate (* (- (* 2 fraction) 1) (frame-height frame)))                 'height)))

(defmacro horizontally (&rest frame-specs) `(let ((accum 1)       (frame-specs (sort ',frame-specs (lambda (el1 el2) (cond                                               ((not (numberp el1)) nil)                                                ((not (numberp el2)) t)))))) (dolist (frame-spec (butlast frame-specs))     (destructuring-bind (fraction window-queries) frame-spec (when (numberp fraction)         (decf accum fraction)) (horiz-split-frame-and-resize group (if (numberp fraction) fraction accum)) (dolist (window-query window-queries)         (ecase (car window-query) (:class (add-hook *map-window-hook* (place-windows-on-frame group (tile-group-current-frame group) :class (cadr window-query)))))))       (focus-frame-sibling group)) (destructuring-bind (fraction window-queries) (car (last frame-specs))     (declare (ignore fraction))      (dolist (window-query window-queries) (ecase (car window-query)         (:class (add-hook *map-window-hook* (place-windows-on-frame group (tile-group-current-frame group) :class (cadr window-query)))))))))

(defmacro define-group-layout (group-name layout-spec) `(let* ((group (or (find-group-by-name ,group-name)                   (add-group (current-screen) ,group-name))))

,layout-spec))

; (horizontally  ;     (1/4 ((:class "Amsn")))   ;  (:fill ((:class "Chatwindow")))))
 * (define-group-layout "Chat"
 * EOF