1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
import XMonad
import Control.Concurrent
import Control.Exception
import Control.Monad
import Control.Monad (when)
import Control.Monad.Writer
import Data.Ord
import Data.List (partition, isPrefixOf, sortBy)
import Data.List.Split
import Data.Maybe
import Internal.Keys
import Internal.Layout
import Internal.LayoutDraw
import System.Directory
import System.FilePath
import System.IO
import System.Process
import Text.Printf
import XMonad.Actions.WindowNavigation
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Layout.IndependentScreens
import XMonad.Layout.Spacing
import XMonad.Util.CustomKeys
import XMonad.Util.NamedWindows
import XMonad.Util.Run (spawnPipe)
import qualified XMonad.StackSet as S
data WorkspaceState = Current | Hidden | Visible
getWorkspaces :: (Ord i) => S.StackSet i l a sid sd -> [(WorkspaceState, i)]
getWorkspaces (S.StackSet (S.Screen cur _ _) vis hi _) =
sortBy (comparing snd) $
mapMaybe (\(a, S.Workspace t _ s) -> fmap (const (a, t)) s) $
map (\w -> (Hidden, w)) hi ++
map (\(S.Screen w _ _) -> (Visible, w)) vis ++
[(Current, cur)]
main = do
-- Execute some commands.
homeDir <- getHomeDirectory
let fp = homeDir </> ".xmonad" </> "startup"
xmproc <- spawnPipe "xmobar"
hSetEncoding xmproc utf8
config <-
applyKeys $ def
{ terminal = "alacritty"
, modMask = mod3Mask
, borderWidth = 2
, keys = \config -> mempty
, focusedBorderColor = "#ff6c00"
-- , normalBorderColor = "#ffd9bf"
, normalBorderColor = "#000000"
, layoutHook = myLayout
, startupHook = do
ewmhDesktopsStartup
spawn fp
, manageHook = composeAll [
isFullscreen --> doFullFloat
, className =? "Tilda" --> doFloat
, className =? "yakuake" --> doFloat
, className =? "MPlayer" --> doFloat
, title =? "Event Tester" --> doFloat
, className =? "mpv" --> doFloat
, className =? "gnubby_ssh_prompt" --> doFloat
]
, workspaces = map return (['0'..'9'] ++ ['a'..'z'])
, handleEventHook = fullscreenEventHook
, focusFollowsMouse = False
, clickJustFocuses = False
, logHook = do
(_, _, layout) <- showLayout
winset <- gets windowset
title <- maybe (pure "") (fmap show . getName) . S.peek $ winset
let wss = getWorkspaces winset
liftIO $ do
hPutStrLn xmproc $ trunc 80 $ execWriter $ do
mapM_ tell layout
tell $ xmobarColor "#404040" "" " │ "
forM_ wss $ \(t, name) -> do
case t of
Current -> tell "<fn=1><fc=#ff8888>"
Visible -> tell "<fn=6><fc=#8888ff>"
Hidden -> tell "<fn=2><fc=#888888>"
tell name
tell " </fc></fn>"
tell $ xmobarColor "#404040" "" "│ "
tell $ "<fc=#a0a0a0><fn=3>"
tell $ title
tell $ "</fn></fc>"
}
-- let toggleStructsKey XConfig {XMonad.modMask = modMask} = (modMask, xK_b)
xmonad (docks config)
where
trunc amt str = reverse $ trunc' False amt str []
trunc' :: Bool -> Int -> String -> String -> String
trunc' _ _ [] acc = acc
trunc' ignore amt (a:as) acc =
case a of
'<' -> trunc' True amt as (a : acc)
'>' -> trunc' False amt as (a : acc)
_ ->
if ignore
then trunc' True amt as (a : acc)
else
case amt of
0 -> trunc' False 0 as acc
3 -> trunc' False 0 as ("..." ++ acc)
_ -> trunc' False (amt - 1) as (a : acc)
splitOnAll arr str = splitOnAll' arr [str]
splitOnAll' [] str = str
splitOnAll' (a:as) [str] = splitOnAll' as (splitOn a str)
splitOnAll' _ lst = lst
|