Commit 8f98ff5d authored by epsi sayidina's avatar epsi sayidina

herbstluftwm combined event

parent 17e4df1c
#!/usr/bin/env bash
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# pipe
function handle_command_event() {
local monitor=$1
shift
local event=$@
# find out event origin
IFS=$'\t' column=($event);
origin=${column[0]}
# find out event origin
case $origin in
reload)
pkill dzen2
;;
quit_panel)
exit
;;
tag*)
# http://www.tldp.org/LDP/abs/html/x17837.html#HERESTRINGSREF
# echo "resetting tags" >&2
set_tag_value $monitor
;;
focus_changed|window_title_changed)
set_windowtitle "${column[2]}"
;;
interval)
set_datetime
;;
esac
}
function content_init() {
monitor=$1
# initialize statusbar before loop
set_tag_value $monitor
set_windowtitle ''
set_datetime
get_statusbar_text $monitor
echo $buffer
}
function content_event_idle() {
# wait for each event
herbstclient --idle
}
function content_event_interval() {
# endless loop
while :; do
echo "interval"
sleep 1
done
}
function content_walk() {
monitor=$1
{
content_event_idle &
pid_idle=$!
content_event_interval &
pid_interval=$!
} | while read event; do
handle_command_event $monitor "$event"
get_statusbar_text $monitor
echo $buffer
done
}
function run_dzen2() {
monitor=$1
shift
parameters=$@
command_out="dzen2 $parameters"
{
content_init $monitor
content_walk $monitor # loop for each event
} | $command_out
}
function detach_dzen2() {
monitor=$1
shift
parameters=$@
run_dzen2 $monitor $parameters &
}
function detach_transset() {
{
sleep 1
exec `(transset .8 -n dzentop >/dev/null)`
} &
}
module MyPipeHandler
( detachDzen2
, detachTransset
) where
import System.Process
import System.Posix.Types
import System.Exit
import GHC.IO.Handle
import System.IO
import System.Posix.Process
import Control.Concurrent
import Control.Monad
-- cabal install split
import Data.List.Split
import MyOutput
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- helper
-- for use with transset
wSleep :: Int -> IO ()
wSleep mySecond = threadDelay (1000000 * mySecond)
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- pipe
handleCommandEvent :: Int -> String -> IO ()
handleCommandEvent monitor event
| origin == "reload" = do system("pkill dzen2"); return ()
| origin == "quit_panel" = do exitSuccess; return ()
| elem origin tagCmds = do setTagValue monitor
| elem origin titleCmds = do setWindowtitle (column !! 2)
| origin == "interval" = do setDatetime
where
tagCmds = ["tag_changed", "tag_flags", "tag_added", "tag_removed"]
titleCmds = ["window_title_changed", "focus_changed"]
-- find out event origin
column = splitOn "\t" event
origin = column !! 0
contentInit :: Int -> Handle -> IO ()
contentInit monitor pipe_dzen2_in = do
-- initialize statusbar before loop
setTagValue monitor
setWindowtitle ""
setDatetime
text <- getStatusbarText monitor
hPutStrLn pipe_dzen2_in text
hFlush pipe_dzen2_in
contentEventIdle :: Handle -> IO ()
contentEventIdle pipe_cat_in = do
let command_in = "herbstclient"
(_, Just pipe_idle_out, _, ph) <-
createProcess (proc command_in ["--idle"])
{ std_out = CreatePipe }
forever $ do
-- wait for next event
event <- hGetLine pipe_idle_out
hPutStrLn pipe_cat_in event
hFlush pipe_cat_in
hClose pipe_idle_out
contentEventInterval :: Handle -> IO ()
contentEventInterval pipe_cat_in = forever $ do
hPutStrLn pipe_cat_in "interval"
hFlush pipe_cat_in
wSleep 1
contentWalk :: Int -> Handle -> IO ()
contentWalk monitor pipe_dzen2_in = do
(Just pipe_cat_in, Just pipe_cat_out, _, ph) <-
createProcess (proc "cat" [])
{ std_in = CreatePipe, std_out = CreatePipe }
forkProcess $ contentEventIdle(pipe_cat_in)
forkProcess $ contentEventInterval(pipe_cat_in)
forever $ do
-- wait for next event
event <- hGetLine pipe_cat_out
handleCommandEvent monitor event
text <- getStatusbarText monitor
hPutStrLn pipe_dzen2_in text
hFlush pipe_dzen2_in
hClose pipe_cat_out
hClose pipe_cat_in
runDzen2 :: Int -> [String] -> IO ()
runDzen2 monitor parameters = do
let command_out = "dzen2"
(Just pipe_dzen2_in, _, _, ph) <-
createProcess (proc command_out parameters)
{ std_in = CreatePipe }
contentInit monitor pipe_dzen2_in
contentWalk monitor pipe_dzen2_in -- loop for each event
hClose pipe_dzen2_in
detachDzen2 :: Int -> [String] -> IO ProcessID
detachDzen2 monitor parameters = forkProcess
$ runDzen2 monitor parameters
detachTransset :: IO ProcessID
detachTransset = forkProcess $ do
wSleep 1
system "transset .8 -n dzentop >/dev/null"
return ()
......@@ -76,9 +76,7 @@ contentEventIdle pipe_cat_in = do
contentEventInterval :: Handle -> IO ()
contentEventInterval pipe_cat_in = forever $ do
let timeText = "interval"
hPutStrLn pipe_cat_in timeText
hPutStrLn pipe_cat_in "interval"
hFlush pipe_cat_in
wSleep 1
......
......@@ -28,9 +28,9 @@ function _M.run_dzen2(monitor, parameters)
end
function _M.detach_dzen2(monitor, parameters)
local pid = posix.fork()
local pid_dzen2 = posix.fork()
if pid == 0 then -- this is the child process
if pid_dzen2 == 0 then -- this is the child process
_M.run_dzen2(monitor, parameters)
else -- this is the parent process
-- nothing
......@@ -38,12 +38,12 @@ function _M.detach_dzen2(monitor, parameters)
end
function _M.detach_transset()
local pid = posix.fork()
local pid_transset = posix.fork()
if pid == 0 then -- this is the child process
if pid_transset == 0 then -- this is the child process
common.sleep(1)
os.execute('transset .8 -n dzentop >/dev/null')
else -- this is the parent process
else -- this is the parent process
-- nothing
end
end
......
......@@ -68,9 +68,9 @@ function _M.run_dzen2(monitor, parameters)
end
function _M.detach_dzen2(monitor, parameters)
local pid = posix.fork()
local pid_dzen2 = posix.fork()
if pid == 0 then -- this is the child process
if pid_dzen2 == 0 then -- this is the child process
_M.run_dzen2(monitor, parameters)
else -- this is the parent process
-- nothing
......@@ -78,12 +78,12 @@ function _M.detach_dzen2(monitor, parameters)
end
function _M.detach_transset()
local pid = posix.fork()
local pid_transset = posix.fork()
if pid == 0 then -- this is the child process
if pid_transset == 0 then -- this is the child process
common.sleep(1)
os.execute('transset .8 -n dzentop >/dev/null')
else -- this is the parent process
else -- this is the parent process
-- nothing
end
end
......
-- luaposix available in AUR
local posix = require "posix"
local common = require('.common')
local helper = require('.helper')
local output = require('.output')
local _M = {}
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- helper
-- because os.clock function will hogs your cpu
function _M.os_sleep(n)
os.execute('sleep ' .. tonumber(n))
end
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- pipe
function _M.handle_command_event(monitor, event)
-- find out event origin
column = common.split(event, "\t")
origin = column[1] -- non zero based
tag_cmds = {'tag_changed', 'tag_flags', 'tag_added', 'tag_removed'}
title_cmds = {'window_title_changed', 'focus_changed'}
if origin == 'reload' then
os.execute('pkill dzen2')
elseif origin == 'quit_panel' then
os.exit()
elseif common.has_value(tag_cmds, origin) then
output.set_tag_value(monitor)
elseif common.has_value(title_cmds, origin) then
output.set_windowtitle(column[3])
elseif origin == 'interval' then
output.set_datetime()
end
end
function _M.content_init(monitor, pipe_dzen2_out)
-- initialize statusbar before loop
output.set_tag_value(monitor)
output.set_windowtitle('')
output.set_datetime()
local text = output.get_statusbar_text(monitor)
pipe_dzen2_out:write(text .. "\n")
pipe_dzen2_out:flush()
end
function _M.content_event_idle(pipe_cat_out)
local pid = posix.fork()
if pid == 0 then -- this is the child process
-- start a pipe
command_in = 'herbstclient --idle'
local pipe_in = assert(io.popen(command_in, 'r'))
-- wait for each event
for event in pipe_in:lines() do
posix.write(pipe_cat_out, event)
io.flush()
end -- for loop
pipein:close()
else -- this is the parent process
-- nothing
end
end
function _M.content_event_interval(pipe_cat_out)
local pid = posix.fork()
if pid == 0 then -- this is the child process
while true do
posix.write(pipe_cat_out, "interval\n")
io.flush()
_M.os_sleep(1)
end
else -- this is the parent process
-- nothing
end
end
function _M.content_walk(monitor, pipe_dzen2_out)
rd, wr = posix.pipe()
_M.content_event_idle(wr)
_M.content_event_interval(wr)
local bufsize = 4096
local event = ''
while true do
-- wait for next event, trim newline
event = common.trim1(posix.read(rd, bufsize))
if event == nil or #event == 0 then break end
_M.handle_command_event(monitor, event)
text = output.get_statusbar_text(monitor)
pipe_dzen2_out:write(text .. "\n")
pipe_dzen2_out:flush()
end -- not using for loop
posix.close(rd)
posix.close(wr)
end
function _M.run_dzen2(monitor, parameters)
local command_out = 'dzen2 ' .. parameters
local pipe_dzen2_out = assert(io.popen(command_out, 'w'))
_M.content_init(monitor, pipe_dzen2_out)
_M.content_walk(monitor, pipe_dzen2_out) -- loop for each event
pipe_dzen2_out:close()
end
function _M.detach_dzen2(monitor, parameters)
local pid_dzen2 = posix.fork()
if pid_dzen2 == 0 then -- this is the child process
_M.run_dzen2(monitor, parameters)
else -- this is the parent process
-- nothing
end
end
function _M.detach_transset()
local pid_transset = posix.fork()
if pid_transset == 0 then -- this is the child process
common.sleep(1)
os.execute('transset .8 -n dzentop >/dev/null')
else -- this is the parent process
-- nothing
end
end
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- return
return _M
......@@ -75,9 +75,7 @@ function _M.content_event_interval(pipe_cat_out)
if pid == 0 then -- this is the child process
while true do
local time_text = "interval\n"
posix.write(pipe_cat_out, time_text)
posix.write(pipe_cat_out, "interval\n")
io.flush()
_M.os_sleep(1)
......@@ -123,9 +121,9 @@ function _M.run_dzen2(monitor, parameters)
end
function _M.detach_dzen2(monitor, parameters)
local pid = posix.fork()
local pid_dzen2 = posix.fork()
if pid == 0 then -- this is the child process
if pid_dzen2 == 0 then -- this is the child process
_M.run_dzen2(monitor, parameters)
else -- this is the parent process
-- nothing
......@@ -133,12 +131,12 @@ function _M.detach_dzen2(monitor, parameters)
end
function _M.detach_transset()
local pid = posix.fork()
local pid_transset = posix.fork()
if pid == 0 then -- this is the child process
if pid_transset == 0 then -- this is the child process
common.sleep(1)
os.execute('transset .8 -n dzentop >/dev/null')
else -- this is the parent process
else -- this is the parent process
-- nothing
end
end
......
......@@ -41,16 +41,16 @@ sub detach_dzen2 {
my $monitor = shift;
my $parameters = shift;
my $pid = fork;
return if $pid; # in the parent process
my $pid_dzen2 = fork;
return if $pid_dzen2; # in the parent process
run_dzen2($monitor, $parameters);
exit;
}
sub detach_transset {
my $pid = fork;
return if $pid; # in the parent process
my $pid_transset = fork;
return if $pid_transset; # in the parent process
sleep 1;
system('transset .8 -n dzentop >/dev/null');
......
......@@ -93,16 +93,16 @@ sub detach_dzen2 {
my $monitor = shift;
my $parameters = shift;
my $pid = fork;
return if $pid; # in the parent process
my $pid_dzen2 = fork;
return if $pid_dzen2; # in the parent process
run_dzen2($monitor, $parameters);
exit;
}
sub detach_transset {
my $pid = fork;
return if $pid; # in the parent process
my $pid_transset = fork;
return if $pid_transset; # in the parent process
sleep 1;
system('transset .8 -n dzentop >/dev/null');
......
package pipehandler;
use warnings;
use strict;
# for tutorial purpose, we use two libraries
use IO::Pipe; # unidirectional
use IPC::Open2; # bidirectional
use File::Basename;
use lib dirname(__FILE__);
use output;
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# pipe
sub handle_command_event {
my $monitor = shift;
my $event = shift;
# find out event origin
my @column = split(/\t/, $event);
my $origin = $column[0];
if ($origin eq 'reload') {
system('pkill dzen2');
} elsif ($origin eq 'quit_panel') {
exit;
} elsif ( # avoiding the unstable ~~ smartmatch operator
($origin eq 'tag_changed')
or ($origin eq 'tag_flags')
or ($origin eq 'tag_added')
or ($origin eq 'tag_removed')
) {
output::set_tag_value($monitor);
} elsif ( ($origin eq 'window_title_changed')
or ($origin eq 'focus_changed')
) {
output::set_windowtitle($column[2]);
} elsif ($origin eq 'interval') {
output::set_datetime();
}
}
sub content_init {
my $monitor = shift;
my $pipe_dzen2_out = shift;
# initialize statusbar before loop
output::set_tag_value($monitor);
output::set_windowtitle('');
output::set_datetime();
my $text = output::get_statusbar_text($monitor);
print $pipe_dzen2_out $text."\n";
flush $pipe_dzen2_out;
}
sub content_event_idle {
my $pipe_cat_out = shift;
my $pid = fork;
return if $pid; # in the parent process
# start a pipe
my $pipe_idle_in = IO::Pipe->new();
my $command = 'herbstclient --idle';
my $handle = $pipe_idle_in->reader($command);
# wait for each event
my $event = '';
while ($event = <$pipe_idle_in>) {
print $pipe_cat_out $event;
flush $pipe_cat_out;
}
$pipe_idle_in->close();
}
sub content_event_interval {
my $pipe_cat_out = shift;
my $pid = fork;
return if $pid; # in the parent process
while(1) {
print $pipe_cat_out "interval\n";
flush $pipe_cat_out;
sleep 1;
}
}
sub content_walk {
my $monitor = shift;
my $pipe_dzen2_out = shift;
my ($rh_cat, $wh_cat);
my $pid_cat = open2 ($rh_cat, $wh_cat, 'cat')
or die "can't pipe sh: $!";
content_event_idle($wh_cat);
content_event_interval($wh_cat);
my $text = '';
my $event = '';
# wait for each event, trim newline
while (chomp($event = <$rh_cat>)) {
handle_command_event($monitor, $event);
$text = output::get_statusbar_text($monitor);
print $pipe_dzen2_out $text."\n";
flush $pipe_dzen2_out;
}
waitpid( $pid_cat, 0 );
}
sub run_dzen2 {
my $monitor = shift;
my $parameters = shift;
my $pipe_dzen2_out = IO::Pipe->new();
my $command = "dzen2 $parameters";
my $handle = $pipe_dzen2_out->writer($command);
content_init ($monitor, $pipe_dzen2_out);
content_walk ($monitor, $pipe_dzen2_out); # loop for each event
$pipe_dzen2_out->close();
}
sub detach_dzen2 {
my $monitor = shift;
my $parameters = shift;
my $pid_dzen2 = fork;
return if $pid_dzen2; # in the parent process
run_dzen2($monitor, $parameters);
exit;
}
sub detach_transset {
my $pid_transset = fork;
return if $pid_transset; # in the parent process
sleep 1;
system('transset .8 -n dzentop >/dev/null');
exit;
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# end of perl module
1;
......@@ -135,16 +135,16 @@ sub detach_dzen2 {
my $monitor = shift;
my $parameters = shift;
my $pid = fork;
return if $pid; # in the parent