# Chessboard program: you type in moves in algebraic notation, and it'll # display the position after each move. def main [ local-scope open-console # take control of screen, keyboard and mouse clear-screen null/screen # non-scrolling app # The chessboard function takes keyboard and screen objects as inputs. # # In Mu it is good form (though not required) to explicitly state what # hardware a function needs. # # Here the console and screen are both null, which usually indicates real # hardware rather than a fake for testing as you'll see below. chessboard null/screen, null/console close-console # clean up screen, keyboard and mouse ] ## But enough about Mu. Here's what it looks like to run the chessboard program. scenario print-board-and-read-move [ local-scope trace-until 100/app # we'll make the screen really wide because the program currently prints out a long line assume-screen 120/width, 20/height # initialize keyboard to type in a move assume-console [ type [a2-a4 ] ] run [ screen, console <- chessboard screen, console # icon for the cursor cursor-icon:char <- copy 9251/␣ screen <- print screen, cursor-icon ] screen-should-contain [ # 1 2 3 4 5 6 7 8 9 10 11 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 .Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves. . . . .8 | r n b q k b n r . .7 | p p p p p p p p . .6 | . .5 | . .4 | P . .3 | . .2 | P P P P P P P . .1 | R N B Q K B N R . . +---------------- . . a b c d e f g h . . . .Type in your move as -. For example: 'a2-a4'. Then press . . . . .Hit 'q' to exit. . . . .move: ␣ . . . . . ] ] ## Here's how 'chessboard' is implemented. type board = &:@:&:@:char # a 2-D array of arrays of characters def chessboard screen:&:screen, console:&:console -> screen:&:screen, console:&:console [ local-scope load-inputs board:board <- initial-position # hook up stdin stdin-in:&:source:char, stdin-out:&:sink:char <- new-channel 10/capacity start-running send-keys-to-channel, console, stdin-out, screen # buffer lines in stdin buffered-stdin-in:&:source:char, buffered-stdin-out:&:sink:char <- new-channel 10/capacity start-running buffer-lines,
dwm - dynamic window manager
============================
dwm is an extremely fast, small, and dynamic window manager for X.


Requirements
------------
In order to build dwm you need the Xlib header files.


Installation
------------
Edit config.mk to match your local setup (dwm is installed into
the /usr/local namespace by default).

Afterwards enter the following command to build and install dwm (if
necessary as root):

    make clean install

If you are going to use the default bluegray color scheme it is highly
recommended to also install the bluegray files shipped in the dextra package.


Running dwm
-----------
Add the following line to your .xinitrc to start dwm using startx:

    exec dwm

In order to connect dwm to a specific display, make sure that
the DISPLAY environment variable is set correctly, e.g.:

    DISPLAY=foo.bar:1 exec dwm

(This will start dwm on display :1 of the host foo.bar.)

In order to display status info in the bar, you can do something
like this in your .xinitrc:

    while true
    do
        echo `date` `uptime | sed 's/.*,//'`
        sleep 1
    done | dwm


