Commit d0d24b0c authored by epsi sayidina's avatar epsi sayidina

herbstluftwm tags with dzen2

parent 06287f33
__pycache__/
*.py[cod]
*.hi
*.o
*.swp
*.swo
#!/usr/bin/env bash
content() {
while true ; do
statusbar_text
handle_cmd_event
done
### dzen2 ###
# After the data is gathered and processed, the output of the previous block
# gets piped to dzen2.
}
statusbar_text() {
### Output ###
# This part prints dzen data based on the _previous_ data handling run,
# and then waits for the next event to happen.
text=''
# draw tags
for i in "${tags[@]}" ; do
text+=$(output_by_tagmark_pre $i)
text+=$(output_by_tagnumber $i)
text+=$(output_by_tagmark_post $i)
done
text+=$(output_leftside_top)
echo $text
}
handle_cmd_event() {
### Data handling ###
# This part handles the events generated in the event loop, and sets
# internal variables based on them. The event and its arguments are
# read into the array cmd, then action is taken depending on the event
# name.
# "Special" events (quit_panel/togglehidepanel/reload) are also handled
# here.
# wait for next event
IFS=$'\t' read -ra cmd || break
# find out event origin
case "${cmd[0]}" in
reload)
pkill dzen2
exit
;;
quit_panel)
exit
;;
tag*)
# http://www.tldp.org/LDP/abs/html/x17837.html#HERESTRINGSREF
# echo "resetting tags" >&2
set_tag_value
;;
focus_changed|window_title_changed)
set_windowtitle "${cmd[@]:2}"
;;
esac
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# Initial Value
init_segments() {
set_windowtitle ""
set_tag_value
}
# #!/usr/bin/env bash
#!/usr/bin/env bash
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# google material colors
......
# #!/usr/bin/env bash
#!/usr/bin/env bash
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# helpers
......
# #!/usr/bin/env bash
#!/usr/bin/env bash
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# initialize
......@@ -55,8 +55,7 @@ function get_statusbar_text() {
function output_by_tag() {
local monitor=$1
local tag_status=$2
local text=''
local tag_status=$2
local tag_index=${tag_status:1:1}
local tag_mark=${tag_status:0:1}
......@@ -64,19 +63,20 @@ function output_by_tag() {
# ----- pre tag
local text_pre=''
case $tag_mark in
'#')
text+="^bg(${color['blue500']})^fg(${color['black']})"
text+=$right_hard_arrow
text+="^bg(${color['blue500']})^fg(${color['white']})"
text_pre+="^bg(${color['blue500']})^fg(${color['black']})"
text_pre+=$right_hard_arrow
text_pre+="^bg(${color['blue500']})^fg(${color['white']})"
;;
'+') text+="^bg(${color['yellow500']})^fg(${color['grey400']})"
'+') text_pre+="^bg(${color['yellow500']})^fg(${color['grey400']})"
;;
':') text+="^bg()^fg(${color['white']})"
':') text_pre+="^bg()^fg(${color['white']})"
;;
'!') text+="^bg(${color['red500']})^fg(${color['white']})"
'!') text_pre+="^bg(${color['red500']})^fg(${color['white']})"
;;
*) text+="^bg()^fg(${color['grey600']})"
*) text_pre+="^bg()^fg(${color['grey600']})"
;;
esac
......@@ -84,18 +84,20 @@ function output_by_tag() {
# assuming using dzen2_svn
# clickable tags if using SVN dzen
text+="^ca(1,herbstclient focus_monitor \"$monitor\" && "
text+="herbstclient use \"$tag_index\") $tag_name ^ca() "
local text_name=''
text_name+="^ca(1,herbstclient focus_monitor \"$monitor\" && "
text_name+="herbstclient use \"$tag_index\") $tag_name ^ca() "
# ----- post tag
local text_post=''
if [ $tag_mark = '#' ]
then
text+="^bg(${color['black']})^fg(${color['blue500']})"
text+=$right_hard_arrow;
text_post+="^bg(${color['black']})^fg(${color['blue500']})"
text_post+=$right_hard_arrow;
fi
buffer=$text
buffer="$text_pre$text_name$text_post"
}
function output_leftside_top() {
......
#!/usr/bin/env bash
# This is a modularized config for herbstluftwm tags in dzen2 statusbar
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# libraries
......@@ -21,8 +22,6 @@ herbstclient pad $monitor $panel_height 0 $panel_height 0
get_dzen2_parameters $monitor $panel_height
# init_segments
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# pipe
......@@ -32,10 +31,5 @@ pkill dzen2
# run process in the background
detach_dzen2 $monitor $dzen2_parameters
# By redirecting stderr to /dev/null,
# you effectively suppress these messages.
# 2> /dev/null
#hc --idle 2> /dev/null | content 2> /dev/null | dzen2 $dzen2_parameters &
# optional transparency
detach_transset
# #!/usr/bin/env bash
#!/usr/bin/env bash
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# pipe
......
module MyGMC (myColor, colorSchemes) where
-- colorschemes
import Data.Map as M
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- google material colors
-- https://material.io/guidelines/style/color.html
-- Color names are easier to remember:
-- Signature/ Declaration of Associative Array/ Hash/ Dictionary/ Map
colorSchemes :: [(String, String)]
colorSchemes =
[("white", "#ffffff")
,("black", "#000000")
,("grey50", "#fafafa")
,("grey100", "#f5f5f5")
,("grey200", "#eeeeee")
,("grey300", "#e0e0e0")
,("grey400", "#bdbdbd")
,("grey500", "#9e9e9e")
,("grey600", "#757575")
,("grey700", "#616161")
,("grey800", "#424242")
,("grey900", "#212121")
,("red50", "#ffebee")
,("red100", "#ffcdd2")
,("red200", "#ef9a9a")
,("red300", "#e57373")
,("red400", "#ef5350")
,("red500", "#f44336")
,("red600", "#e53935")
,("red700", "#d32f2f")
,("red800", "#c62828")
,("red900", "#b71c1c")
,("redA100", "#ff8a80")
,("redA200", "#ff5252")
,("redA400", "#ff1744")
,("redA700", "#d50000")
,("pink50", "#fce4ec")
,("pink100", "#f8bbd0")
,("pink200", "#f48fb1")
,("pink300", "#f06292")
,("pink400", "#ec407a")
,("pink500", "#e91e63")
,("pink600", "#d81b60")
,("pink700", "#c2185b")
,("pink800", "#ad1457")
,("pink900", "#880e4f")
,("pinkA100", "#ff80ab")
,("pinkA200", "#ff4081")
,("pinkA400", "#f50057")
,("pinkA700", "#c51162")
,("blue50", "#e3f2fd")
,("blue100", "#bbdefb")
,("blue200", "#90caf9")
,("blue300", "#64b5f6")
,("blue400", "#42a5f5")
,("blue500", "#2196f3")
,("blue600", "#1e88e5")
,("blue700", "#1976d2")
,("blue800", "#1565c0")
,("blue900", "#0d47a1")
,("blueA100", "#82b1ff")
,("blueA200", "#448aff")
,("blueA400", "#2979ff")
,("blueA700", "#2962ff")
,("yellow50", "#fffde7")
,("yellow100", "#fff9c4")
,("yellow200", "#fff59d")
,("yellow300", "#fff176")
,("yellow400", "#ffee58")
,("yellow500", "#ffeb3b")
,("yellow600", "#fdd835")
,("yellow700", "#fbc02d")
,("yellow800", "#f9a825")
,("yellow900", "#f57f17")
,("yellowA100", "#ffff8d")
,("yellowA200", "#ffff00")
,("yellowA400", "#ffea00")
,("yellowA700", "#ffd600")
,("teal50", "#e0f2f1")
,("teal100", "#b2dfdb")
,("teal200", "#80cbc4")
,("teal300", "#4db6ac")
,("teal400", "#26a69a")
,("teal500", "#009688")
,("teal600", "#00897b")
,("teal700", "#00796b")
,("teal800", "#00695c")
,("teal900", "#004d40")
,("tealA100", "#a7ffeb")
,("tealA200", "#64ffda")
,("tealA400", "#1de9b6")
,("tealA700", "#00bfa5")
,("green50", "#e8f5e9")
,("green100", "#c8e6c9")
,("green200", "#a5d6a7")
,("green300", "#81c784")
,("green400", "#66bb6a")
,("green500", "#4caf50")
,("green600", "#43a047")
,("green700", "#388e3c")
,("green800", "#2e7d32")
,("green900", "#1b5e20")
,("greenA100", "#b9f6ca")
,("greenA200", "#69f0ae")
,("greenA400", "#00e676")
,("greenA700", "#00c853")
,("orange50", "#fff3e0")
,("orange100", "#ffe0b2")
,("orange200", "#ffcc80")
,("orange300", "#ffb74d")
,("orange400", "#ffa726")
,("orange500", "#ff9800")
,("orange600", "#fb8c00")
,("orange700", "#f57c00")
,("orange800", "#ef6c00")
,("orange900", "#e65100")
,("orangeA100", "#ffd180")
,("orangeA200", "#ffab40")
,("orangeA400", "#ff9100")
,("orangeA700", "#ff6d00")
,("deepOrange50", "#fbe9e7")
,("deepOrange100", "#ffccbc")
,("deepOrange200", "#ffab91")
,("deepOrange300", "#ff8a65")
,("deepOrange400", "#ff7043")
,("deepOrange500", "#ff5722")
,("deepOrange600", "#f4511e")
,("deepOrange700", "#e64a19")
,("deepOrange800", "#d84315")
,("deepOrange900", "#bf360c")
,("deepOrangeA100", "#ff9e80")
,("deepOrangeA200", "#ff6e40")
,("deepOrangeA400", "#ff3d00")
,("deepOrangeA700", "#dd2c00")
]
myColor :: String -> String
myColor key = M.findWithDefault "#ffffff" key (fromList colorSchemes)
module MyHelper
( getMonitor
, getGeometry
, getDzen2Parameters
) where
import System.Process
import System.IO
import System.Exit
import Control.Monad
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- helpers
getMonitor :: [String] -> Int
getMonitor args
| length(args) > 0 = read (args !! 0) :: Int
| otherwise = 0
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- geometry calculation
getGeometry :: Int -> IO [Int]
getGeometry monitor = do
let args = ["monitor_rect", show(monitor)]
(_, Just pipe_out, _, ph) <-
createProcess (proc "herbstclient" args)
{ std_out = CreatePipe }
raw <- hGetContents pipe_out
_ <- waitForProcess ph
when (raw == "") $ do
putStrLn $ "Invalid monitor " ++ show(monitor)
exitSuccess
let geometry = map (read::String->Int) (words raw)
return geometry
-- geometry has the format X Y W H
data XYWH = XYWH String String String String
getTopPanelGeometry :: Int -> [Int] -> XYWH
getTopPanelGeometry
height geometry = XYWH
(show (geometry !! 0))
(show (geometry !! 1))
(show (geometry !! 2))
(show height)
getBottomPanelGeometry :: Int -> [Int] -> XYWH
getBottomPanelGeometry
height geometry = XYWH
(show (geometry !! 0))
(show ((geometry !! 3) - height))
(show (geometry !! 2))
(show height)
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- dzen Parameters
getDzen2Parameters :: Int -> [Int] -> [String]
getDzen2Parameters
panelHeight geometry = [
"-x", xpos, "-y", ypos,
"-w", width, "-h", height,
"-fn", font,
"-ta", "l",
"-bg", bgcolor,
"-fg", fgcolor,
"-title-name", "dzentop"
]
where
XYWH xpos ypos width height = getTopPanelGeometry
panelHeight geometry
bgcolor = "#000000"
fgcolor = "#ffffff"
font = "-*-takaopgothic-medium-*-*-*-12-*-*-*-*-*-*-*"
module MyOutput
( setWindowtitle
, setTagValue
, getStatusbarText
) where
import Data.IORef
import System.IO.Unsafe
import qualified Data.Text as T
import System.Process
import System.IO
import Control.Monad
import MyGMC
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- initialize
-- custom tag names
tagShows :: [String]
tagShows = ["一 ichi", "二 ni", "三 san", "四 shi",
"五 go", "六 roku", "七 shichi", "八 hachi", "九 kyū", "十 jū"]
-- initialize variable segment
-- simulate global variable using unsafe
segmentWindowtitle :: IORef String
segmentWindowtitle = unsafePerformIO $ newIORef ""
tagsStatus :: IORef [String]
tagsStatus = unsafePerformIO $ newIORef []
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- decoration
separator = "^bg()^fg(" ++ myColor "black" ++ ")|^bg()^fg()"
-- http://fontawesome.io/
fontAwesome = "^fn(FontAwesome-9)"
-- Powerline Symbol
rightHardArrow = "^fn(powerlinesymbols-14)\57520^fn()"
rightSoftArrow = "^fn(powerlinesymbols-14)\57521^fn()"
leftHardArrow = "^fn(powerlinesymbols-14)\57522^fn()"
leftSoftArrow = "^fn(powerlinesymbols-14)\57523^fn()"
-- theme
preIcon = "^fg(" ++ myColor "yellow500" ++ ")" ++ fontAwesome
postIcon = "^fn()^fg()"
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- main
getStatusbarText :: Int -> IO String
getStatusbarText monitor = do
tags <- readIORef tagsStatus
let tagText = join $ map (outputByTag monitor) tags
let titleText = outputLeftsideTop
let text = (tagText ++) <$> titleText
text
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- each segments
outputByTag :: Int -> String -> String
outputByTag monitor tagStatus = textPre ++ textName ++ textPost
where
-- text = ''
tagIndex = drop 1 tagStatus
tagMark = take 1 tagStatus
index = (read::String->Int) tagIndex - 1 -- zero based
tagName = tagShows !! index
----- pre tag
textPre = case tagMark of
"#" -> "^bg(" ++ myColor "blue500" ++ ")"
++ "^fg(" ++ myColor "black" ++ ")"
++ rightHardArrow
++ "^bg(" ++ myColor "blue500" ++ ")"
++ "^fg(" ++ myColor "white" ++ ")"
"+" -> "^bg(" ++ myColor "yellow500" ++ ")"
++ "^fg(" ++ myColor "grey400" ++ ")"
":" -> "^bg()^fg(" ++ myColor "white" ++ ")"
"!" -> "^bg(" ++ myColor "red500" ++ ")"
++ "^fg(" ++ myColor "white" ++ ")"
_ -> "^bg()^fg(" ++ myColor "grey600" ++ ")"
----- tag by number
-- assuming using dzen2_svn
-- clickable tags if using SVN dzen
textName = "^ca(1,herbstclient focus_monitor \""
++ show(monitor) ++ "\" && " ++ "herbstclient use \""
++ tagIndex ++ "\") " ++ tagName ++ " ^ca() "
----- post tag
textPost = if (tagMark == "#")
then "^bg(" ++ myColor "black" ++ ")"
++ "^fg(" ++ myColor "blue500" ++ ")"
++ rightHardArrow
else ""
outputLeftsideTop :: IO String
outputLeftsideTop = do
segment <- readIORef segmentWindowtitle
let text = " ^r(5x0) " ++ separator ++ " ^r(5x0) " ++ segment
return text
-- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
-- setting variables, response to event handler
--import Data.IORef
setTagValue :: Int -> IO ()
setTagValue monitor = do
let args = ["tag_status", show(monitor)]
(_, Just pipe_out, _, ph) <-
createProcess (proc "herbstclient" args)
{ std_out = CreatePipe }
raw <- hGetContents pipe_out
_ <- waitForProcess ph
let statusList = words raw
writeIORef tagsStatus statusList
setWindowtitle :: String -> IO ()
setWindowtitle windowtitle = do
let icon = preIcon ++ "\61444" ++ postIcon
let text = " " ++ icon ++ " ^bg()^fg(" ++ myColor "grey700" ++ ") " ++ windowtitle
writeIORef segmentWindowtitle text
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
wSleep :: Int -> IO ()
wSleep mySecond = threadDelay (1000000 * mySecond)