mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-19 03:20:21 -07:00
Typeable has been automatically derived for every type since GHC 7.10, so remove these obsolete derivations. This also allows us to get rid of the `DeriveDataTypeable` pragma quite naturally. Related: https://github.com/xmonad/xmonad/pull/299 (xmonad/xmonad@9e5b16ed8a) Related: bd5b969d9ba24236c0d5ef521c0397390dbc4b37 Fixes: https://github.com/xmonad/xmonad-contrib/issues/548
86 lines
3.1 KiB
Haskell
86 lines
3.1 KiB
Haskell
{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
|
|
-----------------------------------------------------------------------------
|
|
-- |
|
|
-- Module : XMonad.Util.ActionCycle
|
|
-- Copyright : (c) 2020 Leon Kowarschick
|
|
-- License : BSD3-style (see LICENSE)
|
|
--
|
|
-- Maintainer : Leon Kowarschick. <thereal.elkowar@gmail.com>
|
|
-- Stability : unstable
|
|
-- Portability : unportable
|
|
--
|
|
-- This module provides a way to have "cycling" actions.
|
|
-- This means that you can define an @X ()@ action that cycles through a list of actions,
|
|
-- advancing every time it is executed.
|
|
-- This may for exapmle be useful for toggle-style keybindings.
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
module XMonad.Util.ActionCycle
|
|
( -- * Usage
|
|
-- $usage
|
|
cycleAction
|
|
, cycleActionWithResult
|
|
)
|
|
where
|
|
import Prelude hiding ((!!))
|
|
import Data.Map.Strict as M
|
|
import XMonad
|
|
import qualified XMonad.Util.ExtensibleState as XS
|
|
import qualified Data.List.NonEmpty as NonEmpty
|
|
import Data.List.NonEmpty ((!!), NonEmpty((:|)))
|
|
|
|
|
|
-- $usage
|
|
-- You can use this module to implement cycling key-bindings by importing 'XMonad.Util.ActionCycle'
|
|
--
|
|
-- > import XMonad.Util.ActionCycle
|
|
--
|
|
-- and then creating a keybinding as follows:
|
|
--
|
|
-- > ((mod1Mask, xK_t), cycleAction "cycleActions" [ spawn "commmand1", spawn "command2", spawn "command3" ])
|
|
--
|
|
-- Note that the name given to cycleAction must be a unique action per cycle.
|
|
|
|
|
|
-- | Generate an @X ()@ action that cycles through a list of actions,
|
|
-- advancing every time the action is called.
|
|
cycleAction
|
|
:: String -- ^ Unique name for this action. May be any arbitrary, unique string.
|
|
-> [X ()] -- ^ List of actions that will be cycled through.
|
|
-> X ()
|
|
cycleAction _ [] = pure ()
|
|
cycleAction name (x:xs) = cycleActionWithResult name (x :| xs)
|
|
|
|
-- | Another version of 'cycleAction' that returns the result of the actions.
|
|
-- To allow for this, we must make sure that the list of actions is non-empty.
|
|
cycleActionWithResult
|
|
:: String -- ^ Unique name for this action. May be any arbitrary, unique string.
|
|
-> NonEmpty.NonEmpty (X a) -- ^ Non-empty List of actions that will be cycled through.
|
|
-> X a
|
|
cycleActionWithResult name actions = do
|
|
cycleState <- XS.gets (getActionCycle name)
|
|
idx <- case cycleState of
|
|
Just x -> do
|
|
XS.modify (nextActionCycle name (NonEmpty.length actions))
|
|
pure x
|
|
Nothing -> do
|
|
XS.modify (setActionCycle name 1)
|
|
pure 0
|
|
actions !! idx
|
|
|
|
|
|
newtype ActionCycleState = ActionCycleState (M.Map String Int)
|
|
|
|
instance ExtensionClass ActionCycleState where
|
|
initialValue = ActionCycleState mempty
|
|
|
|
getActionCycle :: String -> ActionCycleState -> Maybe Int
|
|
getActionCycle name (ActionCycleState s) = M.lookup name s
|
|
|
|
nextActionCycle :: String -> Int -> ActionCycleState -> ActionCycleState
|
|
nextActionCycle name maxNum (ActionCycleState s) = ActionCycleState $ M.update (\n -> Just $ (n + 1) `mod` maxNum) name s
|
|
|
|
setActionCycle :: String -> Int -> ActionCycleState -> ActionCycleState
|
|
setActionCycle name n (ActionCycleState s) = ActionCycleState $ M.insert name n s
|