Configuration
-------------
The configuration of dwm is done by creating a custom config.h
and (re)compiling the source code.
0/eof return-if empty-fake-keyboard?, 0/dummy, true/quit, false/no-error { newline?:bool <- equal c, 10/newline break-unless newline? print screen, [that's not enough] return 0/dummy, false/don't-quit, true/error } file:num <- subtract c, 97/a # 'a' <= file <= 'h' { above-min:bool <- greater-or-equal file, 0 break-if above-min print screen, [file too low: ] print screen, c cursor-to-next-line screen return 0/dummy, false/don't-quit, true/error } { below-max:bool <- lesser-than file, 8 break-if below-max print screen, [file too high: ] print screen, c return 0/dummy, false/don't-quit, true/error } return file, false/don't-quit, false/no-error ] # valid values for rank: 0-7 def read-rank stdin:&:source:char, screen:&:screen -> rank:num, quit?:bool, error?:bool, stdin:&:source:char, screen:&:screen [ local-scope load-inputs c:char, eof?:bool, stdin <- read stdin return-if eof?, 0/dummy, true/quit, false/no-error q-pressed?:bool <- equal c, 81/Q return-if q-pressed?, 0/dummy, true/quit, false/no-error q-pressed? <- equal c, 113/q return-if q-pressed?, 0/dummy, true/quit, false/no-error empty-fake-keyboard?:bool <- equal c, 0/eof return-if empty-fake-keyboard?, 0/dummy, true/quit, false/no-error { newline?:bool <- equal c, 10 # newline break-unless newline? print screen, [that's not enough] return 0/dummy, false/don't-quite, true/error } rank:num <- subtract c, 49/'1' # assert'1' <= rank <= '8' { above-min:bool <- greater-or-equal rank, 0 break-if above-min print screen, [rank too low: ] print screen, c return 0/dummy, false/don't-quite, true/error } { below-max:bool <- lesser-or-equal rank, 7 break-if below-max print screen, [rank too high: ] print screen, c return 0/dummy, false/don't-quite, true/error } return rank, false/don't-quite, false/no-error ] # read a character from the given channel and check that it's what we expect # return true on error def expect-from-channel stdin:&:source:char, expected:char, screen:&:screen -> result:bool, stdin:&:source:char, screen:&:screen [ local-scope load-inputs c:char, eof?:bool, stdin <- read stdin return-if eof? true { match?:bool <- equal c, expected break-if match? print screen, [expected character not found] } result <- not match? ] scenario read-move-blocking [ local-scope assume-screen 20/width, 2/height source:&:source:char, sink:&:sink:char <- new-channel 2/capacity read-move-routine:num/routine <- start-running read-move, source, screen run [ # 'read-move' is waiting for keypress wait-for-routine-to-block read-move-routine read-move-state:num <- routine-state read-move-routine waiting?:bool <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-blocking: routine failed to pause after coming up (before any keys were pressed)] # press 'a' sink <- write sink, 97/a restart read-move-routine # 'read-move' still waiting for keypress wait-for-routine-to-block read-move-routine read-move-state <- routine-state read-move-routine waiting? <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-blocking: routine failed to pause after rank 'a'] # press '2' sink <- write sink, 50/'2' restart read-move-routine # 'read-move' still waiting for keypress wait-for-routine-to-block read-move-routine read-move-state <- routine-state read-move-routine waiting? <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-blocking: routine failed to pause after file 'a2'] # press '-' sink <- write sink, 45/'-' restart read-move-routine # 'read-move' still waiting for keypress wait-for-routine-to-block read-move-routine read-move-state <- routine-state read-move-routine waiting? <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-blocking: routine failed to pause after hyphen 'a2-'] # press 'a' sink <- write sink, 97/a restart read-move-routine # 'read-move' still waiting for keypress wait-for-routine-to-block read-move-routine read-move-state <- routine-state read-move-routine waiting? <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-blocking: routine failed to pause after rank 'a2-a'] # press '4' sink <- write sink, 52/'4' restart read-move-routine # 'read-move' still waiting for keypress wait-for-routine-to-block read-move-routine read-move-state <- routine-state read-move-routine waiting? <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-blocking: routine failed to pause after file 'a2-a4'] # press 'newline' sink <- write sink, 10 # newline restart read-move-routine # 'read-move' now completes wait-for-routine-to-block read-move-routine read-move-state <- routine-state read-move-routine completed?:bool <- equal read-move-state, 1/completed assert completed?, [ F read-move-blocking: routine failed to terminate on newline] trace 1, [test], [reached end] ] trace-should-contain [ test: reached end ] ] scenario read-move-quit [ local-scope assume-screen 20/width, 2/height source:&:source:char, sink:&:sink:char <- new-channel 2/capacity read-move-routine:num <- start-running read-move, source, screen run [ # 'read-move' is waiting for keypress wait-for-routine-to-block read-move-routine read-move-state:num <- routine-state read-move-routine waiting?:bool <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-quit: routine failed to pause after coming up (before any keys were pressed)] # press 'q' sink <- write sink, 113/q restart read-move-routine # 'read-move' completes wait-for-routine-to-block read-move-routine read-move-state <- routine-state read-move-routine completed?:bool <- equal read-move-state, 1/completed assert completed?, [ F read-move-quit: routine failed to terminate on 'q'] trace 1, [test], [reached end] ] trace-should-contain [ test: reached end ] ] scenario read-move-illegal-file [ local-scope assume-screen 20/width, 2/height source:&:source:char, sink:&:sink:char <- new-channel 2/capacity read-move-routine:num <- start-running read-move, source, screen run [ # 'read-move' is waiting for keypress wait-for-routine-to-block read-move-routine read-move-state:num <- routine-state read-move-routine waiting?:bool <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-illegal-file: routine failed to pause after coming up (before any keys were pressed)] sink <- write sink, 50/'2' restart read-move-routine wait-for-routine-to-block read-move-routine ] screen-should-contain [ .file too low: 2 . . . ] ] scenario read-move-illegal-rank [ local-scope assume-screen 20/width, 2/height source:&:source:char, sink:&:sink:char <- new-channel 2/capacity read-move-routine:num <- start-running read-move, source, screen run [ # 'read-move' is waiting for keypress wait-for-routine-to-block read-move-routine read-move-state:num <- routine-state read-move-routine waiting?:bool <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-illegal-rank: routine failed to pause after coming up (before any keys were pressed)] sink <- write sink, 97/a sink <- write sink, 97/a restart read-move-routine wait-for-routine-to-block read-move-routine ] screen-should-contain [ .rank too high: a . . . ] ] scenario read-move-empty [ local-scope assume-screen 20/width, 2/height source:&:source:char, sink:&:sink:char <- new-channel 2/capacity read-move-routine:num <- start-running read-move, source, screen run [ # 'read-move' is waiting for keypress wait-for-routine-to-block read-move-routine read-move-state:num <- routine-state read-move-routine waiting?:bool <- not-equal read-move-state, 2/discontinued assert waiting?, [ F read-move-empty: routine failed to pause after coming up (before any keys were pressed)] sink <- write sink, 10/newline sink <- write sink, 97/a restart read-move-routine wait-for-routine-to-block read-move-routine ] screen-should-contain [ .that's not enough . . . ] ] def make-move board:board, m:&:move -> board:board [ local-scope load-inputs from-file:num <- get *m, from-file:offset from-rank:num <- get *m, from-rank:offset to-file:num <- get *m, to-file:offset to-rank:num <- get *m, to-rank:offset from-f:&:@:char <- index *board, from-file to-f:&:@:char <- index *board, to-file src:char/square <- index *from-f, from-rank *to-f <- put-index *to-f, to-rank, src *from-f <- put-index *from-f, from-rank, 32/space ] scenario making-a-move [ local-scope assume-screen 30/width, 12/height board:board <- initial-position move:&:move <- new move:type *move <- merge 6/g, 1/'2', 6/g, 3/'4' run [ board <- make-move board, move screen <- print screen, board ] screen-should-contain [ # 012345678901234567890123456789 .8 | r n b q k b n r . .7 | p p p p p p p p . .6 | . .5 | . .4 | P . .3 | . .2 | P P P P P P P . .1 | R N B Q K B N R . . +---------------- . . a b c d e f g h . . . ] ]