aboutsummaryrefslogtreecommitdiff
path: root/src/Main.hs
blob: e18c1d88fc0edfa4bc3134b8aa11e870120bc6f9 (plain) (blame)
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