doityourself 0.4.1 -- User manual

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.

Contents

Getting started: Your first desklet

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.

The configuration file

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
}

User scripts

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.

Markups

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.

Context variables

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.

Widgets

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.

Rows and columns

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:

example1.jpg

Alignment of widgets

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

Script interface

Arguments

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.

The test_value context variable

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.

autoclear and autorender

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.

Return value

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.

Reference guide

A detailed description of the available widgets, context variables and commands follows. For context variables, their default value is indicated.

General context variables

test_delay = 5
Amount of time, in seconds, between calls to script test. Set it to 0 to disable test calls.
color = 'FFFFFFFF'
Current color. It is a string of four hex values: red, green, blue, opacity. The opacity is optional and defaults to 'FF'; eg, 'FF0000' is opaque red.
window.padding = 5
Space in pixels between the border of the window and the widgets.
window.click_anywhere = True
If False, only clicks on clickable widgets will generate a call to script click_widget, and clicks on the rest of the desklet's area will be ignored.
window.never_shrink = True
If True, the desklet will only change its size when more size is needed. Set it to False if the script generates content that varies in size and you don't mind the desklet changing its dimensions.
background.color = '1E1E1E64'
Color to be used to fill the desklet's background. Set it to None to make the desklet completely transparent.
background.border.color = None
Set it to a color to make the desklet's border visible.
background.border.padding = 0
If the border is visible, this is the space between the drawn border and the real desklet's border.
background.image = None
If you want to display an image as background, set this context variable to the image's filename. The image should be located in the icons/ directory.
error = None
If set to a string, this string will be shown as an error message on the next render phase. After displaying the error, the error context variable will be set to None again.
error.icon = 'error.png'
Error messages can be shown with an icon at the left. Set this context variable to None to show only the error message.
error.color = 'FF0000FF'
Color to use for text in error messages.
error.font = 'Vera/10'
Font and fontsize to use for text in error messages. The TTF font should be placed in the fonts/ directory, or in the system fonts path.
test_value = None
The special test value context variable. See The test_value context variable.
debug = False
If set to True, doityourself will output special debug information.
id = None
All widgets have an id string (you can see it turning debug to True). Id strings are useful in script click_widget (see Arguments) or with the setattr special command. By setting this context variable to any string, the next created widget will be assigned this id string; else, a default id will be assigned.
autoclear = True
Clear the defined widgets before a call to the script. See autoclear and autorender.
autorender = True
Display the defined widgets after a call to the script. See autoclear and autorender.
widget.min_size = 5
Minimum size, in pixels, that will be assigned to autosized widgets.
valign = 'center'
Alignment of widgets in the same row. Possible values are 'top', 'center' and 'bottom'.
halign = 'left'
Alignment of rows in the same column. Possible values are 'left', 'center' and 'right'.
vpadding = 3
Amount of vertical space, in pixels, between widgets.
hpadding = 3
Amount of horizontal space, in pixels, between widgets.

The widgets

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.

Text

Creation

A text widget is created by normal text (ie, no markup is needed).

Context variables

font = 'Vera/10'

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

text
The text string.
font
Same as the font context variable.

Horizontal and vertical spaces

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.

Horizontal and vertical lines

Creation

<hline width/>
<vline height/>

Both width and height can be set to -1 to be autosized.

Context variables

line.stipple = 0
Size of the stipple. Set it to a non-zero value to create a dashed line.

Attributes

stipple
Same as the line.stipple context variable.

Bar meters

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

bar_meter.padding = 1
Amount of space, in pixels, between the border and the inner bar.
bar_meter.color = None
Color to be used for the inner bar. If None, the current color is used.
bar_meter.border.color = None
Color to be used for the border. If None, the current color is used.
bar_meter.orientation = 'LR'
Orientation of the bar. Possible values: 'LR' (left to right), 'RL' (right to left), 'BT' (bottom to top), 'TB' (top to bottom).
bar_meter.logarithmic = False
If True, a logarithmic scale will be used instead of a linear one. Useful for when the values that should be displayed span several orders of magnitude. eg, if the actual value is 1.4 and the max value is 10000, you won't see anything in the bar meter, unless it is logarithmic.

Attributes

value
The value displayed by the meter.
max
The maximum value displayable by the meter.
color
Same as the bar_meter.color context variable.
border_color
Same as the bar_meter.border.color context variable.
orientation
Same as the bar_meter.orientation context variable.
logarithmic
Same as the bar_meter.logarithmic context variable.

Images

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

filename
The image's file name.

Buttons

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

button.highlight = True
Buttons will have a special highlighting effect when pointed at, unless created with this context variable set to False.

Attributes

highlight
Same as the button.highlight context variable.

Boxes

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

box.padding = 5
Space between the border of the box and the contained widgets.

Attributes

border_color
The color to use for the border. (The standard color attribute controls the fill color).
padding
Same as the box.padding context variable.

Special commands

clear

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.

render

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.

setattr

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.