source: project/wiki/wmiirc @ 12906

Last change on this file since 12906 was 12906, checked in by sjamaan, 11 years ago

Change the URI at which the official documentation of wmii lives.... Cool URLs don't change! :)

File size: 27.9 KB
Line 
1[[tags: egg]]
2
3== wmiirc
4
5[[toc:]]
6
7=== Description
8
9A library for writing configuration scripts for [[http://wmii.suckless.org|wmii, window manager improved 2]].
10
11See also the [[wmiirc snippets]] page for useful code snippets you can
12use in your own wmiirc scripts.
13
14=== Author
15
16[[Peter Bex]]
17
18=== Requirements
19
20Requires the [[http://www.call-with-current-continuation.org/eggs/9p|9p]] egg.
21
22Works with wmii 3.6 (and possibly 3.5) only.
23
24=== Download
25
26[[http://www.call-with-current-continuation.org/eggs/wmiirc.egg|wmiirc.egg]]
27
28=== Documentation
29
30[[http://wmii.suckless.org|wmii]] is a minimalist windowmanager for
31the X window system that, instead of implementing a lot of policy in
32the WM, allows you to control it completely through a virtual
33filesystem it exports over the [[9p]] protocol. Because of this, you
34can script it using any language or tool that can speak this protocol
35and define (almost) any behaviour you want.
36
37This egg is an attempt to make an abstraction that lets you write
38scripts that can control wmii without having to study the structure of
39the 9p filesystem that wmii exports.  Instead, you can do everything
40by calling procedures from this egg.  Of course, if you know the
41filesystem structure you can still choose to access the filesystem
42directly if you need to do something extreme.
43
44==== Concepts
45
46Because wmii works slightly different than most other window managers,
47it is useful to start by exploring its fundamental concepts.  There's
48an official guide that explains these concepts at
49[[http://www.suckless.org/wmii/guide.html]] but it is not very complete
50at the time of this writing.
51
52First off, wmii is a so-called ''dynamic'' window manager.  This means
53it manages the windows for you, so you don't have to bother about
54placing them on your screen.  In default mode, it will divide the
55screen up in equal parts and tile the windows so they are not
56obscured.  However, it also has a ''floated'' mode, which is the only
57mode classic window managers support.  This will simply place the
58windows somewhere on the screen such that they can overlap.  You will
59have to drag them around and/or resize them manually (or write a smart
60script that can position them sanely).
61
62===== Tags and views
63
64wmii manages windows (or ''clients'' in X speak) by ''tagging'' them.
65Any window can have several tags, but it always displays the contents
66of only one tag on the screen.  This is called a ''view'' on that tag.
67This feature provides a superset of the functionality that other
68window managers offer with ''virtual desktops''.  Because windows can
69have multiple tags, it is possible for one window to show up in
70multiple views, effectively causing it to be "sticky" for only a
71selected number of views.
72
73===== Modes
74
75As explained above, wmii supports dynamic management as well as
76floated window management.  Floating windows all live in a special tag
77sometimes identified by the name '~' (tilde).  In dynamic mode there
78are three "submodes".  In 'default' mode the windows are tiled, or
79divided equally across the screen.  When a new window is created, the
80other windows are made smaller to accommodate for the new one, which
81is given an equal amount of space as all the other windows, and the
82window is placed such that it does not obscure any of the other
83windows.  In 'stacked' mode, all windows are placed behind eachother
84in a staircased fashion so '''only''' their titlebars show.  The
85window that has focus is placed in front of all the others, so it
86takes up almost all of your screen.  Clicking on any titlebar sends
87that window to the front, and restacks such that all other windows'
88titlebars are still visible.  In 'maximized' mode you only see one
89window with its titlebar.
90
91===== States
92
93Individual windows can also have different states.  When a window is
94in the 'fullscreen' state, '''all''' window decoration and other stuff
95is hidden so your entire screen is used by one window of one application.
96When a window has the 'urgent' state, it has its "urgent hint" set, which
97is a hint to the window manager that this window's state demands immediate
98attention from the user (for example, in an IM client a private message
99may have arrived).  Wmii can take action when this state is set and it can
100distinguish between client-requested urgency and manager-requested urgency.
101
102===== Columns
103
104The screen is further divided up into columns.  When you first start wmii,
105the screen has only one column so you don't see it.  However, when you send
106a window to the right or the left, it will create a new column it will live
107in from then on.  The first column will be resized so the columns can fit
108next to eachother.  Wmii allows you to define rules what the sizes of these
109columns will be.  Each column has its own mode, so you can have one column
110maximized or stacked while the column next to it is in tiled mode.
111
112===== Bars and tabs
113
114The bottom of the screen contains a bar, which is actually ''two'' bars: one
115on the left and one on the right (''lbar'' and ''rbar'').  These bars consist
116of ''tabs''.  Tabs can contain text in a given color and are clickable.
117Their name does not have to match their text contents, but it is advisable
118to keep these matched for your own sanity.  In the default config, the left
119tab shows a list of available tags/views, with the current one highlighted.
120When you click a tab, a view on the corresponding tag is shown.  By default
121the right bar shows a status that is continuously updated with the current
122time and system load.
123
124===== Events
125
126Whenever anything happens in wmii, an event is fired which your wmiirc
127can catch and act upon.  Events are fired when a key is pressed (but
128only when it is grabbed by the WM, otherwise it goes to applications),
129when a window is (de)selected, when a tag is (de)selected, when a tag
130is created/destroyed etc.  The exact events are listed with the
131{{wmii:event-handlers}} procedure.
132
133===== Special names and limitations
134
135wmii reserves a couple of names and syntaxes, which means you can't
136use arbitrary names for tags, tabs and some other things.  It uses the
137plus symbol (+) as a separator for tag names.  This cannot be escaped
138in any way, which means the + can simply not be used inside names.
139The special name ''sel'' is reserved for the currently selected
140tag/view/client etc. This has an alias as the exclamation mark, but
141its use is deprecated.  Contents of tabs can be prefixed with three
1426-digit hexadecimal numbers which are prefixed with a pound sign (#).
143If they are, this indicates the colors of that tab.  This egg tries to
144take care of doing the formatting of this so you can simply pass
145integer values as colorcodes instead.  Spaces are not allowed in
146several names either.  It's probably safest to avoid all these special
147characters and names altogether.
148
149==== Initialization
150
151To get a connection to the server, call the following:
152
153  procedure: (wmii:connect [inport outport])
154
155If you provide an inport and outport, it will connect to a 9p server
156on those input/output ports.  If you do not provide them, it will try
157to connect to the wmii 9p server on the default location, namely a unix
158domain socket named {{/tmp/ns.USERNAME.DISPLAY/wmii}}, where USERNAME
159is your Unix username and DISPLAY is the current X display string.
160
161After initializing, you can set up column rules, tag rules and event
162handlers.  After having done this, you can enter the event loop using
163
164  procedure: (wmii:event-loop [kill-others])
165
166This procedure will only return when another wmiirc wants to take over
167from the current one.  The {{kill-others}} parameter tells wmiirc to
168tell other wmiirc scripts (whether written using this egg or not) to
169quit.  It defaults to {{#t}}.
170
171==== wmii operations
172
173  procedure: (wmii:quit)
174
175Tells wmii to quit.
176
177  procedure: (wmii:exec cmdline)
178
179Tells wmii to execute the given commandline, replacing the wmii
180process.  This can be used to change to a different window manager.
181
182  procedure: (wmii:global-settings)
183
184Returns an alist of the current global settings.
185
186  procedure: (wmii:global-settings-set! alist)
187
188Change the global settings.  Example:
189
190<enscript highlight=scheme>
191(wmii:global-settings-set!
192 `((font . "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*")
193   (focuscolors . (#xffffff #x285577 #x4c7899))
194   (normcolors . (#x888888 #x222222 #x333333))
195   (grabmod . "Mod1")
196   (border . "1")))
197</enscript>
198
199This sets the default font (used in titlebars, for example) to the
200one in the string, sets the colors of a window that is focused to the
201given colorcodes in {{focuscolors}}, the default colors to the one in
202{{normcolors}} and grabs Mod1 for dragging windows around.  The border
203thickness is set to one pixel.
204
205==== Column rules
206
207You can define the percentage of the screen each column should take up
208by setting up column rules.  This can be done per view, using a simple
209alist and the following procedure:
210
211  procedure: (wmii:colrules-set! alist)
212
213The keys of the alist are strings that are interpreted by wmii as a
214regular expression of view names on which the column rules should
215apply.  The values of the alist are integers or lists of integers
216which represent percentages of the screen width the columns can take.
217The percentages apply to the columns in the same order, from left to
218right.
219
220Example:
221
222<enscript highlight=scheme>
223  (wmii:colrules-set! '(("www" . (20 80))
224                        ("email" . (10 20 70))
225                        ("graphics" . 100) ;; can also be (100)
226                        (".*" . (30 50 20))))
227</enscript>
228
229You can request the current column rules with the following procedure:
230
231  procedure: (wmii:colrules)
232
233This returns an alist of the same type as accepted by wmii:colrules-set!.
234
235==== Tag rules
236
237Tag rules work much like column rules, except they specify which
238tags a client should get when it's first created.
239
240  procedure: (wmii:tagrules-set! alist)
241
242The alist here takes again strings as keys which are interpreted as
243regexes by wmii.  The values are either strings or lists of strings
244which are taken to be tagnames. Example:
245
246<enscript highlight=scheme>
247  (wmii:tagrules-set! `(("XMMS.*" . ("music" "~"))
248                        ("display.*" . ("graphics" "~"))
249                        ("Gimp.*" . ("graphics" "~"))
250                        ("xjump.*" . ("games" "~"))
251                        ("MPlayer.*" . "~")
252                        ("VICE.*" . ("games" "~"))
253                        (".*" . "sel") ;; Default to current tag
254                        (".*" . "1"))) ;; If no tag exists yet, start with '1'
255</enscript>
256
257Just like colrules, tagrules can be listed:
258
259  procedure: (wmii:tagrules)
260
261Returns an alist that looks just like the one from {{wmii:tagrules-set!}}.
262
263==== Event handlers
264
265The core of wmiirc script writing is in the event handlers.  You can register
266those with this procedure:
267
268  procedure: (wmii:event-handlers-set! alist [grab-keys])
269
270The alist has keys that are either simply symbols that name the event
271or lists that provide a full match for the incoming event.  The first
272rule that matches an incoming event is used, the others are ignored.
273The values of the alist are lambdas which handle the event.  The
274{{grab-keys}} parameter defaults to {{#t}} and indicates if key
275handlers should be filtered from the event handlers and the keys used
276by them should be grabbed.  If a key is not grabbed, it will never be
277visible by the wmiirc script; it will be passed to the client directly
278without being passed to the script by wmii.
279
280The events that you can expect are as follows:
281
282; {{(create-tag TAGNAME)}} : The tag with the name {{TAGNAME}} has just been created.
283
284; {{(destroy-tag TAGNAME)}} : The tag with name {{TAGNAME}} has just been destroyed.
285
286; {{(focus-tag TAGNAME)}} : The focus was changed to the tag with name {{TAGNAME}}
287
288; {{(unfocus-tag TAGNAME)}} : The tag with name {{TAGNAME}} which had focus is now not in focus anymore.
289
290; {{urgent CLIENT CLIENT-REQUEST?}} : The client with identifier {{CLIENT}} just got the ''urgency hint'' set. {{CLIENT-REQUEST?}} is #{{t}} if the client requested it, {{#f}} if the window manager did.
291
292; {{not-urgent CLIENT CLIENT-REQUEST?}} : The client with identifier {{CLIENT}} just got the ''urgency hint'' removed. {{CLIENT-REQUEST?}} is #{{t}} if the client removed it, {{#f}} if the window manager did.
293
294; {{urgent-tag TAGNAME CLIENT-REQUEST?}} : The tag with name {{TAGNAME}} has a client which just got the ''urgency hint'' set.  {{CLIENT-REQUEST}} is {{#t}} if the client requested it, {{#f}} if the urgency hint was set by the window manager itself.
295
296; {{not-urgent-tag TAGNAME CLIENT-REQUEST?}} : The tag with name {{TAGNAME}} has a client which just lost the ''urgency hint''.  {{CLIENT}} is {{#t}} if the client removed it, {{#f}} if the urgency hint was removed by the window manager itself.
297
298; {{left-bar-click BUTTON TAB}} : The user clicked on the left bar. {{BUTTON}} is an integer which indicates the mouse button the user pressed (1 = left, 2 = middle, 3 = right).  {{TAB}} is the name of the tab on which was clicked.
299
300; {{right-bar-click BUTTON TAB}} : The user clicked on the right bar. {{BUTTON}} is an integer which indicates the mouse button the user pressed (1 = left, 2 = middle, 3 = right).  {{TAB}} is the name of the tab on which was clicked.
301
302; {{client-mouse-down CLIENT BUTTON}} : The user pressed a mouse button while his mouse cursor was on the titlebar of a window. {{CLIENT}} indicates the client on which was clicked, {{BUTTON}} is an integer which indicates the mouse button the user pressed (1 = left, 2 = middle, 3 = right).
303
304; {{client-mouse-click CLIENT BUTTON}} : The user completed a mouse click on the titlebar of a window (he did not leave the titlebar before releasing the button).  {{CLIENT}} indicates the client on which was clicked, {{BUTTON}} is an integer which indicates the mouse button the user pressed (1 = left, 2 = middle, 3 = right).
305
306; {{(key keys ...)}} : A key was pressed.  The exact key pressed is encoded as several strings with key names.  Usually it is easiest to handle the keys with rest arg notation to capture them in a list.
307
308See the [[#Example|example section]] for a good example of how to use
309these events.
310
311You can also use the following procedure to get the current event handlers:
312
313  procedure: (wmii:event-handlers)
314
315Note that this procedure can not return event handlers in other processes.
316It's simply a getter for the current wmiirc instance's list of event handlers.
317
318=== Keys
319
320  procedure: (wmii:grabbed-keys)
321
322Get a list of currently grabbed keys.
323
324  procedure: (wmii:grabbed-keys-set! keys)
325
326Sets the keys grabbed by wmii.  {{keys}} is a list of key descriptions.
327Keys must be grabbed or they won't be passed to the wmiirc event loop.
328Example:
329
330<enscript highlight="scheme">
331  (wmii:grabbed-keys-set! '(("Mod1" "x")
332                            ("Mod2" "Space")
333                            ("Mod1" "Shift" "Space")))
334</enscript>
335
336This grabs the key combinations Mod1-x, Mod2-space and Mod1-shift-space.
337Key names of "special" keys are always capitalized in wmii.  Normal literal
338keys like the x in the example are always lower case.  If you would like
339to hook shift-x, that would not be ("X"), but ("Shift" "x").
340
341  procedure: (wmii:key-code->string)
342  procedure: (wmii:string->key-code)
343
344Translate a chicken-wmiirc keycode to a string that can be written to wmii's
345{{/keys}} file.  Example:
346
347  (wmii:key-code->string '("Mod1" "Shift" "x")) => "Mod1-Shift-x"
348  (wmii:string->keycode "Mod1-Shift-x") => ("Mod1" "Shift" "x")
349
350=== Navigating
351
352  procedure: (wmii:goto-tag tag)
353
354Switch the view to the named {{tag}}.
355
356  procedure: (wmii:navigate-to direction [tag])
357
358Navigate to the given {{direction}} in the given {{tag}}.  Tag
359defaults to "sel", the current tag.  {{where}} can be "up", "down",
360"left", "right" or "toggle".  If one of the directions, the client
361above, below, to the left or to the right of the current client is
362selected.  If the direction is toggle, clients in float mode are
363selected if currently a client in normal mode is selected, or the
364other way around.  If tag is not the current tag, the currently
365selected client on that tag is changed, but nothing happens in the
366current view, unless the current view just happens to be a view on
367that tag.
368
369  procedure: (wmii:send-to direction [client] [tag])
370
371Send the given {{client}} (defaults to "sel", the currently selected
372client) into the given {{direction}}, as described above.  If {{tag}}
373is given, the client is sent to the given direction on that tag.  It
374is ''not'' sent to that tag.
375
376=== Tags
377
378  procedure: (wmii:tags)
379 
380This procedure returns a list of all the tags known to wmii, as strings.
381
382  procedure: (wmii:tag-settings-set! alist [tag])
383
384Change the settings for the named {{tag}}, which defaults to "sel",
385the current tag.  {{alist}} is an alist with setting names (strings)
386as keys, and setting lists as values. Example:
387
388  (wmii:tag-settings-set! '(("colmode" . ("sel" "stack"))))
389
390This sets the current tag's column mode to stacked.
391 
392  procedure: (wmii:tag-settings [tag])
393
394Returns an alist of the settings for the named {{tag}}.  {{tag}} defaults
395to {{"sel"}}, that is the current tag.
396
397=== Bars
398
399  procedure: (wmii:tabs bar)
400
401Return a list of all tabs on the {{bar}}.  {{bar}} can be {{"lbar"}}
402(the left bar) or {{"rbar"}} (the right bar).
403
404  procedure: (wmii:write-tab bar tab contents [colors])
405
406Change the string {{contents}} of a {{tab}} on the indicated
407{{bar}}. Creates the tab if it doesn't exist yet.  If {{colors}}
408is given and not {{#f}} it should be a list of three numbers which
409represent in hexadecimal the color values of the foreground,
410background and border, respectively.
411
412Example:
413
414  (wmii:write-tab "lbar" "hello" "hello there")
415
416Creates a tab called "hello" on the left bar, which displays the
417string "hello there".
418
419  procedure: (wmii:destroy-tab bar tab)
420
421Destroy {{tab}} on {{bar}}.
422
423=== Clients
424
425  procedure: (wmii:client=? client1 client2)
426
427Are two clients one and the same?  Currently clients are represented
428as simple strings, the way wmii returns them, but in the future
429clients may have more information-rich representations, so always use
430this to compare them to be forwards-compatible.  These "opaque" client
431objects can be obtained by event handlers from the various events that
432operate on a client, or by {{wmii:clients}}, for example.
433
434  procedure: (wmii:clients [tag ...])
435
436Returns a list of all the clients that have any of the named tags.
437If no tags are given, returns all clients.
438
439  procedure: (wmii:client-tags [client])
440
441Return a list of all tags on {{client}}.  Defaults to the
442currently selected client ("sel").
443
444  procedure: (wmii:client-tags-set! tags [client])
445
446Set the {{tags}} (a list of strings) on the {{client}}.
447
448=== Low-level procedures
449
450If you would like access to the 9p filesystem exported by wmii, you
451can use the following procedures:
452
453  procedure: (wmii:write file data)
454
455Write the string contents of {{data}} to the named {{file}}.  If the
456file does not exist, it is created.
457
458  procedure: (wmii:read file)
459
460Read the given {{file}} into a string.
461
462  procedure: (wmii:read-lines file)
463
464Read the given {{file}} line by line and create a list with an entry
465per line.
466
467  procedure: (wmii:directory path)
468
469Show the directory contents of the named {{path}}.
470
471 
472=== Example
473
474This example simply translates the default wmiirc script that's shipped
475with wmii from shell to Chicken:
476
477<enscript highlight=scheme>
478#!/usr/pkg/bin/csi -s
479
480(use wmiirc srfi-18)
481
482(wmii:connect)
483
484(define modkey "Mod2")
485
486(define directions
487  `((up . "k")
488    (down . "j")
489    (left . "h")
490    (right . "l")))
491
492(define wmii-normcolors  '(#x888888 #x222222 #x333333))
493(define wmii-focuscolors '(#xffffff #x285577 #x4c7899))
494
495(define wmii-background #x333333)
496(define wmii-font "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*")
497
498(define (wmii9menu options . rest)
499  (let-optionals rest ((default #f))
500    (receive (in out pid)
501             (process
502              "wmii9menu"
503              `(,@(if default (list "-initial" default) '())
504                "-sf" ,(wmii:color->string (first wmii-focuscolors))
505                "-sb" ,(wmii:color->string (second wmii-focuscolors))
506                "-nf" ,(wmii:color->string (first wmii-normcolors))
507                "-nb" ,(wmii:color->string (second wmii-normcolors))
508                "-font" ,wmii-font
509                ,@options))
510             (close-output-port out)
511             (let ((chosen (read-line in)))
512               (close-input-port in)
513               (and (string? chosen) chosen)))))
514
515(define (dmenu options . rest)
516  (receive (in out pid)
517           (process
518            "dmenu"
519            `("-b"
520              "-sf" ,(wmii:color->string (first wmii-focuscolors))
521              "-sb" ,(wmii:color->string (second wmii-focuscolors))
522              "-nf" ,(wmii:color->string (first wmii-normcolors))
523              "-nb" ,(wmii:color->string (second wmii-normcolors))
524              "-fn" ,wmii-font))
525           (display (string-join options "\n") out)
526           (close-output-port out)
527           (let ((chosen (read-line in)))
528             (close-input-port in)
529             (and (string? chosen) chosen))))
530
531(define client-menu
532 (let ((last-option "nonexistingoption"))
533   (lambda (client)
534     (and-let* ((option (wmii9menu '("Nop" "Delete" "Fullscreen") last-option)))
535       (cond
536        ((string=? option "Delete") (wmii:kill client))
537        ((string=? option "Fullscreen") (wmii:change-state "Fullscreen" #t client)))
538       (set! last-option option)))))
539
540(define wmii-term "xterm")
541
542(wmii:colrules-set! `((".*" . (58 42))))
543
544(wmii:tagrules-set! `(("XMMS.*" . "~")
545                      ("MPlayer.*" . "~")
546                      (".*" . "sel")
547                      (".*" . "1")))
548
549;; We need to do this in order to avoid getting lots of zombie processes
550(define (run . args) (process-wait (process-fork (lambda () (apply process-run args)))))
551
552(define status
553  (let ((status-thread #f))
554    (lambda ()
555      (and status-thread (thread-terminate! status-thread))
556      (set! status-thread
557            (thread-start!
558             (make-thread
559              (lambda ()
560                (let loop ()
561                  (wmii:write-tab "rbar" "status"
562                                  (with-input-from-pipe "echo -n $(uptime | sed 's/.*://; s/,//g') '|' $(date)" read-string))
563                  (thread-sleep! 1)
564                  (loop)))))))))
565
566(wmii:event-handlers-set!
567 `((create-tag
568    . ,(lambda (event tag) (wmii:write-tab "lbar" tag tag wmii-normcolors)))
569   (destroy-tag
570    . ,(lambda (event tag) (wmii:destroy-tab "lbar" tag)))
571   (focus-tag
572    . ,(lambda (event tag)
573         (if (member tag (wmii:tabs "lbar"))
574             (wmii:write-tab "lbar" tag tag wmii-focuscolors))))
575   (unfocus-tag
576    . ,(lambda (event tag)
577         (if (member tag (wmii:tabs "lbar"))
578             (wmii:write-tab "lbar" tag tag wmii-normcolors))))
579   (urgent-tag
580    . ,(lambda (event tag client?) (wmii:write-tab "lbar" tag (string-append "*" tag))))
581   (not-urgent-tag
582    . ,(lambda (event tag client?) (wmii:write-tab "lbar" tag tag)))
583   (left-bar-click
584    . ,(lambda (event button tab) (wmii:goto-tag tab)))
585   (client-mouse-down
586    . ,(lambda (event client button)
587         (case button
588           ((3) (client-menu client)))))
589   ((key ,modkey "Control" "t")
590    . ,(let ((prev #f))
591         (lambda _
592           (let ((keys (wmii:grabbed-keys)))
593             (if prev
594                 (begin (wmii:grabbed-keys-set! prev)
595                        (set! prev #f))
596                 (begin (set! prev keys)
597                        (wmii:grabbed-keys-set! `((,modkey "Control" "t")))))))))
598   ((key ,modkey "space")
599    . ,(lambda _ (wmii:navigate-to "toggle")))
600   ((key ,modkey "d")
601    . ,(lambda _ (wmii:tag-settings-set! '(("colmode" . ("sel" "default"))))))
602   ((key ,modkey "s")
603    . ,(lambda _ (wmii:tag-settings-set! '(("colmode" . ("sel" "stack"))))))
604   ((key ,modkey "m")
605    . ,(lambda _ (wmii:tag-settings-set! '(("colmode" . ("sel" "max"))))))
606   ((key ,modkey "a")
607    . ,(lambda _
608         (and-let* ((action (dmenu (append
609                                 `("rehash" "exec" "status" "quit")
610                                 (proglist (string-split (getenv "WMII_CONFPATH") ":"))))))
611           (cond
612            ((string=? action "rehash") (update-programs))
613            ((string-prefix? "exec " action)
614             (wmii:exec (string-drop action 5)))
615            ((string=? action "status") (status))
616            ((string=? action "quit")
617             (wmii:quit)
618             (exit))
619            (else (run (sprintf "env PATH=${WMII_CONFPATH}:${PATH} ~A" action)))))))
620   ((key ,modkey "p")
621    . ,(lambda _
622         (and-let* ((program (dmenu programs))) (run program))))
623   ((key ,modkey "t")
624    . ,(lambda _
625         (and-let* ((tag (dmenu (wmii:tags)))) (wmii:goto-tag tag))))
626   ((key ,modkey "Return")
627    . ,(lambda _ (run wmii-term)))
628   ((key ,modkey "Shift" "space")
629    . ,(lambda _ (wmii:send-to "toggle")))
630   ((key ,modkey "f")
631    . ,(lambda _ (wmii:change-state "Fullscreen" 'toggle)))
632   ((key ,modkey "Shift" "c")
633    . ,(lambda _ (wmii:kill)))
634   ((key ,modkey "Shift" "t")
635    . ,(lambda _
636         (and-let* ((tag (dmenu (wmii:tags)))) (wmii:client-tags-set! (list tag)))))
637   ,@(map (lambda (x)
638            `((key ,modkey ,(cdr x))
639              . ,(lambda _ (wmii:navigate-to (->string (car x))))))
640          directions)
641   ,@(map (lambda (x)
642            `((key ,modkey "Shift" ,(cdr x))
643              . ,(lambda _ (wmii:send-to (->string (car x))))))
644          directions)   
645   ,@(map (lambda (x)
646            `((key ,modkey ,(->string x))
647              . ,(lambda _ (wmii:goto-tag x))))
648          (iota 10))
649   ,@(map (lambda (x)
650            `((key ,modkey "Shift" ,(->string x))
651              . ,(lambda _ (wmii:client-tags-set! (list (->string x)))))) (iota 10))))
652
653(wmii:global-settings-set!
654 `((font . ,wmii-font)
655   (focuscolors . ,wmii-focuscolors)
656   (normcolors . ,wmii-normcolors)
657   (grabmod . ,modkey)
658   (border . "1")))
659
660(define (proglist path)
661  (sort!
662   (delete-duplicates!
663    (flatten
664     (map (lambda (dir)
665            (if ((conjoin directory? file-execute-access? file-read-access?) dir)
666                (map pathname-strip-directory
667                     (find-files dir (conjoin (complement directory?) file-execute-access?) cons '() 0))
668                '()))
669          path))
670    string=?)
671   string<?))
672
673(define programs '())
674(define (update-programs)
675  (thread-start!
676   (make-thread
677    (lambda () (set! programs (proglist (string-split (getenv "PATH") ":")))))))
678(update-programs)
679
680(let ((curtag (wmii:tag)))
681  (for-each (cut wmii:destroy-tab "lbar" <>) (wmii:tabs "lbar"))
682  (for-each (lambda (t)
683              (if (string=? curtag t)
684                  (wmii:write-tab "lbar" t t wmii-focuscolors)
685                  (wmii:write-tab "lbar" t t wmii-normcolors)))
686            (wmii:tags)))
687
688(run (sprintf "xsetroot -solid '~A'" (wmii:color->string wmii-background)))
689
690(status)
691(wmii:event-loop)
692</enscript>
693
694For some other cool snippets, have a look at the [[wmiirc snippets]] page.
695
696=== Changelog
697
698* 0.3 Improvement in {{clients}} procedure
699* 0.1 Initial release
700
701=== License
702
703  Copyright (c) 2008, Peter Bex
704  All rights reserved.
705 
706  Redistribution and use in source and binary forms, with or without
707  modification, are permitted provided that the following conditions are
708  met:
709 
710  Redistributions of source code must retain the above copyright
711  notice, this list of conditions and the following disclaimer.
712 
713  Redistributions in binary form must reproduce the above copyright
714  notice, this list of conditions and the following disclaimer in the
715  documentation and/or other materials provided with the distribution.
716 
717  Neither the name of the author nor the names of its contributors may
718  be used to endorse or promote products derived from this software
719  without specific prior written permission.
720 
721  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
722  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
723  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
724  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
725  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
726  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
727  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
728  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
729  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
730  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
731  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
732  OF THE POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.