source: project/wiki/wmiirc @ 8662

Last change on this file since 8662 was 8662, checked in by sjamaan, 13 years ago

Link to the official docs, too

File size: 28.2 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.  The
48official documentation lives at
49[[http://www.suckless.org/wiki/wmii/docs]] 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
161'''important''' wmiirc does ''not'' support multiple threads calling
162wmiirc procedures.  It also does not support multiple processes doing
163this, so if you fork you'll need to call (wmii:connect) first in the
164child process (or the parent process) to create a new connection before
165doing anything else.
166
167After initializing, you can set up column rules, tag rules and event
168handlers.  After having done this, you can enter the event loop using
169
170  procedure: (wmii:event-loop [kill-others])
171
172This procedure will only return when another wmiirc wants to take over
173from the current one.  The {{kill-others}} parameter tells wmiirc to
174tell other wmiirc scripts (whether written using this egg or not) to
175quit.  It defaults to {{#t}}.
176
177==== wmii operations
178
179  procedure: (wmii:quit)
180
181Tells wmii to quit.
182
183  procedure: (wmii:exec cmdline)
184
185Tells wmii to execute the given commandline, replacing the wmii
186process.  This can be used to change to a different window manager.
187
188  procedure: (wmii:global-settings)
189
190Returns an alist of the current global settings.
191
192  procedure: (wmii:global-settings-set! alist)
193
194Change the global settings.  Example:
195
196<enscript highlight=scheme>
197(wmii:global-settings-set!
198 `((font . "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*")
199   (focuscolors . (#xffffff #x285577 #x4c7899))
200   (normcolors . (#x888888 #x222222 #x333333))
201   (grabmod . "Mod1")
202   (border . "1")))
203</enscript>
204
205This sets the default font (used in titlebars, for example) to the
206one in the string, sets the colors of a window that is focused to the
207given colorcodes in {{focuscolors}}, the default colors to the one in
208{{normcolors}} and grabs Mod1 for dragging windows around.  The border
209thickness is set to one pixel.
210
211==== Column rules
212
213You can define the percentage of the screen each column should take up
214by setting up column rules.  This can be done per view, using a simple
215alist and the following procedure:
216
217  procedure: (wmii:colrules-set! alist)
218
219The keys of the alist are strings that are interpreted by wmii as a
220regular expression of view names on which the column rules should
221apply.  The values of the alist are integers or lists of integers
222which represent percentages of the screen width the columns can take.
223The percentages apply to the columns in the same order, from left to
224right.
225
226Example:
227
228<enscript highlight=scheme>
229  (wmii:colrules-set! '(("www" . (20 80))
230                        ("email" . (10 20 70))
231                        ("graphics" . 100) ;; can also be (100)
232                        (".*" . (30 50 20))))
233</enscript>
234
235You can request the current column rules with the following procedure:
236
237  procedure: (wmii:colrules)
238
239This returns an alist of the same type as accepted by wmii:colrules-set!.
240
241==== Tag rules
242
243Tag rules work much like column rules, except they specify which
244tags a client should get when it's first created.
245
246  procedure: (wmii:tagrules-set! alist)
247
248The alist here takes again strings as keys which are interpreted as
249regexes by wmii.  The values are either strings or lists of strings
250which are taken to be tagnames. Example:
251
252<enscript highlight=scheme>
253  (wmii:tagrules-set! `(("XMMS.*" . ("music" "~"))
254                        ("display.*" . ("graphics" "~"))
255                        ("Gimp.*" . ("graphics" "~"))
256                        ("xjump.*" . ("games" "~"))
257                        ("MPlayer.*" . "~")
258                        ("VICE.*" . ("games" "~"))
259                        (".*" . "sel") ;; Default to current tag
260                        (".*" . "1"))) ;; If no tag exists yet, start with '1'
261</enscript>
262
263Just like colrules, tagrules can be listed:
264
265  procedure: (wmii:tagrules)
266
267Returns an alist that looks just like the one from {{wmii:tagrules-set!}}.
268
269==== Event handlers
270
271The core of wmiirc script writing is in the event handlers.  You can register
272those with this procedure:
273
274  procedure: (wmii:event-handlers-set! alist [grab-keys])
275
276The alist has keys that are either simply symbols that name the event
277or lists that provide a full match for the incoming event.  The first
278rule that matches an incoming event is used, the others are ignored.
279The values of the alist are lambdas which handle the event.  The
280{{grab-keys}} parameter defaults to {{#t}} and indicates if key
281handlers should be filtered from the event handlers and the keys used
282by them should be grabbed.  If a key is not grabbed, it will never be
283visible by the wmiirc script; it will be passed to the client directly
284without being passed to the script by wmii.
285
286The events that you can expect are as follows:
287
288; {{(create-tag TAGNAME)}} : The tag with the name {{TAGNAME}} has just been created.
289
290; {{(destroy-tag TAGNAME)}} : The tag with name {{TAGNAME}} has just been destroyed.
291
292; {{(focus-tag TAGNAME)}} : The focus was changed to the tag with name {{TAGNAME}}
293
294; {{(unfocus-tag TAGNAME)}} : The tag with name {{TAGNAME}} which had focus is now not in focus anymore.
295
296; {{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.
297
298; {{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.
299
300; {{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.
301
302; {{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.
303
304; {{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.
305
306; {{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.
307
308; {{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).
309
310; {{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).
311
312; {{(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.
313
314See the [[#Example|example section]] for a good example of how to use
315these events.
316
317You can also use the following procedure to get the current event handlers:
318
319  procedure: (wmii:event-handlers)
320
321Note that this procedure can not return event handlers in other processes.
322It's simply a getter for the current wmiirc instance's list of event handlers.
323
324=== Keys
325
326  procedure: (wmii:grabbed-keys)
327
328Get a list of currently grabbed keys.
329
330  procedure: (wmii:grabbed-keys-set! keys)
331
332Sets the keys grabbed by wmii.  {{keys}} is a list of key descriptions.
333Keys must be grabbed or they won't be passed to the wmiirc event loop.
334Example:
335
336<enscript highlight="scheme">
337  (wmii:grabbed-keys-set! '(("Mod1" "x")
338                            ("Mod2" "Space")
339                            ("Mod1" "Shift" "Space")))
340</enscript>
341
342This grabs the key combinations Mod1-x, Mod2-space and Mod1-shift-space.
343Key names of "special" keys are always capitalized in wmii.  Normal literal
344keys like the x in the example are always lower case.  If you would like
345to hook shift-x, that would not be ("X"), but ("Shift" "x").
346
347  procedure: (wmii:key-code->string)
348  procedure: (wmii:string->key-code)
349
350Translate a chicken-wmiirc keycode to a string that can be written to wmii's
351{{/keys}} file.  Example:
352
353  (wmii:key-code->string '("Mod1" "Shift" "x")) => "Mod1-Shift-x"
354  (wmii:string->keycode "Mod1-Shift-x") => ("Mod1" "Shift" "x")
355
356=== Navigating
357
358  procedure: (wmii:goto-tag tag)
359
360Switch the view to the named {{tag}}.
361
362  procedure: (wmii:navigate-to direction [tag])
363
364Navigate to the given {{direction}} in the given {{tag}}.  Tag
365defaults to "sel", the current tag.  {{where}} can be "up", "down",
366"left", "right" or "toggle".  If one of the directions, the client
367above, below, to the left or to the right of the current client is
368selected.  If the direction is toggle, clients in float mode are
369selected if currently a client in normal mode is selected, or the
370other way around.  If tag is not the current tag, the currently
371selected client on that tag is changed, but nothing happens in the
372current view, unless the current view just happens to be a view on
373that tag.
374
375  procedure: (wmii:send-to direction [client] [tag])
376
377Send the given {{client}} (defaults to "sel", the currently selected
378client) into the given {{direction}}, as described above.  If {{tag}}
379is given, the client is sent to the given direction on that tag.  It
380is ''not'' sent to that tag.
381 
382=== Tags
383
384  procedure: (wmii:tags)
385 
386This procedure returns a list of all the tags known to wmii, as strings.
387
388  procedure: (wmii:tag-settings-set! alist [tag])
389
390Change the settings for the named {{tag}}, which defaults to "sel",
391the current tag.  {{alist}} is an alist with setting names (strings)
392as keys, and setting lists as values. Example:
393
394  (wmii:tag-settings-set! '(("colmode" . ("sel" "stack"))))
395
396This sets the current tag's column mode to stacked.
397 
398  procedure: (wmii:tag-settings [tag])
399
400Returns an alist of the settings for the named {{tag}}.  {{tag}} defaults
401to {{"sel"}}, that is the current tag.
402
403=== Bars
404
405  procedure: (wmii:tabs bar)
406
407Return a list of all tabs on the {{bar}}.  {{bar}} can be {{"lbar"}}
408(the left bar) or {{"rbar"}} (the right bar).
409
410  procedure: (wmii:write-tab bar tab contents [colors])
411
412Change the string {{contents}} of a {{tab}} on the indicated
413{{bar}}. Creates the tab if it doesn't exist yet.  If {{colors}}
414is given and not {{#f}} it should be a list of three numbers which
415represent in hexadecimal the color values of the foreground,
416background and border, respectively.
417
418Example:
419
420  (wmii:write-tab "lbar" "hello" "hello there")
421
422Creates a tab called "hello" on the left bar, which displays the
423string "hello there".
424
425  procedure: (wmii:destroy-tab bar tab)
426
427Destroy {{tab}} on {{bar}}.
428
429=== Clients
430
431  procedure: (wmii:client=? client1 client2)
432
433Are two clients one and the same?  Currently clients are represented
434as simple strings, the way wmii returns them, but in the future
435clients may have more information-rich representations, so always use
436this to compare them to be forwards-compatible.  These "opaque" client
437objects can be obtained by event handlers from the various events that
438operate on a client, or by {{wmii:clients}}, for example.
439
440  procedure: (wmii:clients)
441
442Returns a list of all the clients managed by wmii, in all tabs.
443
444  procedure: (wmii:client-tags [client])
445
446Return a list of all tags on {{client}}.  Defaults to the
447currently selected client ("sel").
448
449  procedure: (wmii:client-tags-set! tags [client])
450
451Set the {{tags}} (a list of strings) on the {{client}}.
452
453=== Low-level procedures
454
455If you would like access to the 9p filesystem exported by wmii, you
456can use the following procedures:
457
458  procedure: (wmii:write file data)
459
460Write the string contents of {{data}} to the named {{file}}.  If the
461file does not exist, it is created.
462
463  procedure: (wmii:read file)
464
465Read the given {{file}} into a string.
466
467  procedure: (wmii:read-lines file)
468
469Read the given {{file}} line by line and create a list with an entry
470per line.
471
472  procedure: (wmii:directory path)
473
474Show the directory contents of the named {{path}}.
475
476 
477=== Example
478
479This example simply translates the default wmiirc script that's shipped
480with wmii from shell to Chicken:
481
482<enscript highlight=scheme>
483#!/usr/pkg/bin/csi -s
484
485(use wmiirc srfi-18)
486
487(wmii:connect)
488
489(define modkey "Mod2")
490
491(define directions
492  `((up . "k")
493    (down . "j")
494    (left . "h")
495    (right . "l")))
496
497(define wmii-normcolors  '(#x888888 #x222222 #x333333))
498(define wmii-focuscolors '(#xffffff #x285577 #x4c7899))
499
500(define wmii-background #x333333)
501(define wmii-font "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*")
502
503(define (wmii9menu options . rest)
504  (let-optionals rest ((default #f))
505    (receive (in out pid)
506             (process
507              "wmii9menu"
508              `(,@(if default (list "-initial" default) '())
509                "-sf" ,(wmii:color->string (first wmii-focuscolors))
510                "-sb" ,(wmii:color->string (second wmii-focuscolors))
511                "-nf" ,(wmii:color->string (first wmii-normcolors))
512                "-nb" ,(wmii:color->string (second wmii-normcolors))
513                "-font" ,wmii-font
514                ,@options))
515             (close-output-port out)
516             (let ((chosen (read-line in)))
517               (close-input-port in)
518               (and (string? chosen) chosen)))))
519
520(define (dmenu options . rest)
521  (receive (in out pid)
522           (process
523            "dmenu"
524            `("-b"
525              "-sf" ,(wmii:color->string (first wmii-focuscolors))
526              "-sb" ,(wmii:color->string (second wmii-focuscolors))
527              "-nf" ,(wmii:color->string (first wmii-normcolors))
528              "-nb" ,(wmii:color->string (second wmii-normcolors))
529              "-fn" ,wmii-font))
530           (display (string-join options "\n") out)
531           (close-output-port out)
532           (let ((chosen (read-line in)))
533             (close-input-port in)
534             (and (string? chosen) chosen))))
535
536(define client-menu
537 (let ((last-option "nonexistingoption"))
538   (lambda (client)
539     (let ((option (wmii9menu '("Nop" "Delete" "Fullscreen") last-option)))
540       (when option
541         (cond
542          ((string=? option "Delete") (wmii:kill client))
543          ((string=? option "Fullscreen") (wmii:change-state "Fullscreen" #t client)))
544         (set! last-option option))))))
545
546(define wmii-term "xterm")
547
548(wmii:colrules-set! `((".*" . (58 42))))
549
550(wmii:tagrules-set! `(("XMMS.*" . "~")
551                      ("MPlayer.*" . "~")
552                      (".*" . "sel")
553                      (".*" . "1")))
554
555;; We need to do this in order to avoid getting lots of zombie processes
556(define (run . args) (process-wait (process-fork (lambda () (apply process-run args)))))
557
558(define status
559  (let ((status-pid #f))
560    (lambda ()
561      (and status-pid (process-signal status-pid))
562      (set! status-pid
563            (process-fork
564             (lambda ()
565               (wmii:connect)
566               (let loop ()
567                 (wmii:write-tab "rbar" "status"
568                                 (with-input-from-pipe "echo -n $(uptime | sed 's/.*://; s/,//g') '|' $(date)" read-string))
569                 (sleep 1)
570                 (loop))))))))
571
572(wmii:event-handlers-set!
573 `((create-tag
574    . ,(lambda (event tag) (wmii:write-tab "lbar" tag tag wmii-normcolors)))
575   (destroy-tag
576    . ,(lambda (event tag) (wmii:destroy-tab "lbar" tag)))
577   (focus-tag
578    . ,(lambda (event tag)
579         (if (member tag (wmii:tabs "lbar"))
580             (wmii:write-tab "lbar" tag tag wmii-focuscolors))))
581   (unfocus-tag
582    . ,(lambda (event tag)
583         (if (member tag (wmii:tabs "lbar"))
584             (wmii:write-tab "lbar" tag tag wmii-normcolors))))
585   (urgent-tag
586    . ,(lambda (event tag client?) (wmii:write-tab "lbar" tag (string-append "*" tag))))
587   (not-urgent-tag
588    . ,(lambda (event tag client?) (wmii:write-tab "lbar" tag tag)))
589   (left-bar-click
590    . ,(lambda (event button tab) (wmii:goto-tag tab)))
591   (client-mouse-down
592    . ,(lambda (event client button)
593         (case button
594           ((3) (client-menu client)))))
595   ((key ,modkey "Control" "t")
596    . ,(let ((prev #f))
597         (lambda _
598           (let ((keys (wmii:grabbed-keys)))
599             (if prev
600                 (begin (wmii:grabbed-keys-set! prev)
601                        (set! prev #f))
602                 (begin (set! prev keys)
603                        (wmii:grabbed-keys-set! `((,modkey "Control" "t")))))))))
604   ((key ,modkey "space")
605    . ,(lambda _ (wmii:navigate-to "toggle")))
606   ((key ,modkey "d")
607    . ,(lambda _ (wmii:tag-settings-set! '(("colmode" . ("sel" "default"))))))
608   ((key ,modkey "s")
609    . ,(lambda _ (wmii:tag-settings-set! '(("colmode" . ("sel" "stack"))))))
610   ((key ,modkey "m")
611    . ,(lambda _ (wmii:tag-settings-set! '(("colmode" . ("sel" "max"))))))
612   ((key ,modkey "a")
613    . ,(lambda _
614         (let ((action (dmenu (append
615                               `("rehash" "exec" "status" "quit")
616                               (proglist (string-split (getenv "WMII_CONFPATH") ":"))))))
617           (when action
618             (cond
619              ((string=? action "rehash") (update-programs))
620              ((string-prefix? "exec " action)
621               (wmii:exec (string-drop action 5)))
622              ((string=? action "status") (status))
623              ((string=? action "quit")
624               (wmii:quit)
625               (exit))
626              (else (run (sprintf "env PATH=${WMII_CONFPATH}:${PATH} ~A" action))))))))
627   ((key ,modkey "p")
628    . ,(lambda _
629         (and-let* ((program (dmenu programs))) (run program))))
630   ((key ,modkey "t")
631    . ,(lambda _
632         (and-let* ((tag (dmenu (wmii:tags)))) (wmii:goto-tag tag))))
633   ((key ,modkey "Return")
634    . ,(lambda _ (run wmii-term)))
635   ((key ,modkey "Shift" "space")
636    . ,(lambda _ (wmii:send-to "toggle")))
637   ((key ,modkey "f")
638    . ,(lambda _ (wmii:change-state "Fullscreen" 'toggle)))
639   ((key ,modkey "Shift" "c")
640    . ,(lambda _ (wmii:kill)))
641   ((key ,modkey "Shift" "t")
642    . ,(lambda _
643         (and-let* ((tag (dmenu (wmii:tags)))) (wmii:client-tags-set! (list tag)))))
644   ,@(map (lambda (x)
645            `((key ,modkey ,(cdr x))
646              . ,(lambda _ (wmii:navigate-to (->string (car x))))))
647          directions)
648   ,@(map (lambda (x)
649            `((key ,modkey "Shift" ,(cdr x))
650              . ,(lambda _ (wmii:send-to (->string (car x))))))
651          directions)   
652   ,@(map (lambda (x)
653            `((key ,modkey ,(->string x))
654              . ,(lambda _ (wmii:goto-tag x))))
655          (iota 10))
656   ,@(map (lambda (x)
657            `((key ,modkey "Shift" ,(->string x))
658              . ,(lambda _ (wmii:client-tags-set! (list (->string x)))))) (iota 10))))
659
660(wmii:global-settings-set!
661 `((font . ,wmii-font)
662   (focuscolors . ,wmii-focuscolors)
663   (normcolors . ,wmii-normcolors)
664   (grabmod . ,modkey)
665   (border . "1")))
666
667(define (proglist path)
668  (sort!
669   (delete-duplicates!
670    (flatten
671     (map (lambda (dir)
672            (if ((conjoin directory? file-execute-access? file-read-access?) dir)
673                (map pathname-strip-directory
674                     (find-files dir (conjoin (complement directory?) file-execute-access?) cons '() 0))
675                '()))
676          path))
677    string=?)
678   string<?))
679
680(define programs '())
681(define (update-programs)
682  (thread-start!
683   (make-thread
684    (lambda () (set! programs (proglist (string-split (getenv "PATH") ":")))))))
685(update-programs)
686
687(let ((curtag (wmii:tag)))
688  (for-each (cut wmii:destroy-tab "lbar" <>) (wmii:tabs "lbar"))
689  (for-each (lambda (t)
690              (if (string=? curtag t)
691                  (wmii:write-tab "lbar" t t wmii-focuscolors)
692                  (wmii:write-tab "lbar" t t wmii-normcolors)))
693            (wmii:tags)))
694
695(run (sprintf "xsetroot -solid '~A'" (wmii:color->string wmii-background)))
696
697(status)
698(wmii:event-loop)
699</enscript>
700
701For some other cool snippets, have a look at the [[wmiirc snippets]] page.
702
703=== Changelog
704
7050.1 Initial release
706
707=== License
708
709  Copyright (c) 2008, Peter Bex
710  All rights reserved.
711 
712  Redistribution and use in source and binary forms, with or without
713  modification, are permitted provided that the following conditions are
714  met:
715 
716  Redistributions of source code must retain the above copyright
717  notice, this list of conditions and the following disclaimer.
718 
719  Redistributions in binary form must reproduce the above copyright
720  notice, this list of conditions and the following disclaimer in the
721  documentation and/or other materials provided with the distribution.
722 
723  Neither the name of the author nor the names of its contributors may
724  be used to endorse or promote products derived from this software
725  without specific prior written permission.
726 
727  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
728  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
729  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
730  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
731  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
732  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
733  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
734  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
735  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
736  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
737  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
738  OF THE POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.