add topic space module (wraps XMonad.Actions.TopicSpace) with dynamic topic space config

This commit is contained in:
Maximilian Keßler 2022-07-19 19:29:14 +02:00
parent ddeafa09c2
commit 6efab03456
3 changed files with 119 additions and 1 deletions

View file

@ -6,13 +6,15 @@ import XMonad
import qualified XMonad.StackSet as W
import XMonad.Custom.BindingUtils
import XMonad.Custom.TopicSpace
myBasicKeyBindings :: [([Char], X ())]
myBasicKeyBindings = addMainModifierToBinding $ myFocusBindings ++ mySwapBindings ++ myMasterBindings ++ myXMonadBindings ++ myLaunchBindings
myLaunchBindings :: [([Char], X ())]
myLaunchBindings = [
("<Return>", spawn "kitty"),
("<Return>", spawnInTopicDir "kitty"),
("r", spawn "dmenu_run"),
("S-r", spawn "gmrun"),
("x", kill),

View file

@ -0,0 +1,114 @@
module XMonad.Custom.TopicSpace (
module XMonad.Actions.TopicSpace
, tiNames
, noActionTI, inHomeTI, simpleTI
, topicStartupHook
, currentTopicConfig
, goto
, spawnInTopicDir
) where
-- ---------------------------------------------------------------------
-- $usage
--
-- The goal of this is to wrap a more flexible interface around the XMoand.Actions.TopicSpace
-- module.
-- The goal is to store a TopicConfig as part of the (dynamic) state of the X monad
-- and initialize it with the user-given config in the X monad startup hook.
--
-- This has a number of benefits:
-- - Helper functions like goto :: Topic -> X () that are mentioned in the
-- XMonad.Actions.TopicSpace module can be implemented as part of this module
-- as they do not need to know the configuration "in advance" at definition time.
-- Notice that we have to use X () here anyways since we want to trigger a dynamic
-- action, so we can as well retrieve the TopicSpace config from the X monad
-- at runtime
-- - In particular, this allows splitting the *usage* of topics and the actual *configuration*
-- of topics into separate parts of code.
-- When defining keybindings involving topics (such as switching to them),
-- we do not need to know all topics and their respective configurations yet.
-- Conversely, we can define some topics at multiple different parts of code
-- and only combine them to the final topic configuration in the main xmonad.hs
-- configuration file.
-- This also means that 'picking' the right config out of a set of (custom)
-- modules is very easy now, since they do not have to rely on each other
-- - We can dynamically change the information associated to a workspace
-- Similar to XMonad.Actions.WorkspaceNames,
-- which dynamically adds comments to the names of workspaces,
-- this allows us to dynamically change e.g. the associated working
-- directory of a topic at runtime
-- - while still allowing generic functions like goto to be defined
--
--
-- import qualified Data.Map.Strict as M
import qualified XMonad.Util.ExtensibleState as XS
-- import qualified XMonad.StackSet as W
import XMonad
import XMonad.Actions.TopicSpace
-- | An alias for topicNames.
-- This establishes consistency with tiActions and tiDirs of similar functionality
tiNames :: [TopicItem] -> [Topic]
tiNames = topicNames
-- | Alias with better naming
noActionTI :: Topic -> Dir -> TopicItem
noActionTI = noAction
-- | Alias with better naming
inHomeTI :: Topic -> X () -> TopicItem
inHomeTI = inHome
-- | A topic with no associated info at all
simpleTI :: Topic -> TopicItem
simpleTI n = TI n "~/." (pure ())
--------------------------------------------t
-- X state implementation and tools
-- | Store config in X extensible state
-- We do this by wrapping into a store type to avoid
-- orphan instance declarations
data StoreTopicConfig = StoreTopicConfig TopicConfig
instance ExtensionClass StoreTopicConfig where
initialValue = StoreTopicConfig def
-- | Unwrap a stored topic config
topicConfig :: StoreTopicConfig -> TopicConfig
topicConfig (StoreTopicConfig tc) = tc
-- | Put initial topic Config into X state at startup
-- Add this to the XConfig startupHook
topicStartupHook :: TopicConfig -> X ()
topicStartupHook = XS.put . StoreTopicConfig
-- | Retrieve the current topic config from the X state
currentTopicConfig :: X TopicConfig
currentTopicConfig = fmap topicConfig XS.get
-------------------------------------------
-- | These are the real utilities that we aimed for
-- | Topic-aware switch to topic with windows W.view
goto :: Topic -> X ()
goto topic = do
tc <- currentTopicConfig
switchTopic tc topic
-- | Like the standard from XMonad, but spawns in the working dir of the current topic
-- If the current workspace is not an actual topic (i.e. no information is stored about
-- the workspace in the topicConfig of the X monad), the home directory will be chosen
spawnInTopicDir :: String -> X ()
spawnInTopicDir cmd = do
tc <- currentTopicConfig
dir <- currentTopicDir tc
spawn $ "cd " ++ dir ++ "; " ++ cmd

View file

@ -21,6 +21,7 @@ library
XMonad.Custom.Modifiers
XMonad.Custom.NumberWorkspaces
XMonad.Custom.WorkspaceNames
XMonad.Custom.TopicSpace
hs-source-dirs: src
ghc-options: -funbox-strict-fields -Wall -Wno-unused-do-bind
build-depends: base
@ -28,4 +29,5 @@ library
, xmonad-contrib
, ghc
, X11
, containers
default-language: Haskell2010