source: project/wiki/wmiirc @ 8661

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

Add documentation on the remaining procedures

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