Category:Guish: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
No edit summary
Line 70: Line 70:




Being a command interpreter, guish has a little set of syntax rules. They comprises expressions, commands, quotes and special operators. Generic commands and signals are common to all elements, while there are ones which are specific to each element. A phrase is the execution unit, and ends if the program encounters a newline-like character, or a semicolon (';').
Being a command interpreter, guish has a little set of syntax rules. They comprises expressions, commands, quotes and special operators. Generic commands and signals are common to all elements, while there are ones which are specific to each element. A phrase is the execution unit, and ends if the program encounters a newline-like character, or a semicolon (";").


== Comments ==
== Comments ==
Line 90: Line 90:
Elements are basically widgets and have some commands and signals associated with them; they can be created using element expressions, enclosing element name within '''||''':
Elements are basically widgets and have some commands and signals associated with them; they can be created using element expressions, enclosing element name within '''||''':


<pre> guish &quot;|b|+&quot;</pre>
<pre> |b|+</pre>
In this example, &quot;|b|&quot; is an expression which creates an element of type button, and returns its X11 window id (ex, &quot;65011718+&quot;).
In this example, &quot;|b|&quot; is an expression which creates an element of type button, and returns its X11 window id (ex, &quot;65011718+&quot;).


Line 108: Line 108:
We can refer to elements by using variable substitution, instead of using their window ids:
We can refer to elements by using variable substitution, instead of using their window ids:


<pre> guish -c &quot;bt = |b|&quot;</pre>
<pre> bt = |b|</pre>
and then:
and then:


Line 126: Line 126:
Signals make it possible to run actions on UI changes (or, more generally, on some events).
Signals make it possible to run actions on UI changes (or, more generally, on some events).


<pre>guish -c &quot;|b|=&gt;c{run free}&quot;</pre>
<pre> |b|=&gt;c{run free}</pre>
Here, the user creates a button that when clicked will make guish execute a system command (free in this case) (see '''run''' in SPECIAL COMMANDS).
Here, the user creates a button that when clicked will make guish execute a system command (free in this case) (see '''run''' in SPECIAL COMMANDS).


<pre> guish -zc &quot;|b|&lt;generator =&gt;c{|b|&lt;clone}&quot;</pre>
<pre> |b|&lt;generator =&gt;c{|b|&lt;clone}</pre>
A button which is a factory of buttons.
A button which is a factory of buttons (run this with '''-z''' option).


