This document explains the interface between doityourself and the back-end scripts. You should not need to read it completely; just take a look at the example scripts provided, and you will hopefully get the idea.
doityourself is a generic desklet controlled by a user-made back-end script. It runs on top of adesklets, which is a framework for X Window desklets seamlessly integrated into the desktop.
doityourself provides a yet easier way to write a desklet. To achieve this, you have to write a back-end script (in any language) with a predefined behavior. The script will be called periodically to perform some test or action, and to write some output which will be displayed in the desklet.
See the README file for more information about last changes, known bugs and contact information.
Come on, I want to create my own desklet NOW!
Ok, ok... Creating a custom desklet with doityourself can be as simple as specifying a command in the configuration file. Copy the following line in config.txt:
id0 = { 'rawmode': True, 'script': '/bin/date' }
run doityourself and voilĂ ! You have your first desklet, which shows the current time and date. That was easy, huh?
Wait! That's not right... it shows the seconds but it doesn't refresh every second!
The update interval is by default 5 seconds, but it can be easily changed:
id0 = { 'rawmode': True, 'script': '/bin/date', 'test_delay': 1 }
Ok, that's better. What about changing appearance?
That's an easy one too:
id0 = { 'rawmode': True, 'script': '/bin/date', 'test_delay': 1, 'color': '00FF00', 'background.color': None, }
What's that 'rawmode' thing? What about those user scripts?
Setting rawmode to False (the default value) will tell doityourself to treat the command as a user script. User scripts must follow a specific behavior which is detailed later in this document. They allow to customize your desklet with much greater detail, and include neat things like images, bar meters, etc. User scripts are normally located in the scripts/ directory. Take a look at the provided scripts, and you will get the idea. Keep reading for details.
As with all desklets in adesklets, config.txt, is the file that holds configuration values for all instances of doityourself.
The only mandatory configuration variable is script. It is the filename of the user script or command. If a relative path is used, it will be expected to be located in the scripts/ directory.
rawmode defines the mode of operation. If False (the default), script must be a valid user script. Some predefined arguments will be passed to it, and its output will be parsed in order to find special formatting commands. If rawmode is set to True, script can be any command that writes some output to stdout, and no special arguments are passed to it. This is useful if you don't want to write a script, and you just want your desklet to show the output of a command. Additional arguments for script can also be included in raw mode. For example:
id0 = { 'rawmode': True, 'script': '/bin/uname -a' }
Additionally, any context variable can be initialized in the configuration file. Example:
id0 = { 'rawmode': True, 'script': '/bin/date "+%D"', 'color': '00FF00', 'background.color': None }
In short, user scripts work as follows: doityourself calls the script at defined intervals, passing information to it via its arguments. The script writes to standard output the commands that generate the desired contents and appearance inside the desklet. doityourself may also call the script to take an action whenever the user clicks on the desklet.
User scripts can be written in any language, and can be as simple or as complex as desired. A simple user script would just write anything to stdout. For example:
#!/bin/bash echo Hello, world!
More complex scripts can be created in order to format the output (ie, assign color, alignment) and insert things like images or bar meters. To achieve this, markups must be used.
The formatting commands are divided into markups that follow a syntax similar to HTML:
<command [arg1 arg2 ...]/>
(Remember I said similar, not identical :P)
There are three types of markups, all of them following the same general syntax: those which directly modify context variables, those which generate widgets, and special commands.
The rendering engine contains a set of context variables, such as the current font, color, etc. Each context variable has a predefined default value.
The script can modify context variables using markups. For example, the markup <color 'FF0000'/> sets the context variable color to the value FF0000 which is red. All Widgets created after this assignment will be red.
Context variables keep their values throughout the desklet's session. ie, in the example above, if no other markup changes the current color, it will remain as 'FF0000', even between calls to the script.
The desklet's window area is composed of a background (which can be filled with a color or image), and a group of widgets.
Examples of widgets are a string of text, a bar meter, an image... Widgets are created using markups, except strings, which are created whenever some text not enclosed between < and /> is found. Spaces and tabs outside markups are not ignored.
Widgets are organized in rows and columns. Actually, columns contain only a group of one or more rows, and each row contains a group of widgets and may include other columns, all of them arranged horizontally. As a result, widgets may not overlap each other.
By default, the window begins containing one column containing one empty row.
A new row of widgets is started when:
- an empty line is found in the script's output.
- a newline (\n) is found in a non-empty line, and the current row contains at least one widget.
You can always escape newlines by prepending a backslash (\) character.
A new column is started in the current row with the special <col/> markup. This column will begin containing one row. If new rows are created, they will be contained by this column. You can end the current column (and "return" to the previous one) with the <endcol/> markup.
Here is a example of a user script:
#!/bin/bash cat <<EOF Hello<image 'dys-color.png' 32 32/> <color '00FF00'/> <hline -1/><color 'FFFFFF'/> Line 1<col/> Line 1.1 Line 1.2<endcol/> Line 3 EOF
This is the result:
Note that in the previous example, widgets in the same row are centered vertically. This can be changed with the valign context variable: <valign 'top'/> or <valign 'bottom'/>.
Similarly, the halign context variable controls the alignment of rows inside a column. Possible values are: 'left' (default), 'center' and 'right'.
Additionally, there are two special widgets which come in handy to get widgets aligned: hspace and vspace.
The markup <hspace 50/> creates a horizontal space widget 50 pixels wide. Setting the width to -1 will make the widget autosized.
Autosized widgets are expanded to fill the row (or column) completely. If you place more than one autosized widget in the same row or column, they will be assigned the same size.
Almost all widgets can have their width and/or height autosized. You can use this property in hspace, for example, to center or right-align widgets:
Left-aligned text <hspace -1>Centered text<hspace -1> <hspace -1>Right-aligned text
The script will always receive at least one argument, which can be init, test, click or click_widget.
script init is called once when the desklet starts. The desklet's ID number is passed as the second argument. Normally, the script should write to stdout a group of markups to initialize context variables.
script test is called right after script init, and then periodically after a delay. The script can set this delay in seconds via the context variable test_delay (eg: <test_delay 10/> sets the delay to 10 seconds).
script click is called when the window.click_anywhere context variable is True (the default), and the user clicks on the desklet.
script click_widget is called when the user clicks on a clickable widget (currently, the only clickable widget available is the 'button' widget). The second argument will be the id of the widget that was clicked. Note that script click will not be called in this case.
test_value is a special context variable, which initially holds the value None, and can be set to hold any Python valid expression (a number, a string, a list, etc.). If test_value is not None, its value will be passed to the script as the last argument.
This variable adds some sort of persistence to the user script: by using test_value to hold a value, the script can "remember" things between calls.
By default, before each call to the script with test, click or click_widget, the widgets created previously are automatically forgotten. Also, after each call to the script with the these arguments, the widgets defined in memory are automatically displayed in the window.
If you set the autoclear context variable to False, widgets you have defined will remain in memory between calls to the script, until you use the special command <clear/>. Widgets' properties can still be modified by using the setattr special command.
Similarly, if you set the autorender context variable to False, you will need to use the special command <render/> to display the current set of widgets.
In normal operation, the script writes its output to stdout and returns zero.
If the script returns a non-zero value, stdout will be ignored and its output to stderr will be shown as an error message in red.
A detailed description of the available widgets, context variables and commands follows. For context variables, their default value is indicated.
A description of the available widgets follows. For each widget, there are three subsections: Creation, which explains the markup to be used to create that widget, Context variables, which enumerates the context variables that affect the widget, and Attributes, which details the attributes that can be modified for that widget using the setattr markup.
All widgets have three attributes in common: width, height and color which are self-explanatory and will not be included in each description.
Creation
A text widget is created by normal text (ie, no markup is needed).
Context variables
Current font and fontsize. The fontsize is mandatory. The TTF font should be placed in the fonts/ directory, or in the system fonts path.
Examples: 'Vera/14', 'VeraMono/10'.
Attributes
Creation
<hspace width/> <vspace width/>
Both width and height can be set to -1 to be autosized.
Context variables
There are no special context variables for space widgets.
Attributes
There are no special attributes for space widgets.
Creation
<hline width/> <vline height/>
Both width and height can be set to -1 to be autosized.
Context variables
Attributes
Creation
<bar_meter width height [value max]/>
width and height are the dimensions of the bar. Both can be set to -1 to be autosized.
value and max are optional (default: 0 and 100, respectively). They are the actual and maximum value displayable by the meter. Decimal numbers can be used.
Some examples:
<bar_meter 100 10/> <bar_meter -1 10 24.4 128.3/>
Context variables
Attributes
Creation
<image filename [width height]/>
filename is a string representing the file name of the image to be shown. This file should be placed in the icons/ directory.
If width and height are set, the image will be scaled to those values.
Some examples:
<image 'dys-color.png'/> <image 'email.png' 24 24/>
Context variables
There are no special context variables for image widgets.
Attributes
A special image widget that accepts clicks to generate a call to script click_widget.
Everything said for image widgets applies to button widgets.
Creation
<button filename [width height]/>
Context variables
Attributes
Box widgets allow to enclose other widgets inside a rectangle. This rectangle can have a fill color and a border color.
Creation
Box widgets behave like column widgets (see Rows and Columns):
<box color border_color/> ... <endbox/>
color and border_color can both be None.
Context variables
Attributes
Syntax
<clear/>
Description
A call to this command will clear the currently defined widgets.
Note that by default the autoclear context variable is True, so calling <clear/> is not necessary.
Syntax
<render/>
Description
A call to this command will display the currently defined widgets in the desklet's window.
Note that by default the autorender context variable is True, so calling <render/> is not necessary.
Syntax
<setattr id attribute value/>
id is the id string of a currently defined widget. attribute is the name of an attribute of that widget. value is the value to which the attribute will be set.
Examples:
<setattr 'button0' 'filename' 'email.png'/> <setattr 'bar_meter1' 'value' 25/>
Description
In normal operation, this command is not needed. But, if autoclear is False, and the set of widgets is defined at init time, this command, maybe in conjunction with the id context variable, can be used to modify the attributes of a few widgets and render again, without having to redefine the whole set of widgets. For example:
#!/bin/bash if [ $1 == 'init' ]; then cat <<-EOF <test_delay 1/> <autoclear False/> This is a bar meter: <id 'MyBar'/><bar_meter -1 10/> EOF exit 0 elif [ $1 == 'test' ]; then VALUE=$(( $RANDOM % 100 )) echo "<setattr 'MyBar' 'value' $VALUE/>" fi
If you have a complex set of widgets and on each test call you only want to modify a few of those widgets, it will be much more efficient to use this mechanism, instead of redefining the whole set of widgets every time.