home/xmonad: Choose projects plugin #5

Merged
pleshevskiy merged 3 commits from xmonad_projects into main 2022-09-12 00:07:55 +03:00

View file

@ -8,9 +8,11 @@
-- --
import qualified Codec.Binary.UTF8.String as UTF8 import qualified Codec.Binary.UTF8.String as UTF8
import Control.Monad (replicateM_, sequence_)
import qualified DBus as D import qualified DBus as D
import qualified DBus.Client as D import qualified DBus.Client as D
import qualified Data.Map as M import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Monoid import Data.Monoid
import System.Exit import System.Exit
import XMonad import XMonad
@ -38,8 +40,10 @@ import XMonad.Layout.LimitWindows (limitWindows)
import XMonad.Layout.NoBorders (smartBorders) import XMonad.Layout.NoBorders (smartBorders)
import XMonad.Layout.Spacing (spacing) import XMonad.Layout.Spacing (spacing)
import XMonad.Layout.ThreeColumns (ThreeCol (..)) import XMonad.Layout.ThreeColumns (ThreeCol (..))
import XMonad.Prompt (XPConfig, XPType (..), XPrompt (..), mkComplFunFromList', mkXPromptWithModes)
import qualified XMonad.StackSet as W import qualified XMonad.StackSet as W
import XMonad.Util.EZConfig import XMonad.Util.EZConfig
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.Run import XMonad.Util.Run
-- The preferred terminal program, which is used in a binding below and by -- The preferred terminal program, which is used in a binding below and by
@ -101,7 +105,7 @@ main = mkDbusClient >>= main'
main' :: D.Client -> IO () main' :: D.Client -> IO ()
main' dbus = main' dbus =
xmonad . docks . ewmhFullscreen . ewmh $ xmonad . docks . ewmhFullscreen . ewmh . dynProjects $
def def
{ -- simple stuff { -- simple stuff
terminal = myTerminal, terminal = myTerminal,
@ -122,6 +126,8 @@ main' dbus =
logHook = myPolybarLogHook dbus, logHook = myPolybarLogHook dbus,
startupHook = myStartupHook startupHook = myStartupHook
} }
where
dynProjects = dynamicProjects myProjects
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- Polybar settings (needs DBus client). -- Polybar settings (needs DBus client).
@ -191,7 +197,9 @@ myLayout = avoidStruts . smartBorders $ (Mirror tiled ||| tiled ||| column3 |||
-- per-workspace layout choices. -- per-workspace layout choices.
-- --
-- By default, do nothing. -- By default, do nothing.
myStartupHook = return () myStartupHook = do
spawn "kotatogram-desktop"
spawn "nheko"
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- Status bars and logging -- Status bars and logging
@ -249,11 +257,9 @@ myManageHook = manageApps
-- Key bindings. Add, modify or remove key bindings here. -- Key bindings. Add, modify or remove key bindings here.
-- --
myKeys conf = myKeys conf =
let easyMotionConfig = mkKeymap conf $
def apps_kb ++ workspaces_kb ++ windows_kb ++ layout_kb ++ system_kb ++ misc_kb
{ sKeys = AnyKeys [xK_a, xK_o, xK_e, xK_u, xK_h, xK_t, xK_n, xK_s] where
}
apps_kb = apps_kb =
[ -- launch a terminal [ -- launch a terminal
("M-S-<Return>", spawn $ XMonad.terminal conf), ("M-S-<Return>", spawn $ XMonad.terminal conf),
@ -297,6 +303,11 @@ myKeys conf =
-- Swap the focused window with the previous window -- Swap the focused window with the previous window
("M-S-k", windows W.swapUp) ("M-S-k", windows W.swapUp)
] ]
where
easyMotionConfig =
def
{ sKeys = AnyKeys [xK_a, xK_o, xK_e, xK_u, xK_h, xK_t, xK_n, xK_s]
}
layout_kb = layout_kb =
[ -- Rotate through the available layout algorithms [ -- Rotate through the available layout algorithms
@ -329,19 +340,18 @@ myKeys conf =
] ]
misc_kb = misc_kb =
[ -- Change volume [ ("M-o", projectPrompt def),
-- Change volume
("<XF86AudioMute>", spawn "amixer -q sset Master toggle"), ("<XF86AudioMute>", spawn "amixer -q sset Master toggle"),
("<XF86AudioRaiseVolume>", spawn "amixer -q sset Master 5%+"), ("<XF86AudioRaiseVolume>", spawn "amixer -q sset Master 5%+"),
("<XF86AudioLowerVolume>", spawn "amixer -q sset Master 5%-") ("<XF86AudioLowerVolume>", spawn "amixer -q sset Master 5%-")
] ]
in mkKeymap conf $
apps_kb ++ workspaces_kb ++ windows_kb ++ layout_kb ++ system_kb ++ misc_kb
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- Mouse bindings: default actions bound to mouse events -- Mouse bindings: default actions bound to mouse events
-- --
myMouseBindings (XConfig {XMonad.modMask = modm}) = myMouseBindings (XConfig {XMonad.modMask = modm}) =
M.fromList Map.fromList
-- mod-button1, Set the window to floating mode and move by dragging -- mod-button1, Set the window to floating mode and move by dragging
[ ((modm, button1), \w -> focus w >> mouseMoveWindow w >> windows W.shiftMaster), [ ((modm, button1), \w -> focus w >> mouseMoveWindow w >> windows W.shiftMaster),
-- mod-button2, Raise the window to the top of the stack -- mod-button2, Raise the window to the top of the stack
@ -350,3 +360,115 @@ myMouseBindings (XConfig {XMonad.modMask = modm}) =
((modm, button3), \w -> focus w >> mouseResizeWindow w >> windows W.shiftMaster) ((modm, button3), \w -> focus w >> mouseResizeWindow w >> windows W.shiftMaster)
-- you may also bind events to the mouse scroll wheel (button4 and button5) -- you may also bind events to the mouse scroll wheel (button4 and button5)
] ]
myProjects :: [Project]
myProjects =
[ -- my work
Project
{ projectName = "bm-back",
projectStartHook = do
let workdir = "~/projects/binarymanagement/bm-back"
spawn $ terminal' workdir $ Just "docker-compose -f docker-compose.dev.yml up -d"
replicateM_ 3 $ spawn $ terminal workdir
},
Project
{ projectName = "bm-front",
projectStartHook = do
let workdir = "~/projects/binarymanagement/bm-front"
replicateM_ 3 $ spawn $ terminal workdir
},
-- personal
Project
{ projectName = "myconfig",
projectStartHook = replicateM_ 2 $ spawn $ terminal "~/repos/myconfig"
},
Project
{ projectName = "tas",
projectStartHook = replicateM_ 2 $ spawn $ terminal "~/repos/tas"
},
-- community
Project
{ projectName = "dexios",
projectStartHook = replicateM_ 2 $ spawn $ terminal "~/repos/dexios"
},
Project
{ projectName = "home-manager (nix)",
projectStartHook = replicateM_ 2 $ spawn $ terminal "~/repos/home-manager"
}
]
where
terminal :: String -> String
terminal wd = terminal' wd Nothing
terminal' :: String -> Maybe String -> String
terminal' wd' cmd' =
"alacritty" ++ workdir ++ command
where
workdir = " --working-directory " ++ wd'
command = case cmd' of
Just c -> " --command " ++ c
_ -> ""
------------------------------------------------------------------------
-- Project
type ProjectName = String
data Project = Project
{ projectName :: !ProjectName,
projectStartHook :: !(X ())
}
type ProjectTable = Map ProjectName Project
data ProjectState = ProjectState {projects :: !ProjectTable}
instance ExtensionClass ProjectState where
initialValue = ProjectState Map.empty
data ProjectPrompt = ProjectPrompt XPConfig [ProjectName]
dynamicProjects :: [Project] -> XConfig a -> XConfig a
dynamicProjects ps c =
c {startupHook = dynamicProjectsStartupHook ps <> startupHook c}
dynamicProjectsStartupHook :: [Project] -> X ()
dynamicProjectsStartupHook ps = XS.modify go
where
go :: ProjectState -> ProjectState
go s = s {projects = update $ projects s}
update :: ProjectTable -> ProjectTable
update = Map.union (Map.fromList $ map entry ps)
entry :: Project -> (ProjectName, Project)
entry p = (projectName p, p)
instance XPrompt ProjectPrompt where
showXPrompt (ProjectPrompt _ _) = "Choose Project: "
completionFunction (ProjectPrompt c ns) = mkComplFunFromList' c ns
modeAction (ProjectPrompt _ _) buf auto = do
let name = if null auto then buf else auto
ps <- XS.gets projects
case Map.lookup name ps of
Just p -> openProject p
Nothing -> return ()
openProject :: Project -> X ()
openProject p = do
-- kill all windows in the current workspace
wins <- gets (W.integrate' . W.stack . W.workspace . W.current . windowset)
sequence_ $ map killWindow wins
projectStartHook p
projectPrompt :: XPConfig -> X ()
projectPrompt c = do
ps <- XS.gets projects
let names = Map.keys ps
modes = [XPT $ ProjectPrompt c names]
mkXPromptWithModes modes c