In addition, being a the last argument a code block, it's possible to pass arguments to it (like functions), by putting them inside brackets '''[]''' (note that this works just for signals):
In addition, being a the last argument a code block, it's possible to pass arguments to it (like functions), by putting them inside brackets '''[]''' (note that this works just for signals):


<pre> guish -zc '|b|&lt;generator =&gt;c{|b|&lt;&quot;clone: @{1}&quot;}[&quot;myname&quot;]'</pre>
<pre> |b|&lt;generator =&gt;c{|b|&lt;&quot;clone: @{1}&quot;}[&quot;myname&quot;]</pre>
Here the evaluation of the code block is done when the click signal is triggered.
Here the evaluation of the code block is done when the click signal is triggered.


Line 144: Line 144:


<pre> a = 1; {b = 2}(); puts &quot;@{a}:@{b}&quot;</pre>
<pre> a = 1; {b = 2}(); puts &quot;@{a}:@{b}&quot;</pre>
Here the variable 'a' is defined in the global scope, while
Here the variable &quot;a&quot; is defined in the global scope, while &quot;b&quot; is defined in a temporarily block scope; hence just &quot;a&quot; is printed to stdout.

is printed to stdout.


When accessing reading/defining a variable in a local scope, if the variable is already defined in the enclosing scope (or recursively in any enclosing scope of the enclosing scope till the global scope), then that variable is picked to be read/modified:
When accessing reading/defining a variable in a local scope, if the variable is already defined in the enclosing scope (or recursively in any enclosing scope of the enclosing scope till the global scope), then that variable is picked to be read/modified:


<pre> a = 1; {a = 5; puts@a}(); puts@a</pre>
<pre> a = 1; {a = 5; puts@a}(); puts@a</pre>
Here 'a' is defined in the global scope, then modified from block scope and printed from there, and its value doesn't change.
Here &quot;a&quot; is defined in the global scope, then modified from block scope and printed from there, and its value doesn't change.


== Quotes, blocks and functions ==
== Quotes, blocks and functions ==
Line 157: Line 155:




There are single and double quoting. Anything embedded inside '''''''' is treated literally (no escaping takes place) and as a single token, while inside '''&quot;&quot;''', variable interpolation and escaping ('\n\t\r\f\v\b') applies.
There are single and double quoting. Anything embedded inside '''''''' is treated literally (no escaping takes place) and as a single token, while inside '''&quot;&quot;''', variable interpolation and escaping (&quot;\n\t\r\f\v\b&quot;) applies.


<pre> a = 'my string'; puts &quot;this is: @{a}&quot;</pre>
<pre> a = 'my string'; puts &quot;this is: @{a}&quot;</pre>
Anything embedded inside '''{}''' is treated as a code block and no variable substitution is done at definition time.
Anything embedded inside '''{}''' is treated as a code block and no variable substitution is done at definition time.


To &quot;execute&quot; a block, simply use parens '''()'''. If arguments are given, they can be referenced inside block by using '''@n''', where 'n' is a number which represents a specific argument by position. To refer to all arguments given to the block as a &quot;list&quot; instead, it's possible to use '''@*''' operator (when in string interpolation, argument separator is a space).
To &quot;execute&quot; a block, simply use parens '''()'''. If arguments are given, they can be referenced inside block by using '''@n''', where &quot;n&quot; is a number which represents a specific argument by position. To refer to all arguments given to the block as a &quot;list&quot; instead, it's possible to use '''@*''' operator (when in string interpolation, argument separator is a space).


<pre> v = myvar; a = {puts &quot;here is @{v}&quot;}; a()</pre>
<pre> v = myvar; a = {puts &quot;here is @{v}&quot;}; a()</pre>
Here the variable 'v' is not substituted when assigning the block to 'a'; it's substituted later, when function 'a' is called.
Here the variable &quot;v&quot; is not substituted when assigning the block to &quot;a&quot;; it's substituted later, when function &quot;a&quot; is called.


<pre> {puts join(&quot;&quot;, &quot;string length is: &quot;, len(@1)) }(&quot;home&quot;)</pre>
<pre> {puts join(&quot;&quot;, &quot;string length is: &quot;, len(@1)) }(&quot;home&quot;)</pre>
Line 199: Line 197:


<pre> if ge(@a,4) { |l|&lt;4 }</pre>
<pre> if ge(@a,4) { |l|&lt;4 }</pre>
It is possible to &quot;exit&quot; a block with the ''''leave'''' command on a certain condition too:
It is possible to &quot;exit&quot; a block with the '''leave''' command on a certain condition too:


<pre> if seq(t(@a), 'b') { puts &quot;a button!&quot;; leave seq(d(@a), &quot;test&quot;); puts &quot;end of if&quot; }</pre>
<pre> if seq(t(@a), 'b') { puts &quot;a button!&quot;; leave seq(d(@a), &quot;test&quot;); puts &quot;end of if&quot; }</pre>
Line 220: Line 218:
Since '''2.2.1''' version, guish supports tail recursion optimization too, effectively turning a tail recursive function into a loop:
Since '''2.2.1''' version, guish supports tail recursion optimization too, effectively turning a tail recursive function into a loop:


<pre>upto = {
<pre> upto = {
if gt(@1, @2) {
if gt(@1, @2) {
return
return
}
}
puts @1
puts @1
return upto(add(@1, 1), @2)
return upto(add(@1, 1), @2)
}
}
upto(1, 7)</pre>

upto(1, 7)</pre>
To use TCO, the last phrase of a function must use '''return''' command directly (not inside another block like if-else).
To use TCO, the last phrase of a function must use '''return''' command directly (not inside another block like if-else).


Line 596: Line 593:


; '''R'''
; '''R'''
: triggered when input has focus and 'return' is hit
: triggered when input has focus and &quot;return&quot; is hit


= REDUNDANT TOKENS =
= REDUNDANT TOKENS =
Line 602: Line 599:




These tokens are ignored: '''','''', ''''-&gt;''''
These tokens are ignored: &quot;''','''&quot;, &quot;'''-&gt;'''&quot;


= EVALUATION ORDER AND SUBSTITUTIONS =
= EVALUATION ORDER AND SUBSTITUTIONS =
Line 617: Line 614:


<pre> a = 234 {i1=|i|&lt;'input1'+}(); {i2=|i|&lt;'input2'+}() |b|&lt;btn+</pre>
<pre> a = 234 {i1=|i|&lt;'input1'+}(); {i2=|i|&lt;'input2'+}() |b|&lt;btn+</pre>
This example is composed by 2 phrases, specifically: &quot;a = 234 {i1=|i|&lt;'input1'+}()&quot; and &quot;{i2=|i|&lt;'input2'+}() |b|&lt;btn+&quot;.
This example is composed by 2 phrases, and the code block in each phrase is executed before each assignment.

Here the code block in each phrase is executed before each assignment.


== Hex substitution ==
== Hex substitution ==
Line 625: Line 620:




Non quoted tokens are subject to hex substitution: if a '\x' plus 2 hexadecimal characters is found, it's substituted with corresponding ascii characters.
Non quoted tokens are subject to hex substitution: if a &quot;\x&quot; plus 2 hexadecimal characters is found, it's substituted with corresponding ascii characters.


<pre> puts \x68\x6F\x6D\x65</pre>
<pre> puts \x68\x6F\x6D\x65</pre>
Here, the string 'home' is printed.
Here, the string &quot;home&quot; is printed.


== Globbing ==
== Globbing ==
Line 634: Line 629:




If a ''''*'''' is given, then all widgets wids are substituted.
If a &quot;'''*'''&quot; is given, then all widgets wids are substituted.


<pre> |b||b||b|+; dump *</pre>
<pre> |b||b||b|+; dump *</pre>
Line 643: Line 638:
With the '''=''' operator (actually, it's a special statement command), it's possible to assign a value to a variable, reusing it later by simply referencing it using '''@''' operator when not inside quotes or by wrapping it inside '''@{}''' when in double quotes or shell command substitution quotes '''``'''.
With the '''=''' operator (actually, it's a special statement command), it's possible to assign a value to a variable, reusing it later by simply referencing it using '''@''' operator when not inside quotes or by wrapping it inside '''@{}''' when in double quotes or shell command substitution quotes '''``'''.


There are two methods to define/create empty variables: by explicitely assing an empty string to a variable (ex. 'a = &quot;&quot;') or by simply omit the value (ex. 'a =').
There are two methods to define/create empty variables: by explicitely assing an empty string to a variable (ex. a = &quot;&quot;) or by simply omit the value (ex. a =).


Each block has it's own scope, and variable resolution works by searching from the last scope to the first. Ex:
Each block has it's own scope, and variable resolution works by searching from the last scope to the first. Ex:


<pre> a = 1; puts(@a) ;{a=345; b=6534}(); puts@a; puts&quot;b:@{b}&quot;</pre>
<pre> a = 1; puts(@a) ;{a=345; b=6534}(); puts@a; puts&quot;b:@{b}&quot;</pre>
In the last example, a is set to 1 and printed, then it's changed to 345 from another scope, in which another variable (b) is set. After code block, just 'a' is updated, and 'b' doesn't exist anymore.
In the last example, a is set to 1 and printed, then it's changed to 345 from another scope, in which another variable (b) is set. After code block, just &quot;a&quot; is updated, and &quot;b&quot; doesn't exist anymore.


For example:
For example:
Line 699: Line 694:




== Widget's related functions (first argument must be an element id) ==
== Widget's related functions (first argument &lt;eid&gt; must be an element id) ==






; '''t'''
; '''t(&lt;eid&gt;)'''
: widget's type
: widget's type
; '''w'''
; '''w(&lt;eid&gt;)'''
: widget's width
: widget's width
; '''h'''
; '''h(&lt;eid&gt;)'''
: widget's height
: widget's height
; '''x'''
; '''x(&lt;eid&gt;)'''
: widget's x coord
: widget's x coord
; '''y'''
; '''y(&lt;eid&gt;)'''
: widget's y coord
: widget's y coord
; '''b'''
; '''b(&lt;eid&gt;)'''
: widget's border width
: widget's border width
; '''g'''
; '''g(&lt;eid&gt;)'''
: widget's margin width
: widget's margin width
; '''d'''
; '''d(&lt;eid&gt;)'''
: widget's text data
: widget's text data
; '''a'''
; '''a(&lt;eid&gt;)'''
: widget's custom/attached data
: widget's custom/attached data
; '''T'''
; '''T(&lt;eid&gt;)'''
: widget's title
: widget's title
; '''c'''
; '''c(&lt;eid&gt;)'''
: widget's checked/unchecked status (only for checkbox)
: widget's checked/unchecked status (only for checkbox)
; '''n'''
; '''n(&lt;eid&gt;)'''
: widget's number of subwidgets (only for page)
: widget's number of subwidgets (only for page)
; '''s'''
; '''s(&lt;eid&gt;)'''
: widget's subwidgets ids (one token each, only for page)
: widget's subwidgets ids (one token each, only for page)
; '''pid'''
; '''pid(&lt;eid&gt;)'''
: process ID associated with the widget
: process ID associated with the widget
; '''v'''
; '''v(&lt;eid&gt;)'''
: widget is visible
: widget is visible
; '''e'''
; '''e(&lt;eid&gt;)'''
: widget is enabled (freezed/unfreezed)
: widget is enabled (freezed/unfreezed)
; '''f'''
; '''f(&lt;eid&gt;)'''
: widget is focused
: widget is focused
; '''exists(&lt;eid&gt;)'''
: widget exists


== Generic functions ==
== Generic functions ==
Line 742: Line 739:




Symbol ''''...'''' means a variable number of arguments.
Symbol &quot;'''...'''&quot; means a variable number of arguments.


; '''exists(&lt;eid&gt;)'''
: gets an element id and returns 1 if the element exists, else 0.
; '''read([&lt;file&gt;])'''
; '''read([&lt;file&gt;])'''
: reads and returns a line (expluding newline) from standard input; if an existing [file] is given, reads and returns all its content. Beware that this function blocks the GUI events, and returns nothing when reading from stdin and source is non-blocking.
: reads and returns a line (expluding newline) from standard input; if an existing [file] is given, reads and returns all its content. Beware that this function blocks the GUI events, and returns nothing when reading from stdin and source is non-blocking.
Line 753: Line 748:
: append text to the end of file and returns the number of characters written. Creates the file if it doesn't exist yet.
: append text to the end of file and returns the number of characters written. Creates the file if it doesn't exist yet.
; '''call(&lt;name&gt;, ...)'''
; '''call(&lt;name&gt;, ...)'''
: gets a variable name and a variable number of arguments, then calls the function whose name is 'name' with those arguments and returns the result.
: gets a variable name and a variable number of arguments, then calls the function whose name is &quot;name&quot; with those arguments and returns the result.
; '''env(&lt;var&gt;)'''
; '''env(&lt;var&gt;)'''
: returns the value of the environment variable 'var'
: returns the value of the environment variable &quot;var&quot;
; '''rev(...)'''
; '''rev(...)'''
: returns a reversed list of tokens. This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
: returns a reversed list of tokens. This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
; '''def([&lt;var&gt;=[&lt;val&gt;], ...)'''
; '''def([&lt;var&gt;, &lt;val&gt;], ...)'''
: sets variables, works exactly like assignment with special operator '''=''', but in expressions. This function is somewhat special, it'll return nothing (statement behaviour), neither an empty token.
: sets variables, works exactly like assignment with special operator '''=''', but in expressions. This function is somewhat special, it'll return nothing (statement behaviour), neither an empty token.
; '''puts(...)'''
; '''puts(...)'''
Line 771: Line 766:
: pops the first token from function arguments (when inside a function). This function is somewhat special, as if there are no arguments to pop, it'll return nothing (statement behaviour), neither an empty token.
: pops the first token from function arguments (when inside a function). This function is somewhat special, as if there are no arguments to pop, it'll return nothing (statement behaviour), neither an empty token.
; '''take(si, ei, ...)'''
; '''take(si, ei, ...)'''
: returns tokens starting at 'si' and ending at 'ei' (inclusive). This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
: returns tokens starting at &quot;si&quot; and ending at &quot;ei&quot; (inclusive). This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
; '''head(...)'''
; '''head(...)'''
: returns the first token given. This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
: returns the first token given. This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
Line 777: Line 772:
: returns all tokens except the first one. This function is somewhat special, as when there are one or no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
: returns all tokens except the first one. This function is somewhat special, as when there are one or no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
; '''times(&lt;n&gt;, &lt;token&gt;)'''
; '''times(&lt;n&gt;, &lt;token&gt;)'''
: returns a &quot;list&quot; made by 'n' times 'token'. This function is somewhat special, as when there are 0 tokens to replicate, it'll return nothing (statement behaviour), neither an empty token.
: returns a &quot;list&quot; made by &quot;n&quot; times &quot;token&quot;. This function is somewhat special, as when there are 0 tokens to replicate, it'll return nothing (statement behaviour), neither an empty token.
; '''slice(&lt;si&gt;, &lt;ei&gt;, &lt;token&gt;)'''
; '''slice(&lt;si&gt;, &lt;ei&gt;, &lt;token&gt;)'''
: returns the portion of a token starting at index 'si' and ending at 'ei' (inclusive).
: returns the portion of a token starting at index &quot;si&quot; and ending at &quot;ei&quot; (inclusive).
; '''get(&lt;i&gt;, &lt;token&gt;)'''
; '''get(&lt;i&gt;, &lt;token&gt;)'''
: returns the character of a token at index 'i'.
: returns the character of a token at index &quot;i&quot;.
; '''fetch(&lt;name&gt;)'''
; '''fetch(&lt;name&gt;)'''
: returns the value of the variable with name 'name', or an empty token if the variable doesn't exist.
: returns the value of the variable with name &quot;name&quot;, or an empty token if the variable doesn't exist.
; '''in(&lt;substr&gt;, &lt;token&gt;)'''
; '''in(&lt;substr&gt;, &lt;token&gt;)'''
: returns 1 if substr is found in token, otherwise 0.
: returns 1 if substr is found in token, otherwise 0.
; '''join(&lt;sep&gt;, ...)'''
; '''join(&lt;sep&gt;, ...)'''
: returns a single token from a variable number of tokens, joining them using 'sep'.
: returns a single token from a variable number of tokens, joining them using &quot;sep&quot;.
; '''range(&lt;start&gt;, &lt;end&gt;)'''
; '''range(&lt;start&gt;, &lt;end&gt;)'''
: returns numbers starting at 'start' and ending at 'end' (inclusive) as multiple tokens.
: returns numbers starting at &quot;start&quot; and ending at &quot;end&quot; (inclusive) as multiple tokens.
; '''defined(&lt;name&gt;)'''
; '''defined(&lt;name&gt;)'''
: returns 1 if 'name' is a variable, otherwise 0.
: returns 1 if &quot;name&quot; is a variable, otherwise 0.
; '''isvar(&lt;name&gt;)'''
; '''isvar(&lt;name&gt;)'''
: returns 1 if 'name' is a (type) variable, otherwise 0.
: returns 1 if &quot;name&quot; is a (type) variable, otherwise 0.
; '''isfunc(&lt;name&gt;)'''
; '''isfunc(&lt;name&gt;)'''
: returns 1 if 'name' refers to a function, otherwise 0.
: returns 1 if &quot;name&quot; refers to a function, otherwise 0.
; '''isalias(&lt;name&gt;)'''
; '''isalias(&lt;name&gt;)'''
: returns 1 if 'name' is an alias, otherwise 0.
: returns 1 if &quot;name&quot; is an alias, otherwise 0.
; '''len(&lt;token&gt;)'''
; '''len(&lt;token&gt;)'''
: returns the length of the token.
: returns the length of the token.
; '''split(&lt;token&gt;, &lt;sep&gt;)'''
; '''split(&lt;token&gt;, &lt;sep&gt;)'''
: splits 'token' using separator 'sep' and returns resulting tokens having their type equal to that of 'token'.
: splits &quot;token&quot; using separator &quot;sep&quot; and returns resulting tokens having their type equal to that of &quot;token&quot;.
; '''csplit(&lt;token&gt;, &lt;sep&gt;)'''
; '''csplit(&lt;token&gt;, &lt;sep&gt;)'''
: splits 'token' using separator 'sep' and returns resulting tokens as normal commands.
: splits &quot;token&quot; using separator &quot;sep&quot; and returns resulting tokens as normal commands.
; '''seq(&lt;t1&gt;, &lt;t2&gt;, ...)'''
; '''seq(&lt;t1&gt;, &lt;t2&gt;, ...)'''
: returns 1 if all arguments are equal (string comparison), 0 otherwise.
: returns 1 if all arguments are equal (string comparison), 0 otherwise.
Line 860: Line 855:
Here, we create a label with a blue background and white foreground.
Here, we create a label with a blue background and white foreground.


Each field must be separated by newlines, ''';''' or '''|'''. Colors can be specified by using a common shortname, such as 'yellow', or by using RGB value, such as '#ff32ae'.
Each field must be separated by newlines, ''';''' or '''|'''. Colors can be specified by using a common shortname, such as &quot;yellow&quot;, or by using RGB value, such as &quot;#ff32ae&quot;.


; '''background | bg'''
; '''background | bg: &lt;color&gt;'''
: set background color
: set background color
; '''color | foreground | fg'''
; '''color | foreground | fg: &lt;color&gt;'''
: set foreground color
: set foreground color
; '''pressed-background | pbg'''
; '''pressed-background | pbg: &lt;color&gt;'''
: background color when element is pressed
: background color when element is pressed
; '''pressed-color | pfg'''
; '''pressed-color | pfg: &lt;color&gt;'''
: foreground color when element is pressed
: foreground color when element is pressed
; '''hovered-background | hbg'''
; '''hovered-background | hbg: &lt;color&gt;'''
: background color when element is hovered
: background color when element is hovered
; '''hovered-color | hfg'''
; '''hovered-color | hfg: &lt;color&gt;'''
: foreground color when element is hovered
: foreground color when element is hovered
; '''border-color | bc'''
; '''border-color | bc: &lt;color&gt;'''
: set border color
: set border color
; '''background-image | i'''
; '''background-image | i: &lt;path&gt;'''
: set background image by specifying image path; if the string 'null' is given, current image is removed. (This attribute requires building guish with Imlib2 support.)
: set background image by specifying image path; if the string &quot;null&quot; is given, current image is removed. (This attribute requires building guish with Imlib2 support.)
; '''width | w'''
; '''width | w: &lt;value in pixels&gt;'''
: set width
: set width
; '''height | h'''
; '''height | h: &lt;value in pixels&gt;'''
: set height
: set height
; '''border | b'''
; '''border | b: &lt;value in pixels&gt;'''
: set border width
: set border width
; '''margin | g'''
; '''margin | g: &lt;value in pixels&gt;'''
: set margin width
: set margin width
; '''mode | m'''
; '''mode | m: &lt;expanding mode&gt;'''
: set expanding mode type (See Expanding mode)
: set expanding mode type (See Expanding mode)
; '''align | a'''
; '''align | a: &lt;alignment&gt;'''
: set text alignment type (See Alignment)
: set alignment type (See Alignment)
; '''f | font'''
; '''f | font: &lt;font name&gt;'''
: set font type using a X11 font name
: set font type using a X11 font name


Line 909: Line 904:





Any element that's not a page has a particular text alignment that can be changed. If an alignment is specified for a page element instead, (whose defaults alignments are top-center for horizontal layout, and middle-left for vertical one), then its sub-elements will be aligned accordingly, depending from page layout type too.


; '''l | left | middle-left'''
; '''l | left | middle-left'''

Revision as of 19:38, 24 November 2022

Language
Guish
This programming language may be used to instruct a computer to perform a task.
Official website
See Also:


Listed below are all of the tasks on Rosetta Code which have been solved using Guish.

NAME

guish - A language to make and modify GUIs

SYNOPSIS

guish [OPTIONS] [CODE]

guish [-h][-e][-z][-i][-c][-q][-a][-x][-d][-F][-V][-v <var>=<val>][-f <file>][<code>]

DESCRIPTION

guish is a language to create and modify GUIs; it can be used to tie different programs together by embedding, or to make simple GUIs.

This is version 2.x, which depends just on Xlib as all toolkits have been removed (there are some optional dependencies).

OPTIONS

-h
guess
-e
quit program on errors/warnings.
-z
display elements when created.
-i
disable automatic variable interpolation in strings.
-c
quit guish when closing last element/window.
-q
terminate all external programs when quitting.
-a
enable aliases and aliases resolution for commands (see Aliases).
-x
fallback on tty after reading data from other inputs.
-d
daemonize, excluding fallback on tty if set.
-F
show available x11 fonts.
-V
show version.
-v <var>=<val>
register a variable with value, can be used multiple times.
-f <file>
read and execute commands from <file>.

INPUTS AND SOURCES

guish reads commands from multiple source sequentially; these source are: command line, file, standard input, and if -x option is given, controlling terminal. After reading commands from a source, it tries to switch to another one, and when there are no more sources, it simply stays idle.

So this is the sequence: if there is a file (script) specified with -f option, execute from there, else if there are commands on command line, execute them. If standard input is a pipe, switch to it and execute from there, then finally switch to controlling terminal (if -x option is given) and execute from there.

If a named pipe is given with -f option, then it will be opened in non-blocking mode, allowing to issue commands from the other end of the pipe.

SYNTAX OVERVIEW

Being a command interpreter, guish has a little set of syntax rules. They comprises expressions, commands, quotes and special operators. Generic commands and signals are common to all elements, while there are ones which are specific to each element. A phrase is the execution unit, and ends if the program encounters a newline-like character, or a semicolon (";").

Comments

Single line comments begin with a #, and end at newline like character:

 a = 4 # this is a comment

Multiline comments instead are embedded inside #[ and ]# (or end at the end of source):

 a = 4 #[ This,
 is a multiline comment,
 ending here. ]# puts "a: @{a}"

Elements and element expressions

Elements are basically widgets and have some commands and signals associated with them; they can be created using element expressions, enclosing element name within ||:

 |b|+

In this example, "|b|" is an expression which creates an element of type button, and returns its X11 window id (ex, "65011718+").

The + command will then show the button (all elements are hidden by default unless -z option is given).

Subject and implied subject

To refer to the last created/modified element, you can use it without naming it explicitly, for example:

 |i|;+

Variables and variable substitution

We can refer to elements by using variable substitution, instead of using their window ids:

 bt = |b|

and then:

 @bt < "new button"

Commands

Commands instead can be of three distinct types: special, generic and normal.

Special commands are meant to change guish behaviour, generic ones are meant to modify an element of any type and normal ones are for a specific element type (every element can have specialized commands).

Signals

Signals make it possible to run actions on UI changes (or, more generally, on some events).

 |b|=>c{run free}

Here, the user creates a button that when clicked will make guish execute a system command (free in this case) (see run in SPECIAL COMMANDS).

 |b|<generator =>c{|b|<clone}

A button which is a factory of buttons (run this with -z option).

In addition, being a the last argument a code block, it's possible to pass arguments to it (like functions), by putting them inside brackets [] (note that this works just for signals):

 |b|<generator =>c{|b|<"clone: @{1}"}["myname"]

Here the evaluation of the code block is done when the click signal is triggered.

Scopes

All variables (functions too, as blocks can be assigned to variables) have a specific scope:

 a = 1; {b = 2}(); puts "@{a}:@{b}"

Here the variable "a" is defined in the global scope, while "b" is defined in a temporarily block scope; hence just "a" is printed to stdout.

When accessing reading/defining a variable in a local scope, if the variable is already defined in the enclosing scope (or recursively in any enclosing scope of the enclosing scope till the global scope), then that variable is picked to be read/modified:

 a = 1; {a = 5; puts@a}(); puts@a

Here "a" is defined in the global scope, then modified from block scope and printed from there, and its value doesn't change.

Quotes, blocks and functions

There are single and double quoting. Anything embedded inside ''' is treated literally (no escaping takes place) and as a single token, while inside ""', variable interpolation and escaping ("\n\t\r\f\v\b") applies.

 a = 'my string'; puts "this is:	 @{a}"

Anything embedded inside {} is treated as a code block and no variable substitution is done at definition time.

To "execute" a block, simply use parens (). If arguments are given, they can be referenced inside block by using @n, where "n" is a number which represents a specific argument by position. To refer to all arguments given to the block as a "list" instead, it's possible to use @* operator (when in string interpolation, argument separator is a space).

 v = myvar; a = {puts "here is @{v}"}; a()

Here the variable "v" is not substituted when assigning the block to "a"; it's substituted later, when function "a" is called.

 {puts join("", "string length is: ", len(@1)) }("home")

Here instead, the block is defined and executed immediately, using "home" as the first argument.

Being a block a piece of code, it can be used to define functions by simply being assigned to a variable:

 fn = {return add(@1, @2)}
 puts join(" ", "my func res:", fn(2, 4)) 

In addition, when defining a new function, it's possible to "overwrite" the builtin functions in the current scope.

When returning from a function, instead, it's possible to return multiple arguments (the remaining phrase) to the caller:

 fn = {return 1 2 3}; puts join('+', fn())

Aliases

If -a option is given (or activated with setopt command), aliases substitution takes place. An alias can be set simply by using assignment:

 print = puts
 print "here!"

The main difference with respect to a normal variable is that aliases are generated only if the given value is a "free" token (tokens of command type), and the value corresponds to a known command (otherwise it's a normal variable).

Conditionals

Anything equal to 0 or "empty" (like ''', ""') is false, true otherwise. This is useful with if and else commands:

 if 1 { |b|<text } else { |b|<neverhere }

or

 if ge(@a,4) { |l|<4 }

It is possible to "exit" a block with the leave command on a certain condition too:

 if seq(t(@a), 'b') { puts "a button!"; leave seq(d(@a), "test"); puts "end of if" }

In the last example, the execution jumps out of the "if" block if the text of the button is equal to "test", otherwise it reaches the last block command and prints "end of it".

Loops and iteration

Here an example of a while loop:

 a = 1; after 4 {a = 0}; while eq(@a, 1) { wait 1 puts 'true' } puts 'end'

And here another one of a for loop:

 for x 1 2 3 4 { puts @x }

Tail recursion optimization (TCO)

Since 2.2.1 version, guish supports tail recursion optimization too, effectively turning a tail recursive function into a loop:

 upto = {
     if gt(@1, @2) {
         return
     }
     puts @1
     return upto(add(@1, 1), @2)
 }
 upto(1, 7)

To use TCO, the last phrase of a function must use return command directly (not inside another block like if-else).

External window id substitution

Everything inside <( ) is recognized as an external command (X11 GUI), forked and executed, and its window id is substituted (using _NET_WM_PID).

Note that this method will not work with programs that fork.

For example:

 a = <(xterm)

xterm program is spawn, and can be driven (almost) like a normal element.

External command substitution

Everything inside `` is recognized as an external command and executed. Then the command output (STDOUT) is substituted inside source code and interpreted after that.

For example:

 |b|<`echo clickme`

Expressions

 puts add(4, mul(5, 6))

Here 34 is printed by puts special command.

SPECIAL VARIABLES

SW
primary screen width, in pixels.
SH
primary screen height, in pixels.
X
pointer's x coord.
Y
pointer's y coord.
self
variable holding the window id when in signal code.
FILE
variable holding the path of current source file.

ENVIRONMENT VARIABLES

GUISH_MAXWIDWAIT
the maximum number of seconds to wait when applying external window id substitution (defaults to 3 seconds)

ELEMENTS

Available elements are:

b
A button
i
An input box
l
A label
p
A page (container of other elements; show and hide are applied to all subelements)
c
A checkbox

COMMANDS

Special commands

Special commands are not tied to elements, they are like statements.

=> <signal> <subcmd>
register a sub-command <subcmd> to run when <signal> triggers
q
quit guish
run <cmd>
execute shell command <cmd>
dump <args>
print <args> to stdout with a newline added
puts <arg>
print <arg> to stdout with a newline added
p <arg>
print <arg> to stdout
e <arg>
print <arg> to stderr
unset <name/scheduled num>
unset variable or timed scheduled procedure registered with <num>, see every command
source <file>
execute commands from file
vars
display all variables on standard error
ls
display all existing widgets on standard error
del <wid>
delete a widget with id <wid>
opts
show options status on standard error
setopt <name> <val>
set an option using name and val
every <seconds> <block>
schedule <code> to run after <seconds> seconds are elapsed
after <seconds> <block>
schedule <block> to run once after <seconds> seconds are elapsed
wait <seconds>
stop command execution and wait <seconds> seconds before resuming; XEvent handling, schedules actions and signal execution are unaffected by this option.
if <condition> <block>
executes <block> if condition evaluates to true (see Conditionals).
unless <condition> <block>
executes <block> if condition evaluates to false (see Conditionals).
else <block>
executes <block> if last conditional command was successful (see Conditionals).
return <phrase>
when used inside a function, returns all its arguments (the remaining phrase) to the caller.
leave <condition>
leaves the enclosing block if <condition> evaluates to true (does not apply to loops).
while <condition> <block>
executes <block> until <condition> evaluates to true (see Conditionals).
until <condition> <block>
executes <block> until <condition> evaluates to true (see Conditionals).
for <variable> <list of items> <code>
executes <code> for each item in list of items using a variable. Note that <code> must be a code block.
break
exit from current loop.
rel <element1> <element2> <alignment>
relates <element1> to <element2>, moving <element1> near <element2> using <alignment> (see alignment in STYLE AND ATTRIBUTES section, as <alignment> opts are similar) every time <element2> is moved. If "0" is specified as alignment, the relation is deleted.
pass [<args>]
do nothing, consuming remaining arguments.
send <keysequence>
send a keysequence to an element (must be enabled at compilation time)
ctrl <keysequence>
send control key sequence to an element (must be enabled at compilation time)

Generic commands

Generic commands are applicable to any element, regardless of its type (there are exceptions though).

G
element is undetectable in taskbar
F
resize the element to fit the entire screen
d
restore element's default window attributes
!
bypass window manager
!!
follow window manager as default
n
center element in its parent
-
hide element
+
show element
c
click element
f
focus element
t
make element stay at top
b
make element stay at bottom
x
hide element, or quit guish if quit-on-last-close is on and the element is the last closed one
l
lower the element
r
raise the element
M
maximize the element
D
disable the element
E
enable the element
o
fits element's size to its content
w
resize an element in right-bottom directions to fit its parent, respecting limits of other elements
nfill
resize an element in right-bottom directions to fit its parent
rfill
resize an element in right direction to fit its parent, respecting limits of other elements
nrfill
resize an element in right direction to fit its parent
bfill
resize an element in bottom direction to fit its parent, respecting limits of other elements
nbfill
resize an element in bottom direction to fit its parent
at <x> <y>
when setting text, write text at <x> <y> coords inside element
L
clear element's data
: <title>
set element title
a <data>
attach custom <data> to a widget; to retrieve it see "BUILTIN FUNCTIONS" section.
s <text>
set element style (see STYLE AND ATTRIBUTES section).
z <w> <h>
resize element by width and height
i
increment element's width by 10px
I
decrement element's width by 10px
k
increment element's height by 10px
K
decrement element's height by 10px
m <x> <y>
move element to coords <x> <y>
> <element> <alignment>
moves implied element to <element> using <alignment> (see alignment in STYLE AND ATTRIBUTES section, as <alignment> opts are similar).
< <text>
set element text using <text>
<+ <text>
add additional text to element text using <text>
g
enable/disable (toggle) moving the parent of the element by click-and-drag it. Enabling this will automatically exclude x/y moving flags below.
X
enable/disable (toggle) moving an element inside its parent by click-and-drag on x axis Enabling this will automatically exclude the flag to click-and-drag and move parent.
Y
enable/disable (toggle) moving an element inside its parent by click-and-drag on y axis Enabling this will automatically exclude the flag to click-and-drag and move parent.

Normal commands

Normal commands are per element.

checkbox commands

C
check
U
uncheck

input commands

S
show input data as normal while typing
H
hide input data while typing
P
use password mode, displaying just asterisks
W
toggles "go to the next line" when hitting return (triggers return signal anyway).

page commands

Q
make subelements equals (in size)
S <style>
style all subelements
P
free all embedded elements
<< <element>
embeds element (or an external client)
<<< <element>
embeds element (or an external client), fitting the page to its content
>> <element>
free element, reparenting it to root window
>>> <element>
free element, reparenting it to root window and fitting the page to its content
v
set vertical layout readjusting all subwidgets
h
set horizontal layout readjusting all subwidgets

SIGNALS

Special signals

Special signals are independent from elements, and are tied to internal guish events.

q
triggered at program exit
t
triggered when program recevives a SIGINT or a SIGTERM

Generic signals

Generic signals are common to all elements.

x
triggered when element is closed
c
triggered when element is clicked
lc
triggered when element is left-clicked
rc
triggered when element is right-clicked
mc
triggered when element is middle-clicked
cc
triggered when element is double clicked
lcc
triggered when element is double left-clicked
rcc
triggered when element is double right-clicked
mcc
triggered when element is double middle-clicked
p
triggered when element is pressed
lp
triggered when element is left-pressed
rp
triggered when element is right-pressed
mp
triggered when element is middle-pressed
r
triggered when element is released
lr
triggered when element is left-released
rr
triggered when element is right-released
mr
triggered when element is middle-released
m
triggered when element is moved
s
triggered when element scrolled down
S
triggered when element scrolled up
z
triggered when element is resized
e
triggered when mouse pointer "enters" the element
l
triggered when mouse pointer "leaves" the element
f
triggered when focusing the element
u
triggered when un-focusing the element

Normal signals

Normal signals are per element.

checkbox signals

U
triggered when checkbox is unchecked
C
triggered when checkbox is checked

input signals

R
triggered when input has focus and "return" is hit

REDUNDANT TOKENS

These tokens are ignored: ",", "->"

EVALUATION ORDER AND SUBSTITUTIONS

Every time a new phrase is evaluated, it goes through a series of special substitutions/evaluations before it's commands are interpreted these are: code evaluation, hex substitution (at tokenizer level), globbing, variable substitution, element expression, shell command substitution and external window id substitution. See related sections to know more.

Code evaluation

Every phrase is reduced to an empty phrase while evaluating:

 a = 234 {i1=|i|<'input1'+}(); {i2=|i|<'input2'+}() |b|<btn+

This example is composed by 2 phrases, and the code block in each phrase is executed before each assignment.

Hex substitution

Non quoted tokens are subject to hex substitution: if a "\x" plus 2 hexadecimal characters is found, it's substituted with corresponding ascii characters.

 puts \x68\x6F\x6D\x65

Here, the string "home" is printed.

Globbing

If a "*" is given, then all widgets wids are substituted.

 |b||b||b|+; dump *

Variable substitution

With the = operator (actually, it's a special statement command), it's possible to assign a value to a variable, reusing it later by simply referencing it using @ operator when not inside quotes or by wrapping it inside @{} when in double quotes or shell command substitution quotes ``.

There are two methods to define/create empty variables: by explicitely assing an empty string to a variable (ex. a = "") or by simply omit the value (ex. a =).

Each block has it's own scope, and variable resolution works by searching from the last scope to the first. Ex:

 a = 1; puts(@a) ;{a=345; b=6534}(); puts@a; puts"b:@{b}"

In the last example, a is set to 1 and printed, then it's changed to 345 from another scope, in which another variable (b) is set. After code block, just "a" is updated, and "b" doesn't exist anymore.

For example:

 gname = MY_GRIP_NAME
 |l|<@gname

or

 gname = MY_GRIP_NAME
 name = 'random name'
 puts "@{gname} is maybe @{name}"

It's also possible to assign "lists" to a variable by putting the tokens inside []:

 a = [a, b]; for x @a { puts @x }

Beware that this works just for assignment, [] cannot be used in expressions.

Element substitution

Anything inside || is an element expression; a widget of a given element is created and its X11 window id substituted. Ex.

 |b|+

If an integer is given, instead of one of available element types, then the program tries to find an existing program having that integer as window id. Ex.

 |12341234|-

This creates a widget ("external") for the external program and hides it.

Shell command substitution

Anything inside `` is treated as a shell command, and it's output is substituted.

 d = `date`
 ols = `ls -l`

External window id substitution

Everything inside <( ) is recognized as an external command (X11 GUI), forked and executed, and its window id is substituted (using _NET_WM_PID).

For example:

 a = <(xterm)

xterm program is spawn, and can be driven (almost) like a normal element.

BUILTIN FUNCTIONS

Widget's related functions (first argument <eid> must be an element id)

t(<eid>)
widget's type
w(<eid>)
widget's width
h(<eid>)
widget's height
x(<eid>)
widget's x coord
y(<eid>)
widget's y coord
b(<eid>)
widget's border width
g(<eid>)
widget's margin width
d(<eid>)
widget's text data
a(<eid>)
widget's custom/attached data
T(<eid>)
widget's title
c(<eid>)
widget's checked/unchecked status (only for checkbox)
n(<eid>)
widget's number of subwidgets (only for page)
s(<eid>)
widget's subwidgets ids (one token each, only for page)
pid(<eid>)
process ID associated with the widget
v(<eid>)
widget is visible
e(<eid>)
widget is enabled (freezed/unfreezed)
f(<eid>)
widget is focused
exists(<eid>)
widget exists

Generic functions

Symbol "..." means a variable number of arguments.

read([<file>])
reads and returns a line (expluding newline) from standard input; if an existing [file] is given, reads and returns all its content. Beware that this function blocks the GUI events, and returns nothing when reading from stdin and source is non-blocking.
write(<text>, <file>)
writes text into file and returns the number of characters written. Creates the file if it doesn't exist yet.
append(<text>, <file>)
append text to the end of file and returns the number of characters written. Creates the file if it doesn't exist yet.
call(<name>, ...)
gets a variable name and a variable number of arguments, then calls the function whose name is "name" with those arguments and returns the result.
env(<var>)
returns the value of the environment variable "var"
rev(...)
returns a reversed list of tokens. This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
def([<var>, <val>], ...)
sets variables, works exactly like assignment with special operator =, but in expressions. This function is somewhat special, it'll return nothing (statement behaviour), neither an empty token.
puts(...)
prints given tokens to stdout. This function is somewhat special, it'll return nothing (statement behaviour), neither an empty token.
push(...)
pushes given tokens to a function arguments (when inside a function). This function is somewhat special, it'll return nothing (statement behaviour), neither an empty token.
pushb(...)
pushes given tokens to a function arguments from the beginning (when inside a function). This function is somewhat special, it'll return nothing (statement behaviour), neither an empty token.
pop()
pops the last token from function arguments (when inside a function). This function is somewhat special, as if there are no arguments to pop, it'll return nothing (statement behaviour), neither an empty token.
popb()
pops the first token from function arguments (when inside a function). This function is somewhat special, as if there are no arguments to pop, it'll return nothing (statement behaviour), neither an empty token.
take(si, ei, ...)
returns tokens starting at "si" and ending at "ei" (inclusive). This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
head(...)
returns the first token given. This function is somewhat special, as when there are no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
tail(...)
returns all tokens except the first one. This function is somewhat special, as when there are one or no tokens to get, it'll return nothing (statement behaviour), neither an empty token.
times(<n>, <token>)
returns a "list" made by "n" times "token". This function is somewhat special, as when there are 0 tokens to replicate, it'll return nothing (statement behaviour), neither an empty token.
slice(<si>, <ei>, <token>)
returns the portion of a token starting at index "si" and ending at "ei" (inclusive).
get(<i>, <token>)
returns the character of a token at index "i".
fetch(<name>)
returns the value of the variable with name "name", or an empty token if the variable doesn't exist.
in(<substr>, <token>)
returns 1 if substr is found in token, otherwise 0.
join(<sep>, ...)
returns a single token from a variable number of tokens, joining them using "sep".
range(<start>, <end>)
returns numbers starting at "start" and ending at "end" (inclusive) as multiple tokens.
defined(<name>)
returns 1 if "name" is a variable, otherwise 0.
isvar(<name>)
returns 1 if "name" is a (type) variable, otherwise 0.
isfunc(<name>)
returns 1 if "name" refers to a function, otherwise 0.
isalias(<name>)
returns 1 if "name" is an alias, otherwise 0.
len(<token>)
returns the length of the token.
split(<token>, <sep>)
splits "token" using separator "sep" and returns resulting tokens having their type equal to that of "token".
csplit(<token>, <sep>)
splits "token" using separator "sep" and returns resulting tokens as normal commands.
seq(<t1>, <t2>, ...)
returns 1 if all arguments are equal (string comparison), 0 otherwise.
count(...)
returns the number of given tokens.
any(...)
returns 1 if at least one token is not empty or equal to 0, 0 otherwise. This function is special, as the evaluation will be interrupted as soon as there is at least 1 true argument.
all(...)
returns 1 if all tokens are not empty or equal to 0, 0 otherwise. This function is special, as the evaluation will be interrupted as soon as there is at least 1 false argument.
add(...)
perform addition.
sub(...)
perform subtraction.
mul(...)
perform multiplication
div(...)
perform division.
mod(...)
perform modulus.
xor(<n1>, <n2>, ...)
perform bitwise XOR.
and(<n1>, <n2>, ...)
perform bitwise AND.
or(<n1>, <n2>, ...)
perform bitwise OR.
lsh(<n1>, <n2>, ...)
perform bitwise left shift.
rsh(<n1>, <n2>, ...)
perform bitwise right shift.
not(<n>)
perform negation
eq(<n1>, <n2>, ...)
equal-to
ne(<n1>, <n2>, ...)
not-equal-to
lt(<n1>, <n2>, ...)
less-than
gt(<n1>, <n2>, ...)
greater-than
le(<n1>, <n2>, ...)
less-equal-than
ge(<n1>, <n2>, ...)
greater-equal-than
abs(<n>)
perform absolute value
neg(<n>)
unary minus.

STYLE AND ATTRIBUTES

Each element has some properties/attributes which can be set by using style command. This command takes a string that has a format like CSS:

 |l| s 'bg: blue; fg: white'

Here, we create a label with a blue background and white foreground.

Each field must be separated by newlines, ; or |. Colors can be specified by using a common shortname, such as "yellow", or by using RGB value, such as "#ff32ae".

background | bg: <color>
set background color
color | foreground | fg: <color>
set foreground color
pressed-background | pbg: <color>
background color when element is pressed
pressed-color | pfg: <color>
foreground color when element is pressed
hovered-background | hbg: <color>
background color when element is hovered
hovered-color | hfg: <color>
foreground color when element is hovered
border-color | bc: <color>
set border color
background-image | i: <path>
set background image by specifying image path; if the string "null" is given, current image is removed. (This attribute requires building guish with Imlib2 support.)
width | w: <value in pixels>
set width
height | h: <value in pixels>
set height
border | b: <value in pixels>
set border width
margin | g: <value in pixels>
set margin width
mode | m: <expanding mode>
set expanding mode type (See Expanding mode)
align | a: <alignment>
set alignment type (See Alignment)
f | font: <font name>
set font type using a X11 font name

Expanding mode

fixed | f
width and height are fixed (default for all elements)
wfixed | w
width is fixed, height can change
hfixed | h
height is fixed, width can change
relaxed | r
width and height can change

Alignment

Any element that's not a page has a particular text alignment that can be changed. If an alignment is specified for a page element instead, (whose defaults alignments are top-center for horizontal layout, and middle-left for vertical one), then its sub-elements will be aligned accordingly, depending from page layout type too.

l | left | middle-left
show text at middle left
r | right | middle-right
show text at middle right
c | center | middle-center
show text at middle center
tl | top-left
show text at top left
tr | top-right
show text at top right
t | top-center
show text at top center
bl | bottom-left
show text at bottom left
br | bottom-right
show text at bottom right
b | bottom-center
show text at bottom center

AUTHOR

Francesco Palumbo <phranz@subfc.net>

LICENSE

GPL3

Pages in category "Guish"

The following 3 pages are in this category, out of 3 total.