.TH SINDRE 1 sindre\-VERSION .SH NAME sindre \- GUI programming language .SH SYNOPSIS .nh sindre [\fB\-f \fIprogram-file\fR] [\fB\-e \fIprogram-text\fR] .SH DESCRIPTION Sindre is a programming language inspired by Awk that makes it easy to write simple graphical programs in the spirit of dzen, dmenu, xmobar, gsmenu and the like. .SH OPTIONS .TP .PD 0 .BI \-f " program-file" .TP .PD .BI \-\^\-file " program-file" Read a program fragment from the file .IR program-file . Multiple .B \-f options may be used, and may be interleaved with .B \-e options. See the section on .B Multiple Fragments below. .TP .PD 0 .BI \-e " program-text" .TP .PD .BI \-\^\-expression " program-text" Read program fragment from the argument .IR program-text . Multiple .B \-e options may be used, and may be interleaved with .B \-f options. See the section on .B Code Substitution below. .TP .PD 0 .BI \-\^\-fd " NAME=FD" Create an input stream with the given name that reads from the given file descriptor. The file descriptor should be created by the script invoking Sindre, for example .ft B sindre --fd foostream=3 3<~/.xsession-errors. .ft R You should never create more than one stream per file descriptor. The standard input stream is automatically available as the stream 'stdin'. If multiple .B \-\^\-fd options are given that define the same stream name, the last one will take priority. .TP .PD 0 .BI \-\^\-wmmode " normal|dock|override" " (defaults to override)" If .IR normal , put the program under the management of the window manager as a normal client. If .IR dock , run as a dock/panel, assuming window manager support. If .IR override (the default), grab control of the display and stay on top until the program terminates. .SH USAGE .SS Lexical conventions Identifiers start with a letter and consist of alphanumerics or underscores. Class names start with a capital letter, while object and variable names start with lowercase. Line-comments are supported with // and block comments with /* ... */. Semicolons are used to separate statements and declarations, although they are optional when not needed to resolve ambiguity. .SS Overview The Sindre language is extremely similar to Awk in syntax and semantics, although there are subtle differences as well. A program primarily consists of action declarations that have the form .TP .IB pattern " { " statements " } " .P When an event arrives, each declaration is checked in order, and those whose pattern matches have their statements executed. Some patterns also bind variables while executing the statements, like a function call. The statement .B next can be used to immediately stop further processing of an event. Additionally there are a few special declarations. A GUI declaration defines a tree of possibly named widgets, and looks like .TP .BI "GUI { " name "=" class "(" parameters ") { " children " } }" .P where both name (including the equal sign), parameters (including the parentheses) and children (including the braces) are optional. Each child follows the same syntax as the body (the text between the braces) of a GUI declaration, and should be separated by semicolons. Widget parameters are of the form .P .IB param1 " = " exp1 ", " param2 " = " exp2 ", ... , " paramN " = " expN .P and are evaluated left-to-right. A parameter whose value is considered false (see section .BR VALUES ) will be ignored if its value is otherwise not valid for the parameter. Otherwise, an error will occur if the value is not what the widget expects (for example, the string "foo" passed as the widget height). .P A global variable declaration looks like .TP .IB name = exp .P Global variables are initialised before the GUI is created, so they can be used in widget parameters. On the other hand, they cannot refer to widgets. If you need to perform work after the GUI has been created, use a BEGIN declaration. .P Function are defined as in Awk, and recursion is supported: .P .BI "function " name "(" arg1 ", " arg2 ", ..., " argN ") { " statements " }" .P Arguments are lexically scoped within the function. If a function is called with fewer arguments than given in its declaration, the leftovers are given a false value. This is the only way to emulate local variables. .SS Patterns .TP .B BEGIN At program startup, after the GUI has been created. .TP .BI < key > When the given key is pressed. The syntax for keys is taken from GNU Emacs and consists of an optional set of modifiers (C- (Control), M- (Meta/Alt), Shift, S- (Super) or H- (Hyper)) followed by a key name. The Shift modifier is stripped from keypresses that are characters. For example, .B means a press of "a" while the Control key is held down, and .B is with a capital "A". Modifiers can be chained, so you can match .B if you really want to. The names for control characters, such as BackSpace above, are taken from X11 keynames. You can use .BR xev (1) to figure out the names to a given key. .TP .IB object -> event ( name1 ", " name2 ", ..., " nameN ) Matches when the named object sends the named event. The names will be bound to the value payload of the event, in the same way as with a function call. .TP .BI $ class ( name ")->" event ( name1 ", " name2 ", ..., " nameN ) As above, but matches when any widget of the given class sends the named event. .I name will be bound to the widget that emitted the event. .TP .IB pat1 " || " ... " || " patN Matches if any of the patterns, checked left-to-right, match. .SS Statements If-conditions, while-loops and for-loops are supported with the same syntax as in Awk, except that braces are always mandatory. All variables, except for function parameters, are global and initialised to false at program startup. A loop can be stopped with .B continue or .BR break , with usual C semantics, and .B return can be used to exit early from a function. .SS Expressions and Values All values, except for objects, are always passed by value in arguments and return values. Sindre supports numbers (integers and decimal syntax), dictionaries, strings and objects. Boolean values are canonically represented as integers, with the number 0 being false and any other value considered true. Strings follow the Haskell literal syntax (which is essentially identical to that of C). Objects can be used as event sources, as mentioned above, and have methods and fields. A method call has the syntax object.method(args) and a field is object.field, and can be used as an lvalue. Dictionaries differ significantly from those in Awk, as they have no special syntactical treatment. An empty dictionary is written as .B [] and elements can be added/changed by using the usual Awk-like syntax .BR foo["bar"]=4 , although the variable must already contain a dictionary or you will get an error (so use .B foo=[] to initialise). Keys and values can have any type. Multidimensional dictionaries are only supported by making the values dictionaries themselves, and has no special syntax, and arrays are merely dictionaries with integral keys. .SS Multiple Fragments When multiple .B \-f and .B \-e options are used, Sindre conceptually concatenates the given program text fragments in the order of the options. There are two differences from plain concatenation, however: .TP .B Duplicate definitions A program fragment is normally not allowed to define two global variables or functions with the same name, nor to contain two GUI declarations. When the above options are used, redefinitions of previous definitions appearing in later fragments take precedence. .TP .B Event handling priority Event handlers are run from top to bottom in terms of the program text, but event handlers in later fragments are run first. Thus, .ft B sindre -e 'obj->ev() { print "foo" } obj->ev() { print "bar" }' -e 'obj->ev() { print "baz" }' .ft R will print "baz foo bar" whenever the event .B obj->ev() happens. BEGIN declarations are similarly executed in reverse order. .ft B sindre -e 'BEGIN { print "I go last" }' -e 'BEGIN { print "I go first" }' .ft R .SS Special Variables .TP "\w'ENVIRON'u+1n" .B RSTART After regular expression matching, this variable will be set to the index (1-based) of the match. .TP .B RLENGTH The length of the most recent regular expression match. .TP .B ENVIRON A dictionary containing the environment variables of the Sindre process. Note that changing this dictionary currently has no effect on the environment. .TP .B EXITVAL Whenever an external program has been run, this variable will contain its exit value. .SS Numeric functions .TP "\w'atan2(x, y)'u+1n" .BI abs( n ) The numeric value of .IR n . .TP .BI atan2( x , " y" ) Arctangent of .I x/y in radians. .TP .BI cos( x ) Cosine of .IR x , in radians. .TP .BI sin( x ) Sine of .IR x , in radians. .TP .BI exp( x ) Natural exponent of .IR x . .TP .BI log( x ) Natural logarithm of .IR x . .TP .BI int( x ) .I x truncated to an integer. .TP .TP .BI sqrt( x ) The square root of .IR x . .SS String Functions .PP Note that indexes are 1-based. .PP .TP "\w'substr(s, m, n)'u+1n" .BI length( s ) Returns the number of characters in .I s .TP .BI substr( s , " m" , " n" ) Return .I n characters of .IR s , starting from character number .IR m . If either .IR n or m is out of bounds, the resulting string may be less than .I n characters. .TP .BI index( s , " t" ) Return the index at which .I t is found in .IR s , or 0 if .I t is not present. .TP .BI match( s , " r" ) Match the regular expression .I r against .IR t , returning the index of the first match, as well as setting .B RMATCH and .BR RLENGTH . .TP .BI gsub( r , " t" , " s" ) For each match of the regular expression .I r in .IR s , return a new string where each of those matches is replaced with .IR t . .TP .BI sub( r , " t" , " S" ) Like .IR sub , but only the first match is replaced. .TP .BI tolower( s ) Return an all-lowercase version of .IR s . .TP .BI toupper( s ) Return an all-uppercase version of .IR s . .SS System Functions .TP "\w'osystem(s)'u+1n" .BI osystem( s ) Run .I s as a shell command and return its output. .TP .BI system( s ) Run .I s as a shell command and return its exit value. .SH EXIT STATUS Sindre returns a .B 0 exit status on success, and .B 1 if there was an internal problem. .SH EXAMPLES See the examples/ subdirectory of the Sindre source tree. .SH SEE ALSO .BR dmenu (1), .BR awk (1), .BR sinmenu (1) .SH BUGS The syntax and semantics for local variables are inherited from Awk, and are rather ugly. It is possible to write programs that have no way of exiting, short of killing the process manually. Actions are executed atomically and synchronously, so an infinite loop can freeze the program, requiring the user to kill it manually.