First of all example plugins can be found in the
For a fun example of what a plugin can do take a look at the snake game:
cat /etc/skel/.config/tde/snake/init.lua | tde-client
Note: To stop the game press escape
Before writing your first plugin you need to understand where they need to be located.
Plugins are located in the
If the directory doesn't exist yet then create one.
mkdir -p "$HOME/.config/tde"
Each subdirectory in this directory is one plugin
Plugin configuration file
The configuration file to enable/disable plugins can be found in the following location
By default it looks like this:
# Notification widget plugins will be added in the notification center notification="widget.user-profile" notification="widget.social-media" notification="widget.weather" notification="widget.sars-cov-2" notification="widget.calculator" #module="hello-world" #settings="hello-world-widget" #topbar-right="icon_button" # topbar-left="icon_button" # topbar-center="icon_button" #settings="settings-app-widget"
As you can see by default tde already makes use of some plugins.
NOTE: plugins starting with
widgetare threated as internal widget implemented directly into
Modules: These plugins are simple scripts written in
luathat are ran in the background under the same process as widgets (thus they can manipulate widgets and more). Users usually don't see these plugins working.
- low battery notifier
- settings modifiers
- file watchers
- and many more.
You can compair then with daemons.
Widgets: Next you have widgets, these are the plugins you see every day. They are the GUI representation of a certain object. You can see them all over the place. Starting from the clock, package updater, wifi widget, workspaces, settings app and more. When writting a plugin you must take into consideration which one to use. Everything is allowed in a Module, however when writing a Widget you must inherit wibox and return such an object to be consumed by TDE.
This will be explained below
Plugins widgets can be placed in multiple locations around the user interface. In the configuration file you can specify where the widget should be placed. Here are the current widget locations.
settings- The widget will be placed at the bottom of the settings app (left menu)
topbar- The widget will be placed in the topbar on the right side next to all the buttons
notification center- The widget will be put in the notification center under the widget tab
My First Plugin
This part is interactive, it will guide you to make both a
Module and a
Widget, how to debug, testing out etc.
Follow this tutorial if you have never build a plugin before.
Setting up development environment
First of all, make sure you have wm-launch installed.
This will create a mock
TDE instance that you can test without messing up your real desktop environment.
It is highly recommended you use this and this tutorial will make great use of it.
Note: The above is not a hard requirement but makes debugging a lot more easily
To test if you installed wm-launch correctly execute the following command:
wm-launch -r 1080x1080
1080x1080option creates a window of size 1080 pixels x 1080 pixels, if your monitor is sufficiently large increase this number
Having autocompletion for
TDE is really usefull and makes developing a lot easier.
TDE only support autocomplete in VS Code using the following docs
Lets get started with your first module.
Firstly create a new directory in
mkdir -p "$HOME/.config/tde/my-first-module"
This directory will house everything related to your project.
Next we tell
TDE that we want to enable this module called
Edit the following file
~/.config/tos/plugins.conf and add the following:
The above line will make
tde use your module.
Next we will create the
lua file that is your plugins entrypoint
The file is located in
Write the following into that file
print("Hello, World!") print("This is executed from my plugin")
In essence you should have the following directory structure:
.config/ ├─ tos/ │ ├─ plugins.conf ├─ tde/ │ ├─ my-first-module/ │ │ ├─ init.lua
Run Your Plugin
Now lets run your plugin!
wm-launch is your best bet
Since you created the plugin and enabled it can simply launch the
Look at your terminal and wait a few seconds until you see the
Hello, World! and the
This is executed from my plugin lines appear somewhere in the output
In current session
Note: running arbitrary code in the current session could potentially break the system, make sure nothing wrong can happen The code you run can potentially contain leaks making the active session slow. This simple example couldn't hurt, but larger plugins can
First of all open 2 terminal.
- The first monitors the log file from the active session
- The second starts/activates your plugin.
Executed this command in the first terminal:
tail -f "$HOME/.cache/tde/stdout.log"
Executed this command in the seconds terminal:
cat "$HOME/.config/tde/my-first-module/init.lua" | tde-client
Afterwards check the first terminal, you should see your
Hello, World! and
This is executed from my plugin messages appear in the output.
tde-clientis an interface into the active session, it allows sending
commandsto the interpreter so that you can modify the behaviour of
More advanced example
Great you created your first module, of course you can do more than printing to
Since you are writing
lua you have full control over the plugin.
Lets take a more advanced example. A plugin that performs 2 simple tasks. 1. Execute a shell script 2. Plays a sound once the script finished
init.lua file and add the following content
-- include some required modules local spawn = awful.spawn -- this is an example of the default 'pop' sound that tos uses, change the file to your liking local function play_sound() spawn("paplay /etc/xdg/tde/sound/audio-pop.wav") end -- This function gets called when our shell script is done executing -- In our example we don't make use of the parameters local function done_callback(stdout, stderr, reason, exitcode) print("Done executing shell script") print("STDOUT:") print(stdout) play_sound() end -- start of this plugin print('Plugin Loaded') play_sound() -- pop sound -- lets execute a simple shell script local cmd = [[ echo 'Script started' sleep 5 echo 'Script stopped' ]] -- and execute it, we 'bind' the done_callback function to this shell script spawn.easy_async_with_shell(cmd, done_callback)
The only build in module we use is called awful.spawn
Now execute your plugin as noted in the last section and see what happens.
This section will be explained in the future
Now that you have followed the tutorial and created both a basic
Widget you can explore the documentation.
Learn about the api and what
TDE directly has to offer.
Some useful resources: