Preface
Goal: Separate Main Flow, Code, and Data.
So anyone can focus to alter special customization in Main Script, without changing the whole stuff.
Which PHP
Since there many PHP version. I should say that I use PHP7. But don’t worry, it is portable. I do not use any sophisticated code.
Reading
Before you jump off to scripting, you might desire to read this overview.
All The Source Code:
Impatient coder like me, like to open many tab on browser.
Table of Content
-
Preface: Table of Content
-
3: System Calls
-
6: Hash: Config
-
10: Run Baby Run
1: Directory Structure
Directory Structure has been explained in preface.
This figure will explain how it looks
in PHP script
directory.
2: Modularizing in PHP
Nothing to say here. PHP is simple
Declare a module
No need to explicitly define what to export.
Nothing to write in helper Script
Call a module
require_once('helper.php');
3: System Calls
Here we wrap herbstclient
system call
in a function named hc
.
helper.php
function hc($arguments)
{
system("herbstclient $arguments");
}
autostart.php
# Read the manual in $ man herbstluftwm
hc('emit_hook reload');
# gap counter
system("echo 35 > /tmp/herbstluftwm-gap");
4: Array: Tag Names and Keys
config.php
$tag_names = range(1, 9);
$tag_keys = array_merge(range(1, 9), [0]);
5: Hash: Color Schemes
Using key-value pairs, a simple data structure.
gmc.php
$color = array(
'white' => '#ffffff',
'black' => '#000000',
'grey50' => '#fafafa',
'grey100' => '#f5f5f5',
);
autostart.php
# background before wallpaper
system("xsetroot -solid '".COLOR['blue500']."'");
View Source File:
6: Hash: Config
The Hash in Config is very similar with the colors above. Except that it has string interpolation all over the place.
config.php
# Modifier variables
$s = 'Shift';
$c = 'Control';
$m = 'Mod4';
$a = 'Mod1';
$keybinds = array(
# session
"$m-$s-q" => 'quit',
"$m-$s-r" => 'reload',
"$m-$s-c" => 'close'
)
This config will be utilized in main script as shown in the following code.
autostart.php
do_config("keybind", $keybinds);
do_config("keybind", $tagskeybinds);
do_config("mousebind", $mousebinds);
do_config("attr", $attributes);
do_config("set", $sets);
do_config("rule", $rules);
View Source File:
7: Processing The Hash Config
This is the heart of this script.
This do-config
function has two arguments,
the herbstclient command i.e “keybind”, and hash from config.
I can see how simple and clean, PHP is.
helper.php
function do_config($command, $hash)
{
# loop over hash
foreach ($hash as $key => $value) {
hc($command.' '.$key.' '.$value);
# uncomment to debug in terminal
# echo $command.' '.$key.' '.$value."\n";
}
}
Debug Herbstclient Command
I do not remove line where I do debug when I made this script, so anyone can use it later, avoid examining blindly. Sometimes strange things happen. Just uncomment this line to see what happened.
echo $command.' '.$key.' '.$value."\n";
You can see the debugging result in figure below.
View Source File:
8: Setting the Tags
Nothing special here, PHP read all exported variable from modules, but PHP function do not read the varable unless it defined global.
helper.php
function set_tags_with_name()
{
global $tag_names, $tag_keys;
hc("rename default '$tag_names[0]' 2>/dev/null || true");
foreach($tag_names as $index=>$value) {
hc("add '$value'");
$key = $tag_keys[$index];
if (!empty($key)) {
hc("keybind Mod4-$key use_index '$index'");
hc("keybind Mod4-Shift-$key move_index '$index'");
}
}
}
9: Launch the Panel
Two more functions left, it is do_panel
and startup_run
.
This two also be easy to do in PHP.
helper.php
function do_panel()
{
$panel = __dir__."/panel-lemonbar.php";
if (!is_executable($panel))
$panel = "/etc/xdg/herbstluftwm/panel.sh";
$raw = shell_exec('herbstclient list_monitors | cut -d: -f1');
$monitors = explode("\n", trim($raw));
foreach ($monitors as $monitor) {
# start it on each monitor
system("$panel $monitor > /dev/null &"); // no $output
}
}
10: Run Baby Run
This is the last part. It is intended to be modified. Everyone has their own personal preferences.
startup.php
function startup_run()
{
$command = 'silent new_attr bool my_not_first_autostart';
system("herbstclient $command", $exitcode);
# without redirection your app WILL HANG !
if ( ! ((bool) trim($exitcode)) ) {
# non windowed app
system("compton > /dev/null &");
system("dunst > /dev/null &");
system("parcellite > /dev/null &");
system("nitrogen --restore > /dev/null &");
system("mpd > /dev/null &");
# windowed app
exec("xfce4-terminal > /dev/null 2>&1 &");
exec("firefox > /dev/null 2>&1 &");
exec("geany > /dev/null 2>&1 &");
exec("thunar > /dev/null 2>&1 &");
}
}
Specific PHP Issue
Without redirection, your script will hang.
Be aware of the > /dev/null &
part in PHP.
It is mandatory for running background processing.
The PHP manual has said it clearly.
View Source File:
11: Putting It All Together
The last part is going to main script and putting it all back together.
Now the flow is clear
Header Part: autostart.php
require_once('gmc.php');
require_once('helper.php');
require_once('config.php');
require_once('startup.php');
Procedural Part: autostart.php
# background before wallpaper
system("xsetroot -solid '".COLOR['blue500']."'");
# Read the manual in $ man herbstluftwm
hc('emit_hook reload');
# gap counter
system("echo 35 > /tmp/herbstluftwm-gap");
# do not repaint until unlock
hc("lock");
# standard
hc('keyunbind --all');
hc("mouseunbind --all");
hc("unrule -F");
set_tags_with_name();
# do hash config
do_config("keybind", $keybinds);
do_config("keybind", $tagskeybinds);
do_config("mousebind", $mousebinds);
do_config("attr", $attributes);
do_config("set", $sets);
do_config("rule", $rules);
# unlock, just to be sure
hc("unlock");
# launch statusbar panel
do_panel();
# load on startup
startup_run();
View Source File:
Coming up Next
After the Window Manager, comes the Panel.
Happy Configuring.