aboutsummaryrefslogblamecommitdiff
path: root/.xmonad/xmonad.hs
blob: ac82d8a9c57d83ea4a836238b4b99315149089a2 (plain) (tree)
1
2
3
4
5
                                                                             


                                          
                            














                                                                                
                                                                   
                                                             


































                                                                               




                               
                                                        
                                                                 

                                                                          
                                                                  
                                                              
                                                                  

                                                                            
                                                                  


                                                                               

                                             

     


































































































































































                                                                                 
                                      
                                
                                

                                   



                                
                                   
                                
 
                              
 
                     
                          
 




                                                                            










                                                                           


                        
 
                  



                         
                 

   







                                                                           
 
                                                         

                                                                      

                                      




                                                          


                                                                      


                                                             
 

                                                                  















                                                                       














                                                                



                                                       

                       










                                               
 
                                     








                                                                  


                                 





                                                          
                                          
                                                                                 
 









                                                                          
                                                                                         






                                              

                                                        


                                                            
                                            


                                                                 
                                           
       






                                           
{-# OPTIONS_GHC -W -fwarn-unused-imports -fno-warn-missing-signatures -O2 #-}
import Control.Monad (liftM2)
import Data.Map (fromList, toList, union)
import System.Environment (getEnv, setEnv)
import System.IO (hPutStrLn)
import XMonad
import XMonad.Actions.CopyWindow (copy, kill1, killAllOtherCopies)
import XMonad.Actions.CycleWS (moveTo, nextWS, WSType(NonEmptyWS)
                              , prevWS, shiftToNext, shiftToPrev, toggleWS)
import XMonad.Actions.DynamicWorkspaces (addWorkspacePrompt, removeWorkspace
                                        , renameWorkspace, selectWorkspace
                                        , withWorkspace)
import XMonad.Actions.GridSelect (HasColorizer, GSConfig, buildDefaultGSConfig
                                 , defaultColorizer, goToSelected
                                 , gridselectWorkspace, gs_navigate, navNSearch)
import XMonad.Actions.Submap (submap)
import XMonad.Hooks.DynamicLog (dzenColor, dynamicLogWithPP
                               , ppCurrent, ppVisible, ppSep, ppHidden
                               , ppUrgent, ppTitle, ppExtras
                               , ppOrder, ppOutput, trim, wrap)
import XMonad.Hooks.ManageDocks (avoidStruts, docks, docksEventHook
                                , ToggleStruts(ToggleStruts))
import XMonad.Hooks.ManageHelpers (isFullscreen, doFullFloat)
import XMonad.Hooks.UrgencyHook (focusUrgent)
import XMonad.Layout.Accordion (Accordion(Accordion))
import XMonad.Layout.Dishes (Dishes(Dishes))
import XMonad.Layout.FixedColumn (FixedColumn(FixedColumn))
import XMonad.Layout.Grid (Grid(Grid))
import XMonad.Layout.LimitWindows (limitWindows)
import XMonad.Layout.Magnifier (magnifiercz')
import XMonad.Layout.MultiToggle (mkToggle, single, Toggle(Toggle))
import XMonad.Layout.MultiToggle.Instances (StdTransformers(MIRROR))
import XMonad.Layout.NoBorders (smartBorders)
import XMonad.Layout.NoFrillsDecoration (activeBorderColor, activeColor
                                        , activeTextColor, decoHeight, fontName
                                        , inactiveBorderColor, inactiveColor
                                        , inactiveTextColor, urgentColor
                                        , urgentTextColor)
import XMonad.Layout.PerWorkspace (onWorkspace)
import XMonad.Layout.ResizableTile (ResizableTall(ResizableTall))
import XMonad.Layout.Tabbed (shrinkText, tabbed)
import XMonad.Layout.ThreeColumns (ThreeCol(ThreeColMid))
import XMonad.Layout.ToggleLayouts (toggleLayouts, ToggleLayout(ToggleLayout))
import XMonad.Layout.WindowNavigation (Navigate(Move))
import XMonad.Prompt (fgColor, bgColor, XPPosition(Bottom), height
                     , position, promptBorderWidth)
import XMonad.Prompt.Shell (shellPrompt)
import XMonad.Util.Loggers (date, logCmd)
import XMonad.Util.Run (spawnPipe)
import XMonad.Util.Themes (theme, themeAuthor, themeDescription, ThemeInfo(TI)
                          , themeName)
import XMonad.Util.Types (Direction1D(Next, Prev), Direction2D(L, R, U, D))
import XMonad.StackSet (shiftMaster, greedyView, shift)

---------------
--  BINDINGS
---------------

myMod = mod4Mask -- windows key
myCtrl = controlMask
myTerminal = "urxvtc"

-- Mouse bindings: default actions bound to mouse events
myMouseBindings (XConfig {XMonad.modMask = modMask}) = fromList $
    -- mod-button1 %! Set the window to floating mode and move by dragging
    [ ((modMask, button1), (\w -> focus w >> mouseMoveWindow w
                                          >> windows shiftMaster))
    -- mod-button2 %! Raise the window to the top of the stack
    , ((modMask, button2), (\w -> focus w >> windows shiftMaster))
    -- mod-button3 %! Set the window to floating mode and resize by dragging
    , ((modMask, button3), (\w -> focus w >> mouseResizeWindow w
                                          >> windows shiftMaster))
    -- you may also bind events to the mouse scroll wheel (button4 and button5)
    , ((modMask, button5), (\_ -> moveTo Next NonEmptyWS))
    , ((modMask, button4), (\_ -> moveTo Prev NonEmptyWS ))
    -- scroll wheel click
    , ((modMask, 6), (\w -> focus w >> kill))
    ]

mykeys x = [
  ((myMod, xK_Left), prevWS)
  , ((myMod, xK_Right), nextWS)
  , ((myMod .|. shiftMask, xK_Left),  shiftToPrev >> prevWS)
  , ((myMod .|. shiftMask, xK_Right), shiftToNext >> nextWS)
  , ((myMod, xK_a), toggleWS)
  , ((myMod, xK_z), shellPrompt myXPConfig)
  , ((myMod, xK_g), goToSelected myGSConfig)
  , ((myMod .|. shiftMask, xK_m), sendMessage $ Toggle MIRROR)
  , ((myMod .|. shiftMask, xK_g), gridselectWorkspace myGSConfig greedyView)
  , ((myMod, xK_x), sendMessage ToggleStruts)
  , ((myMod, xK_F1), spawn "${HOME}/.screenlayout/`hostname`-work.sh")
  , ((myMod, xK_F2), spawn "${HOME}/.screenlayout/`hostname`-home.sh")
  , ((myMod, xK_F3), spawn "${HOME}/.screenlayout/`hostname`-solo.sh")
  , ((myMod, xK_F4), spawn "sleep 0.5 && xset dpms force suspend")
  , ((myMod, xK_F5), spawn "sleep 0.5 && xset dpms force off")
  , ((myMod, xK_F6), spawn "sleep 0.5 && ${HOME}/bin/icd && ${HOME}/bin/mice.sh")
  , ((myMod, xK_Up),   spawn "sleep 0.5 && b u")
  , ((myMod, xK_Down), spawn "sleep 0.5 && b d")
  , ((myMod, xK_l), spawn "slock")
  , ((myMod .|. myCtrl .|. shiftMask, xK_Right), sendMessage $ Move R)
  , ((myMod .|. myCtrl .|. shiftMask, xK_Left),  sendMessage $ Move L)
  , ((myMod .|. myCtrl .|. shiftMask, xK_Up),    sendMessage $ Move U)
  , ((myMod .|. myCtrl .|. shiftMask, xK_Down),  sendMessage $ Move D)
  , ((myMod, xK_BackSpace), focusUrgent)
  , ((myMod, xK_s), sendMessage $ ToggleLayout)
  , ((myMod, xK_b), submap . fromList $
                    [ ((m, k), f)
                    | m <- [0, myMod]
                    , (k, f) <- [ (xK_a, addWorkspacePrompt myXPConfig)
                                , (xK_c, withWorkspace myXPConfig
                                         (windows . copy))
                                , (xK_d, kill1)
                                , (xK_k, removeWorkspace)
                                , (xK_m, withWorkspace myXPConfig
                                         (windows . shift))
                                , (xK_o, killAllOtherCopies)
                                , (xK_r, renameWorkspace myXPConfig)
                                , (xK_s, selectWorkspace myXPConfig)
                                ]
                    ]
    )]

dvorakify kl = fromList $ map (\((m, k), d) -> ((m, dk k), d)) $ toList kl
  where
    dk :: KeySym -> KeySym
    dk k    | k == xK_grave = xK_dollar
            | k == xK_asciitilde = xK_asciitilde

            | k == xK_1 = xK_ampersand
            | k == xK_exclam = xK_percent

            | k == xK_2 = xK_bracketleft
            | k == xK_at = xK_7

            | k == xK_3 = xK_braceleft
            | k == xK_numbersign = xK_5

            | k == xK_4 = xK_braceright
            | k == xK_dollar = xK_3

            | k == xK_5 = xK_parenleft
            | k == xK_percent = xK_1

            | k == xK_6 = xK_equal
            | k == xK_asciicircum = xK_9

            | k == xK_7 = xK_asterisk
            | k == xK_ampersand = xK_0

            | k == xK_8 = xK_parenright
            | k == xK_asterisk = xK_2

            | k == xK_9 = xK_plus
            | k == xK_parenleft = xK_4

            | k == xK_0 = xK_bracketright
            | k == xK_parenright = xK_6

            | k == xK_minus = xK_exclam
            | k == xK_underscore = xK_8

            | k == xK_equal = xK_numbersign
            | k == xK_plus = xK_grave

            | k == xK_q = xK_semicolon -- upper row, left side
            | k == xK_Q = xK_colon

            | k == xK_w = xK_comma
            | k == xK_W = xK_less

            | k == xK_e = xK_period
            | k == xK_E = xK_greater

            | k == xK_bracketleft = xK_slash -- upper row, top right
            | k == xK_braceleft = xK_question

            | k == xK_bracketright = xK_at
            | k == xK_braceright = xK_asciicircum

            | k == xK_R = xK_P
            | k == xK_T = xK_Y
            | k == xK_Y = xK_F
            | k == xK_U = xK_G
            | k == xK_I = xK_C
            | k == xK_O = xK_R
            | k == xK_P = xK_L
            | k == xK_A = xK_A
            | k == xK_S = xK_O
            | k == xK_D = xK_E
            | k == xK_F = xK_U
            | k == xK_G = xK_I
            | k == xK_H = xK_D
            | k == xK_J = xK_H
            | k == xK_K = xK_T
            | k == xK_L = xK_N
            | k == xK_Z = xK_quotedbl
            | k == xK_X = xK_Q
            | k == xK_C = xK_J
            | k == xK_V = xK_K
            | k == xK_B = xK_X
            | k == xK_N = xK_B
            | k == xK_M = xK_M

            | k == xK_r = xK_p
            | k == xK_t = xK_y
            | k == xK_y = xK_f
            | k == xK_u = xK_g
            | k == xK_i = xK_c
            | k == xK_o = xK_r
            | k == xK_p = xK_l
            | k == xK_a = xK_a
            | k == xK_s = xK_o
            | k == xK_d = xK_e
            | k == xK_f = xK_u
            | k == xK_g = xK_i
            | k == xK_h = xK_d
            | k == xK_j = xK_h
            | k == xK_k = xK_t
            | k == xK_l = xK_n
            | k == xK_z = xK_apostrophe
            | k == xK_x = xK_q
            | k == xK_c = xK_j
            | k == xK_v = xK_k
            | k == xK_b = xK_x
            | k == xK_n = xK_b
            | k == xK_m = xK_m

            | k == xK_comma = xK_w -- bottom right
            | k == xK_less = xK_W

            | k == xK_period = xK_v
            | k == xK_greater = xK_V

            | k == xK_slash = xK_z
            | k == xK_question = xK_Z

            | otherwise = k

-------------
-- THEMES
-------------

-- Color names are easier to remember:
colorBlack           = "#000000"
colorOrange          = "#ff7701"
-- colorDarkGray        = "#171717"
-- colorPink            = "#e3008d"
colorGreen           = "#00aa4a"
colorBlue            = "#008dd5"
colorYellow          = "#fee100"
colorWhite           = "#cfbfad"
-- colorBrightGreen     = "#00FF00"
colorRed             = "#FF0000"

xftFont = "Inconsolata:size=8"

newTheme :: ThemeInfo
newTheme = TI "" "" "" def

rakTheme :: ThemeInfo
rakTheme =
    newTheme { themeName        = "rakTheme"
             , themeAuthor      = "Ryan Kavanagh"
             , themeDescription = "Small decorations: orange and blue theme"
             , theme            = def { activeColor         = colorBlack
                                      , inactiveColor       = colorBlack
                                      , activeBorderColor   = colorOrange
                                      , inactiveBorderColor = colorBlack
                                      , activeTextColor     = colorOrange
                                      , inactiveTextColor   = colorBlue
                                      , urgentColor         = colorRed
                                      , urgentTextColor     = colorYellow
                                      , decoHeight          = 13
                                      , fontName            = "Inconsolata"
                                      }
             }

myTheme = theme rakTheme

myXPConfig = def {
    fgColor  = "white"
  , bgColor  = "black"
  , promptBorderWidth = 0
  , position = Bottom
  , height   = 15
  }

-----------------
-- LAYOUTS
-----------------

-- My workspaces

myWorkspaces = ["term", "web", "chatter", "reading", "5", "music", "LaTeX"]
               ++ (map show [8..20])

-- smartBorders removes borders when there's no ambiguity
myLayout = mkToggle (single MIRROR) (smartBorders $ toggleLayouts Full
                                     $ avoidStruts perWS)
  where
    -- Per workspace layout selection.
    perWS = onWorkspace "term"  (myTall ||| customRyan) $
            onWorkspace "web"   (tabbed shrinkText myTheme
                                 ||| mySplit ||| myTCM) $
            onWorkspace "LaTeX" latexFirst $
            customRyan

    -- Each of these allows toggling through a set of layouts
    -- in the same logical order, but from a different starting point.
    customRyan = myGrid  ||| myDish  ||| Accordion ||| myCode
                 ||| myFixed ||| myTall
    latexFirst = myFixed ||| customRyan

    -- This is a three column mode, with the master in the middle.
    myTCM = ThreeColMid 1 (3/100) (1/2)
    -- This is a tall-like layout with magnification.
    -- The master window is fixed at 80 columns wide, making this good
    -- for coding. Limited to 3 visible windows at a time to ensure all
    -- are a good size.
    myCode = limitWindows 3 $ magnifiercz' 1.4 $ FixedColumn 1 20 80 10

    -- Stack with one large master window.
    -- It's easy to overflow a stack to the point that windows are too
    -- small, so only show first 5.
    myDish = limitWindows 5 $ Dishes nmaster ratio
      where
        -- The default number of windows in the master pane
        nmaster = 1
        -- Default proportion of screen occupied by other panes
        ratio = 1/5

    -- Split screen, optimized for web browsing.
    mySplit = magnifiercz' 1.4 $ Tall nmaster delta ratio
      where
        -- The default number of windows in the master pane
        nmaster = 1
        -- Percent of screen to increment by when resizing panes
        delta   = 3/100
        -- Default proportion of screen occupied by master pane
        ratio   = 60/100

    -- Standard grid.
    myGrid = Grid

    myFixed = FixedColumn 1 20 80 10

    myTall = ResizableTall nmaster delta ratio [50/100]
        where
            nmaster = 1
            delta = 3/100
            ratio = 1/2

-------------------
-- STATUS BAR
-------------------

statusBarCmd = "dzen2" ++
               " -dock" ++
               " -bg '" ++ colorBlack ++ "'" ++
               " -fg '" ++ colorBlue ++ "'" ++
               " -sa c" ++
               " -fn '" ++ xftFont ++ "'" ++
               " -w 925 -x 0 -y 0 -ta l -e ''"

-- dynamiclog pretty printer for dzen
mPP h = def
        { ppCurrent = dzenColor colorOrange colorBlack
        , ppVisible = dzenColor colorGreen colorBlack
        , ppHidden  = dzenColor colorBlue colorBlack
        , ppUrgent  = dzenColor colorRed colorBlack . wrap "[" "]"
        , ppSep     = dzenColor "grey60" colorBlack " ^r(1x8) "
        , ppTitle   = dzenColor colorWhite colorBlack . trim
        , ppOrder   = \(ws:l:t:d:b:o) -> [b,d,ws,l,t] ++ o
        , ppExtras  = [date "%H:%M:%S", batteryCheck]
        , ppOutput  = hPutStrLn h
        }
    where
        batteryCheck = logCmd ("${HOME}/.dzen/battery.sh")

---------------------
-- GENERAL CONFIG
--------------------

myGSConfig :: HasColorizer a => GSConfig a
myGSConfig = (buildDefaultGSConfig defaultColorizer) { gs_navigate = navNSearch }

myManageHook = composeAll . concat $
                [ [ className =? c --> doFloat             | c <- floats]
                , [ className =? c --> viewShift "web"     | c <- web]
                , [ className =? c --> viewShift "chatter" | c <- chatter]
                , [ className =? c --> viewShift "music"   | c <- music]
                , [ isFullscreen   --> doFullFloat ]
              ]
  where
    viewShift = doF . liftM2 (.) greedyView shift
    floats    = ["MPlayer"]
    web       = ["Firefox", "Firefox-esr", "Navigator", "google-chrome", "Google-chrome"]
    chatter   = ["slack", "Slack"]
    music     = ["pavucontrol", "Pavucontrol"]

myConfig dzenPipe = docks $ def {
      workspaces           = myWorkspaces
      , modMask            = myMod
      , terminal           = myTerminal
      , normalBorderColor  = inactiveBorderColor myTheme
      , focusedBorderColor = activeBorderColor myTheme
      , borderWidth        = 1
      , layoutHook         = myLayout
      , manageHook         = manageHook def <+> myManageHook
      , mouseBindings      = myMouseBindings
      , keys               = \x -> (fromList $ mykeys x)
                                   `union` dvorakify (keys def x)
      , logHook            = dynamicLogWithPP $ mPP dzenPipe
      , handleEventHook    = docksEventHook
      }

main = do
    dzenPipe <- spawnPipe statusBarCmd
    path <- getEnv "PATH"
    home <- getEnv "HOME"
    setEnv "PATH" (home ++ "/bin:" ++ path)
    xmonad $ myConfig dzenPipe