Commit 17e4df1c authored by epsi sayidina's avatar epsi sayidina

herbstluftwm idle event

parent ae1fb7bc
......@@ -11,8 +11,9 @@ readonly tag_shows=( "一 ichi" "二 ni" "三 san" "四 shi"
"五 go" "六 roku" "七 shichi" "八 hachi" "九 kyū" "十 jū")
# initialize variable segment
segment_windowtitle='';
segment_windowtitle=''; # empty string
tags_status=(); # empty array
segment_datetime=''; # empty string
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# decoration
......@@ -46,6 +47,10 @@ function get_statusbar_text() {
text+=$buffer
done
# draw date and time
output_by_datetime
text+=$buffer
# draw window title
output_by_title
text+=$buffer
......@@ -108,6 +113,12 @@ function output_by_title() {
buffer=$text
}
function output_by_datetime() {
local text=" ^r(5x0) $separator ^r(5x0) "
text+="$segment_datetime"
buffer=$text
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# setting variables, response to event handler
......@@ -125,3 +136,15 @@ function set_windowtitle() {
segment_windowtitle=" $icon ^bg()^fg(${color['grey700']}) $windowtitle"
}
function set_datetime() {
local date_icon="$pre_icon$post_icon"
local date_str=$(date +'%a %b %d')
local date_text="$date_icon ^bg()^fg(${color['grey700']}) $date_str"
local time_icon="$pre_icon$post_icon"
local time_str=$(date +'%H:%M:%S')
local time_text="$time_icon ^bg()^fg(${color['blue500']}) $time_str"
segment_datetime="$date_text $time_text"
}
......@@ -6,7 +6,6 @@
function content_init() {
monitor=$1
# initialize statusbar before loop
set_tag_value $monitor
set_windowtitle ''
......
......@@ -9,7 +9,7 @@ function handle_command_event() {
local event=$@
# find out event origin
IFS=$'\t' column=($event);
IFS=$'\t' column=($event);
origin=${column[0]}
# find out event origin
......@@ -28,6 +28,9 @@ function handle_command_event() {
focus_changed|window_title_changed)
set_windowtitle "${column[2]}"
;;
interval)
set_datetime
;;
esac
}
......@@ -37,24 +40,41 @@ function content_init() {
# initialize statusbar before loop
set_tag_value $monitor
set_windowtitle ''
set_datetime
get_statusbar_text $monitor
echo $buffer
}
function content_walk() {
monitor=$1
function content_event_idle() {
# wait for each event
herbstclient --idle
}
# start a pipe
command_in='herbstclient --idle'
function content_event_interval() {
# endless loop
while :; do
echo "interval"
sleep 1
done
}
# wait for each event
$command_in | while read event; do
handle_command_event $monitor "$event"
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
get_statusbar_text $monitor
echo $buffer
done
}
function run_dzen2() {
......
module MyOutput
( setWindowtitle
, setTagValue
( setTagValue
, setWindowtitle
, setDatetime
, getStatusbarText
) where
......@@ -12,6 +13,9 @@ import System.IO
import Control.Monad
import Data.Time.LocalTime
import Data.Time.Format
import MyGMC
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
......@@ -29,10 +33,13 @@ tagShows = ["一 ichi", "二 ni", "三 san", "四 shi",
-- simulate global variable using unsafe
segmentWindowtitle :: IORef String
segmentWindowtitle = unsafePerformIO $ newIORef ""
segmentWindowtitle = unsafePerformIO $ newIORef "" -- empty string
tagsStatus :: IORef [String]
tagsStatus = unsafePerformIO $ newIORef []
tagsStatus = unsafePerformIO $ newIORef [] -- empty string list
segmentDatetime :: IORef String
segmentDatetime = unsafePerformIO $ newIORef "" -- empty string
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- decoration
......@@ -53,16 +60,25 @@ preIcon = "^fg(" ++ myColor "yellow500" ++ ")" ++ fontAwesome
postIcon = "^fn()^fg()"
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- main
-- helper
wFormatTime :: FormatTime t => t -> String -> String
wFormatTime myUtcTime myTimeFormat = formatTime
Data.Time.Format.defaultTimeLocale myTimeFormat myUtcTime
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- main
getStatusbarText :: Int -> IO String
getStatusbarText monitor = do
tags <- readIORef tagsStatus
let tagText = join $ map (outputByTag monitor) tags
let titleText = outputByTitle
let text = (tagText ++) <$> titleText
text
timeText <- outputByDatetime
titleText <- outputByTitle
let text = tagText ++ timeText ++ titleText
return text
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- each segments
......@@ -115,6 +131,13 @@ outputByTitle = do
return text
outputByDatetime :: IO String
outputByDatetime = do
segment <- readIORef segmentDatetime
let text = " ^r(5x0) " ++ separator ++ " ^r(5x0) " ++ segment
return text
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- setting variables, response to event handler
--import Data.IORef
......@@ -139,3 +162,23 @@ setWindowtitle windowtitle = do
let text = " " ++ icon ++ " ^bg()"
++ "^fg(" ++ myColor "grey700" ++ ") " ++ windowtitle
writeIORef segmentWindowtitle text
formatDatetime :: ZonedTime -> String
formatDatetime now = dateText ++ " " ++ timeText
where
dateStr = wFormatTime now "%a %b %d"
timeStr = wFormatTime now "%H:%M:%S"
dateIcon = preIcon ++ "\61555" ++ postIcon
timeIcon = preIcon ++ "\61463" ++ postIcon
dateText = " " ++ dateIcon ++ " ^bg()"
++ "^fg(" ++ myColor "grey700" ++ ") " ++ dateStr
timeText = " " ++ timeIcon ++ " ^bg()"
++ "^fg(" ++ myColor "blue500" ++ ") " ++ timeStr
setDatetime :: IO ()
setDatetime = do
now <- getZonedTime
writeIORef segmentDatetime $ formatDatetime now
......@@ -32,7 +32,6 @@ wSleep mySecond = threadDelay (1000000 * mySecond)
contentInit :: Int -> Handle -> IO ()
contentInit monitor pipe_dzen2_in = do
-- initialize statusbar before loop
setTagValue monitor
setWindowtitle ""
......
......@@ -36,6 +36,7 @@ handleCommandEvent monitor event
| 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"]
......@@ -49,23 +50,51 @@ 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
contentWalk :: Int -> Handle -> IO ()
contentWalk monitor pipe_dzen2_in = do
contentEventIdle :: Handle -> IO ()
contentEventIdle pipe_cat_in = do
let command_in = "herbstclient"
(_, Just pipe_idle_out, _, ph) <-
(_, Just pipe_idle_out, _, ph) <-
createProcess (proc command_in ["--idle"])
{ std_out = CreatePipe }
forever $ do
-- wait for next event
event <- hGetLine pipe_idle_out
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
let timeText = "interval"
hPutStrLn pipe_cat_in timeText
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
......@@ -73,7 +102,8 @@ contentWalk monitor pipe_dzen2_in = do
hPutStrLn pipe_dzen2_in text
hFlush pipe_dzen2_in
hClose pipe_idle_out
hClose pipe_cat_out
hClose pipe_cat_in
runDzen2 :: Int -> [String] -> IO ()
runDzen2 monitor parameters = do
......
......@@ -15,8 +15,9 @@ _M.tag_shows = {'一 ichi', '二 ni', '三 san', '四 shi',
'五 go', '六 roku', '七 shichi', '八 hachi', '九 kyū', '十 jū'}
-- initialize variable segment
_M.segment_windowtitle = ''
_M.tags_status = {}
_M.segment_windowtitle = '' -- empty string
_M.tags_status = {} -- empty table
_M.segment_datetime = '' -- empty string
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- decoration
......@@ -47,7 +48,10 @@ function _M.get_statusbar_text(monitor)
for index = 1, #(_M.tags_status) do
text = text .. _M.output_by_tag(monitor, _M.tags_status[index])
end
-- draw date and time
text = text .. _M.output_by_datetime()
-- draw window title
text = text .. _M.output_by_title()
......@@ -115,6 +119,13 @@ function _M.output_by_title()
return text
end
function _M.output_by_datetime()
local text = ' ^r(5x0) ' .. _M.separator .. ' ^r(5x0) '
.. _M.segment_datetime
return text
end
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- setting variables, response to event handler
......@@ -130,13 +141,25 @@ end
function _M.set_windowtitle(windowtitle)
local icon = _M.pre_icon .. '' .. _M.post_icon
if (windowtitle == nil) then windowtitle = '' end
_M.segment_windowtitle = ' ' .. icon ..
' ^bg()^fg(' .. gmc.color['grey700'] .. ') ' .. windowtitle
end
function _M.set_datetime()
local date_icon = _M.pre_icon .. '' .. _M.post_icon
local date_str = os.date('%a %b %d')
local date_text = date_icon .. ' ^bg()'
.. '^fg(' .. gmc.color['grey700'] .. ') ' .. date_str
local time_icon = _M.pre_icon .. '' .. _M.post_icon
local time_str = os.date('%H:%M:%S')
local time_text = time_icon .. ' ^bg()'
.. '^fg(' .. gmc.color['blue500'] .. ') ' .. time_str
_M.segment_datetime = date_text .. ' ' .. time_text
end
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- return
......
......@@ -11,7 +11,6 @@ local _M = {}
-- pipe
function _M.content_init(monitor, pipe_dzen2_out)
-- initialize statusbar before loop
output.set_tag_value(monitor)
output.set_windowtitle('')
......
......@@ -44,10 +44,10 @@ function _M.content_walk(monitor, pipe_dzen2_out)
command_in = 'herbstclient --idle'
local pipe_idle_in = assert(io.popen(command_in, 'r'))
local text = ''
-- wait for each event
-- wait for each event, trim newline
for event in pipe_idle_in:lines() do
_M.handle_command_event(monitor, event)
_M.handle_command_event(monitor, common.trim1(event))
text = output.get_statusbar_text(monitor)
pipe_dzen2_out:write(text .. "\n")
......
......@@ -7,6 +7,14 @@ 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
......@@ -26,6 +34,8 @@ function _M.handle_command_event(monitor, event)
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
......@@ -33,28 +43,73 @@ 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_walk(monitor, pipe_dzen2_out)
-- start a pipe
command_in = 'herbstclient --idle'
local pipe_idle_in = assert(io.popen(command_in, 'r'))
local text = ''
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_idle_in:lines() do
-- 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
local time_text = "interval\n"
posix.write(pipe_cat_out, time_text)
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 -- for loop
pipe_idle_in:close()
end -- not using for loop
posix.close(rd)
posix.close(wr)
end
function _M.run_dzen2(monitor, parameters)
......
......@@ -21,9 +21,9 @@ use constant TAG_SHOWS => ['一 ichi', '二 ni', '三 san', '四 shi',
'五 go', '六 roku', '七 shichi', '八 hachi', '九 kyū', '十 jū'];
# initialize variable segment
my $segment_windowtitle = '';
my @tags_status = [];
my $segment_datetime = '';
my $segment_windowtitle = ''; # empty string
my @tags_status = []; # empty array
my $segment_datetime = ''; # empty string
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# decoration
......@@ -55,8 +55,8 @@ sub get_statusbar_text {
$text .= output_by_tag($monitor, $tag_status);
}
# draw window title
# $text .= output_by_datetime();
# draw date and time
$text .= output_by_datetime();
# draw window title
$text .= output_by_title();
......@@ -152,9 +152,9 @@ sub set_datetime {
my $time_icon = PRE_ICON."".POST_ICON;
my $time_format = '%H:%M:%S';
my $time_str = localtime->strftime($time_format);
my $time_text = "$date_icon ^bg()^fg($color{'blue500'}) $time_str";
my $time_text = "$time_icon ^bg()^fg($color{'blue500'}) $time_str";
$segment_datetime = "$date_text $time_text";
$segment_datetime = "$date_text $time_text";
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
......
......@@ -17,7 +17,6 @@ sub content_init {
my $monitor = shift;
my $pipe_dzen2_out = shift;
# initialize statusbar before loop
output::set_tag_value($monitor);
output::set_windowtitle('');
......
......@@ -64,8 +64,8 @@ sub content_walk {
my $text = '';
my $event = '';
# wait for each event
while($event = <$pipe_idle_in>) {
# wait for each event, trim newline
while (chomp($event = <$pipe_idle_in>)) {
handle_command_event($monitor, $event);
$text = output::get_statusbar_text($monitor);
......
......@@ -3,7 +3,9 @@ package pipehandler;
use warnings;
use strict;
use IO::Pipe;
# for tutorial purpose, we use two libraries
use IO::Pipe; # unidirectional
use IPC::Open2; # bidirectional
use File::Basename;
use lib dirname(__FILE__);
......@@ -15,7 +17,7 @@ use output;
sub handle_command_event {
my $monitor = shift;
my $event = shift;
my $event = shift;
# find out event origin
my @column = split(/\t/, $event);
......@@ -36,6 +38,8 @@ sub handle_command_event {
or ($origin eq 'focus_changed')
) {
output::set_windowtitle($column[2]);
} elsif ($origin eq 'interval') {
output::set_datetime();
}
}
......@@ -46,34 +50,72 @@ sub content_init {
# 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_walk {
my $monitor = shift;
my $pipe_dzen2_out = shift;
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);
my $text = '';
# wait for each event
my $event = '';
while ($event = <$pipe_idle_in>) {
print $pipe_cat_out $event;
flush $pipe_cat_out;
}
# wait for each event
while($event = <$pipe_idle_in>) {
handle_command_event($monitor, $event);
$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;
$text = output::get_statusbar_text($monitor);
print $pipe_dzen2_out $text;
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;
}
$pipe_idle_in->close();
waitpid( $pid_cat, 0 );
}
sub run_dzen2 {
......
......@@ -12,8 +12,9 @@ const TAG_SHOWS = ['一 ichi', '二 ni', '三 san', '四 shi',
'五 go', '六 roku', '七 shichi', '八 hachi', '九 kyū', '十 jū'];
// initialize variable segment
$segment_windowtitle = '';
$tags_status = [];
$segment_windowtitle = ''; # empty string
$tags_status = []; # empty array
$segment_datetime = ''; # empty string
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# decoration
......@@ -46,6 +47,9 @@ function get_statusbar_text($monitor)
$text .= output_by_tag($monitor, $tag_status);
}
//# draw date and time
$text .= output_by_datetime();
// draw window title
$text .= output_by_title();
......@@ -112,6 +116,16 @@ function output_by_title()
return $text;
}
function output_by_datetime()
{
global $segment_datetime;