aboutsummaryrefslogtreecommitdiff
path: root/src/Internal
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2022-04-10 13:26:16 -0600
committerJosh Rahm <joshuarahm@gmail.com>2022-10-09 12:19:46 -0600
commita652c330707e2e9bbe963e01af79ce730cf3452e (patch)
tree047655195f50efcbd51db8f825acf589dc6abead /src/Internal
parent381a3e5a00813314249bb74b5460f5ff5a4006bb (diff)
downloadrde-a652c330707e2e9bbe963e01af79ce730cf3452e.tar.gz
rde-a652c330707e2e9bbe963e01af79ce730cf3452e.tar.bz2
rde-a652c330707e2e9bbe963e01af79ce730cf3452e.zip
Rename Internal to Rahm.Desktop
Diffstat (limited to 'src/Internal')
-rw-r--r--src/Internal/CornerLayout.hs58
-rw-r--r--src/Internal/DMenu.hs45
-rw-r--r--src/Internal/Hash.hs11
-rw-r--r--src/Internal/Keys.hs820
-rw-r--r--src/Internal/KeysM.hs497
-rw-r--r--src/Internal/Layout.hs326
-rw-r--r--src/Internal/LayoutDraw.hs155
-rw-r--r--src/Internal/LayoutList.hs297
-rw-r--r--src/Internal/Lib.hs160
-rw-r--r--src/Internal/Logger.hs32
-rw-r--r--src/Internal/Marking.hs204
-rw-r--r--src/Internal/MouseMotion.hs97
-rw-r--r--src/Internal/NoPersist.hs23
-rw-r--r--src/Internal/PassMenu.hs13
-rw-r--r--src/Internal/PromptConfig.hs12
-rw-r--r--src/Internal/RebindKeys.hs119
-rw-r--r--src/Internal/ScreenRotate.hs19
-rw-r--r--src/Internal/Submap.hs104
-rw-r--r--src/Internal/Swallow.hs29
-rw-r--r--src/Internal/SwapMaster.hs41
-rw-r--r--src/Internal/Windows.hs86
-rw-r--r--src/Internal/XMobarLog.hs78
22 files changed, 0 insertions, 3226 deletions
diff --git a/src/Internal/CornerLayout.hs b/src/Internal/CornerLayout.hs
deleted file mode 100644
index 5545aef..0000000
--- a/src/Internal/CornerLayout.hs
+++ /dev/null
@@ -1,58 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
--- Creates a layout, the "corner layout" that keeps the master window in the
--- corner and the other windows go around it.
-module Internal.CornerLayout where
-
-import Data.Typeable (Typeable)
-import XMonad (LayoutClass(..), Rectangle(..), Resize(..), fromMessage)
-import qualified XMonad.StackSet as S
-
-data Corner a = Corner Rational Rational
- deriving (Show, Typeable, Read)
-
-instance LayoutClass Corner a where
- pureLayout (Corner frac _) screen@(Rectangle x y w h) ss =
- let w' = floor $ fromIntegral w * frac
- h' = floor $ fromIntegral h * frac
- corner = Rectangle 0 0 w' h'
- vertRect = Rectangle (fromIntegral w') 0 (w - w') h
- horizRect = Rectangle 0 (fromIntegral h') w' (h - h')
- ws = S.integrate ss
-
- vn = (length ws - 1) `div` 2
- hn = (length ws - 1) - vn
- in
- case ws of
- [a] -> [(a, screen)]
- [a, b] -> [
- (a, Rectangle x y w' h),
- (b, Rectangle (x + fromIntegral w') y (w - w') h)]
- _ ->
- zip ws $ map (
- \(Rectangle x' y' w h) -> Rectangle (x + x') (y + y') w h) $
- corner :
- splitVert vertRect vn ++
- splitHoriz horizRect hn
-
- pureMessage (Corner frac delta) m = fmap resize (fromMessage m)
- where
- resize Shrink = Corner (frac - delta) delta
- resize Expand = Corner (frac + delta) delta
-
-splitVert :: Rectangle -> Int -> [Rectangle]
-splitVert (Rectangle x y w h) i' =
- map
- (\i -> Rectangle x (y + fromIntegral (step * i)) w step)
- [0 .. i - 1]
- where
- i = fromIntegral i'
- step = h `div` i
-
-splitHoriz :: Rectangle -> Int -> [Rectangle]
-splitHoriz (Rectangle x y w h) i' =
- map
- (\i -> Rectangle (x + fromIntegral (step * i)) y step h)
- [0 .. i - 1]
- where
- step = w `div` i
- i = fromIntegral i'
diff --git a/src/Internal/DMenu.hs b/src/Internal/DMenu.hs
deleted file mode 100644
index 0d22b55..0000000
--- a/src/Internal/DMenu.hs
+++ /dev/null
@@ -1,45 +0,0 @@
-module Internal.DMenu where
-
-import XMonad.Util.Dmenu
-import XMonad
-import Control.Monad
-import Data.Map (Map)
-import qualified Data.Map as Map
-import XMonad.Util.Run
-import Data.List (intercalate)
-import Text.Printf (printf)
-
-data Colors =
- Colors {
- fg :: String,
- bg :: String
- } | DefaultColors
-
-menuCommand :: [String]
-menuCommand = ["rofi", "-monitor", "-4", "-dmenu", "-sort", "-levenshtein-sort"]
-
-menuCommandString :: String
-menuCommandString = unwords menuCommand
-
-runDMenu :: X ()
-runDMenu = void $
- safeSpawn
- "rofi"
- ["-monitor", "-4", "-display-run", "Execute", "-show", "run"]
-
-runDMenuPrompt :: String -> Maybe String -> [String] -> X String
-runDMenuPrompt prompt color select =
- let realColor = maybe [] (\c -> ["-sb", c, "-nf", c]) color
- in
- runProcessWithInput "/home/rahm/.local/bin/dmenu_debug.sh" ([
- "-p", prompt,
- "-l", "12",
- "-dim", "0.4" ] ++ realColor) (intercalate "\n" select)
-
-
-runDMenuPromptWithMap :: String -> Maybe String -> Map String a -> X (Maybe a)
-runDMenuPromptWithMap prompt color map = do
- let realColor = maybe [] (
- \c -> ["-theme-str", printf "* {theme-color: %s;}" c]) color
- menuMapArgs (head menuCommand)
- (tail menuCommand ++ ["-p", prompt] ++ realColor) map
diff --git a/src/Internal/Hash.hs b/src/Internal/Hash.hs
deleted file mode 100644
index 272808b..0000000
--- a/src/Internal/Hash.hs
+++ /dev/null
@@ -1,11 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Internal.Hash where
-
-import Numeric (showHex)
-import qualified Data.ByteString as BS
-import qualified Data.ByteString.Char8 as BC
-import qualified Crypto.Hash.SHA1 as SHA1
-
-quickHash :: String -> String
-quickHash str =
- concatMap (`showHex` "") $ BS.unpack (SHA1.hash $ BC.pack str)
diff --git a/src/Internal/Keys.hs b/src/Internal/Keys.hs
deleted file mode 100644
index ad9d719..0000000
--- a/src/Internal/Keys.hs
+++ /dev/null
@@ -1,820 +0,0 @@
-{-# LANGUAGE RankNTypes, FlexibleContexts, ViewPatterns #-}
-module Internal.Keys (applyKeys) where
-
-import XMonad.Util.Run (safeSpawn)
-import Data.Monoid (Endo(..))
-import Control.Monad.Trans.Class
-import Control.Monad.Reader
-import Control.Monad.Writer
-import Control.Monad.Loops (iterateWhile)
-import Control.Monad.Fix (fix)
-import Graphics.X11.ExtraTypes.XF86;
-import Internal.KeysM
-import Internal.SwapMaster (swapMaster)
-import XMonad.Hooks.ManageDocks
-import XMonad.Layout.MosaicAlt
-import Graphics.X11.ExtraTypes.XorgDefault
-import System.Process
-import XMonad.Util.Ungrab
-import XMonad.Layout.Spacing
-import Data.Maybe (isJust, fromMaybe)
-import Debug.Trace
-import Control.Applicative
-import Prelude hiding ((!!))
-import Control.Monad
-import Data.Char
-import Data.List hiding ((!!))
-import Data.List.Safe ((!!))
-import Data.Map (Map)
-import Internal.Layout
-import Internal.Marking
-import Internal.PromptConfig
-import System.IO
-import Text.Printf
-import XMonad
-import Internal.Submap
-import XMonad.Actions.WindowNavigation
-import XMonad.Prompt
-import XMonad.Prompt.Input
-import XMonad.Prompt.Shell
-import XMonad.Util.CustomKeys
-import XMonad.Util.Scratchpad
-import XMonad.Actions.RotSlaves
-import XMonad.Actions.CopyWindow as CopyWindow
-import XMonad.Actions.SpawnOn as SpawnOn
-
-import qualified Data.Map as Map
-import qualified XMonad.StackSet as W
-
-import Internal.LayoutList
-import Internal.MouseMotion
-import Internal.Windows
-import Internal.Lib
-import Internal.DMenu
-import Internal.PassMenu
-import Internal.Logger
-import Internal.RebindKeys
-import Internal.Swallow
-import Internal.ScreenRotate (screenRotateForward, screenRotateBackward)
-
-type KeyMap l = XConfig l -> Map (KeyMask, KeySym) (X ())
-type ButtonsMap l = XConfig l -> Map (KeyMask, Button) (Window -> X ())
-
-
-spawnX :: String -> X ()
-spawnX = spawn
-
-noWindow :: b -> Window -> b
-noWindow = const
-
-decreaseVolume = spawnX "pactl set-sink-volume @DEFAULT_SINK@ -5%"
-increaseVolume = spawnX "pactl set-sink-volume @DEFAULT_SINK@ +5%"
-playPause = spawnX "spotify-control play"
-mediaPrev = spawnX "spotify-control prev"
-mediaNext = spawnX "spotify-control next"
-
-decreaseVolumeDoc = doc "Decrease volume" decreaseVolume
-increaseVolumeDoc = doc "Increase volume" increaseVolume
-playPauseDoc = doc "Play/Pause current media" playPause
-mediaPrevDoc = doc "Previous media" mediaPrev
-mediaNextDoc = doc "Next media" mediaNext
-
-
-button6 :: Button
-button6 = 6
-
-button7 :: Button
-button7 = 7
-
-button8 :: Button
-button8 = 8
-
-button9 :: Button
-button9 = 9
-
-button10 :: Button
-button10 = 10
-
-button11 :: Button
-button11 = 11
-
-button12 :: Button
-button12 = 12
-
-button13 :: Button
-button13 = 13
-
-button14 :: Button
-button14 = 14
-
-button15 :: Button
-button15 = 15
-
-keyBindingToKeymap :: (XConfig l -> KeyBindings) -> KeyMap l
-keyBindingToKeymap bindings config = fmap bindingToX (bindings config)
-
- where
- bindingToX b =
- case b of
- Documented _ (Action x) -> x
- Documented _ (Submap mapping) ->
- submap (fmap bindingToX mapping)
- Documented _ (Repeat mapping) ->
- fix $ \recur ->
- submap (fmap (\b -> bindingToX b >> recur) mapping)
-
-keymap :: XConfig l -> KeyBindings
-keymap = runKeys $ do
- config <- getConfig
-
- let subkeys keysM = Submap (runKeys keysM config)
- repeatable keysM = Repeat (runKeys keysM config)
-
- bind xK_apostrophe $ do
- justMod $
- doc "Jumps between marks." $
- mapNextString $ \_ str ->
- case str of
- ['\''] -> jumpToLast
- [ch] | isAlphaNum ch -> jumpToMark ch
- "[" -> historyPrev
- "]" -> historyNext
- _ -> return ()
-
- shiftMod $
- doc "Swap the current window with a mark." $
- mapNextString $ \_ str ->
- case str of
- ['\''] -> swapWithLastMark
- [ch] | isAlphaNum ch -> swapWithMark ch
- _ -> return ()
-
- bind xK_BackSpace $ do
- -- The only raw keybinding. Meant to get a terminal to unbrick XMonad if
- -- something goes wrong with the keyboard layout and for first-time boots
- -- where dmenu/alacritty may not be installed.
- rawMask mod4Mask $
- doc "Spawns XTerm as a fallback if xkb is messed up." $
- spawnX "xterm"
-
- -- Moves xmobar to different monitors.
- justMod $
- doc "Move XMobar to another screen." $
- spawnX "pkill -SIGUSR1 xmobar"
-
- bind xK_F1 $ do
- -- Experimental. Sends 'a' to all windows.
- --
- -- I've discovered that many clients ignore such synthetic events, including
- -- Spotify, Chrome and Gedit. Some, like Chrome, seem to honor them if it's
- -- focused. It's pretty annoying because it keeps me from doing some cool
- -- things all for BS security theater, but I guess there might be some way
- -- to do this via XTest?
- shiftMod $ forAllWindows $ \w -> do
- logs $ "Try send to " ++ show w
- sendKey (0, xK_a) w
-
- justMod $
- doc "Print this documentation"
- (safeSpawn "gxmessage" [
- "-fn", "Source Code Pro",
- documentation (keymap config)] :: X ())
-
- bind xK_F7 $
-
- justMod $
- doc "Print this documentation." $
- logs (documentation (keymap config))
-
- bind xK_F10 $ do
- justMod playPauseDoc
-
- bind xK_F11 $ do
- justMod mediaPrevDoc
-
- bind xK_F12 $ do
- justMod mediaNextDoc
-
- bind xK_Return $ do
- justMod swapMaster
-
- bind xK_Tab $ do
- justMod $ windows W.focusDown
- shiftMod $ windows W.focusUp
-
- -- Switch between different screens. These are the leftmost keys on the home
- -- row in a Dvorak layout. One might want to switch these to ASD for QWERTY.
- forM_ (zip [xK_a, xK_o, xK_e] [0..]) $ \(key, idx) ->
- bind key $ do
- -- Move focus to that screen.
- justMod $
- doc ("Switch focus to screen " ++ show idx) $
- withScreen W.view idx
- -- Swap the current screen with the one given
- altMod $
- doc ("Swap the current screen with screen " ++ show idx) $
- withScreen W.greedyView idx
- -- Move the current window to the select screen.
- shiftMod $
- doc ("Move the current window to screne " ++ show idx) $
- withScreen W.shift idx
-
- altgrMod $
- logs "Test altgr"
-
- bind xK_bracketright $ do
- justMod $
- doc "Increase the gaps between windows." $
- sendMessage $ modifyWindowBorder 5
-
- bind xK_bracketleft $ do
- justMod $
- doc "Decrease the gaps between windows." $
- sendMessage $ modifyWindowBorder (-5)
-
- bind xK_b $ do
- justMod $ spawnX "bluetooth-select.sh"
-
- bind xK_c $ do
- justMod $
- doc "Run PassMenu" runPassMenu
-
- shiftMod $
- doc "Kill the current window" CopyWindow.kill1
-
- bind xK_f $ do
- justMod $
- doc "Flip the current layout vertically" $
- sendMessage FlipLayout
- shiftMod $
- doc "Flip the current layout horizontally" $
- sendMessage HFlipLayout
-
- bind xK_g $ do
- justMod $
- doc "Goto a workspace\n\n\t\
-
- \If the second character typed is alpha-numberic, jump to that\n\t\
- \workspace. The workspace is created on-the-fly if such a workspace\n\t\
- \does not exist.\n\n\t\
-
- \If the second character typed is:\n\t\t\
- \]: go to the next workspace\n\t\t\
- \[: go to the previous workspace\n\t\t\
- \}: cycle the workspaces on the screens to the right\n\t\t\
- \{: cycle the workspaces on the screens to the left\n\t\t\
- \<space>: Jump to the accompaning workspace.\n\t\t\
- \F1: display this help.\n" $
- mapNextStringWithKeysym $ \_ keysym str ->
- case (keysym, str) of
- (_, [ch]) | isAlphaNum ch -> gotoWorkspace ch
- (_, "]") -> pushHistory $ withRelativeWorkspace next W.greedyView
- (_, "[") -> pushHistory $ withRelativeWorkspace prev W.greedyView
- (_, "}") -> windows screenRotateForward
- (_, "{") -> windows screenRotateBackward
- (_, " ") -> gotoAccompaningWorkspace
-
- -- Test binding. Tests that I can still submap keysyms alone (keys
- -- where XLookupString won't return anything helpful.)
- (f, _) | f == xK_F1 ->
- (safeSpawn "gxmessage" [
- "-fn", "Source Code Pro",
- documentation (keymap config)] :: X ())
-
- _ -> return ()
- shiftMod $
- doc "Move the currently focused window to another workspace" $
- mapNextString $ \_ str ->
- case str of
- [ch] | isAlphaNum ch -> shiftToWorkspace ch
- "]" -> withRelativeWorkspace next W.shift
- "[" -> withRelativeWorkspace prev W.shift
- _ -> return ()
- shiftAltMod $
- doc "Swap this workspace with another workspace (rename)." $
- mapNextString $ \_ str ->
- case str of
- [ch] | isAlphaNum ch -> swapWorkspace ch
- _ -> return ()
-
- bind xK_h $ do
- justMod $
- doc "Focus on the next window down in the stack" $
- windows W.focusDown
-
- shiftMod $
- doc "Swap the current window with the next one down in the stack" $
- windows W.swapDown
-
- controlMod $
- doc "Rotate all the windows down the stack"
- rotAllDown
-
- bind xK_j $ do
- justMod $
- doc "Shrink the size of the zoom region" $
- sendMessage ShrinkZoom
-
- shiftMod $
- doc "Go to the previous window in history." historyPrev
-
- bind xK_k $ do
- justMod $
- doc "Expand the size of the zoom region" $
- sendMessage ExpandZoom
-
- shiftMod $
- doc "Go to the next window in history." historyNext
-
- bind xK_l $ do
- justMod $
- doc "Focus the next window in the stack" $
- windows W.focusUp
-
- shiftMod $
- doc "Swap the currently focused window with the next window in the stack." $
- windows W.swapUp
-
- controlMod $
- doc "Rotate the windows up."
- rotAllUp
-
- altMod $
- doc "Lock the screen" $
- spawnX "xsecurelock"
-
- bind xK_minus $ do
- justMod $
- doc "Decrease the number of windows in the master region." $
- sendMessage (IncMasterN (-1))
-
- shiftMod $
- doc "For mosaic layout, shrink the size-share of the current window" $
- withFocused $ sendMessage . shrinkWindowAlt
-
- bind xK_m $ do
- justMod $
- doc "Mark the current window with the next typed character." $
- mapNextString $ \_ str ->
- case str of
- [ch] | isAlphaNum ch -> markCurrentWindow ch
- _ -> return ()
-
- bind xK_n $ do
- justMod $
- doc "Shift to the next workspace." $
- withRelativeWorkspace next W.greedyView
-
- bind xK_p $ do
- justMod $
- doc "Shift to the previous workspace." $
- withRelativeWorkspace prev W.greedyView
-
- bind xK_plus $ do
- justMod $
- doc "Increase the number of windows in the master region." $
- sendMessage (IncMasterN 1)
-
- shiftMod $
- doc "For mosaic layout, increase the size-share of the current window." $
- withFocused $ sendMessage . expandWindowAlt
-
- bind xK_q $ do
- shiftMod $
- doc "Recompile and restart XMonad" $
- spawnX "xmonad --recompile && xmonad --restart"
-
- justMod $
- doc "Experimental Bindings" $
- subkeys $ do
-
- bind xK_q $
- (justMod -|- noMod) $
- doc "EXPERIMENTAL: Move mouse to control media." $
- mouseRotateMotion (logs "CW") (logs "CCW")
-
- bind xK_r $ do
- justMod $ doc "Run a command via Rofi" runDMenu
- shiftMod $
- doc "Rotate the current layout. (flips x, y coordinates)" $
- sendMessage DoRotate
-
- bind xK_s $ do
- altMod $ spawnX "sudo -A systemctl suspend && xsecurelock"
-
- bind xK_space $ do
- justMod $
- doc "Use the next layout in the layout list." $ sendMessage toNextLayout
-
- altMod $
- doc "Reset the layout to the default layout." $ sendMessage toFirstLayout
-
- shiftMod $
- doc "Use the previous layout in the layout list." $
- sendMessage toPreviousLayout
-
- bind xK_t $ do
- justMod $
- doc "Spawn a terminal." $ spawnX (terminal config)
-
- shiftMod $
- doc "Sink the current window into the tiling." $ withFocused $ windows . W.sink
-
- altMod $
- doc "Spawn a floating terminal" $ spawnX (terminal config ++ " -t Floating\\ Term")
-
- bind xK_v $
- -- Allows repeated strokes of M-h and M-l to reduce and increase volume
- -- respectively.
- justMod $
- doc "Changes the volume." $
- repeatable $ do
- bind xK_h $
- justMod $
- doc "Decrease volume."
- decreaseVolumeDoc
-
- bind xK_l $
- justMod $
- doc "Increase volume."
- increaseVolumeDoc
-
- bind xK_v $
- justMod (return () :: X ())
-
- bind xK_w $ do
- justMod $ doc "Jump to a window (via rofi)" windowJump
-
- bind xK_x $ do
- justMod $
- doc "Toggles respect for struts." $
- sendMessage ToggleStruts
-
- bind xK_z $ do
-
- justMod $
- doc "Less often used keybindings." $
- subkeys $ do
-
- bind xK_g $ do
- (justMod -|- noMod) $
- doc "Copy a window to the given workspace" $
- mapNextString $ \_ s ->
- case s of
- [ch] | isAlphaNum ch -> windows (CopyWindow.copy s)
- _ -> return ()
-
- bind xK_p $ do
- (justMod -|- noMod) $
- doc "Go to the prior window in the history" historyPrev
-
- bind xK_t $ do
- (justMod -|- noMod) $ logs "Test Log"
-
- -- bind xK_n $ do
- -- (justMod -|- noMod) $
- -- doc "Take a note" $
- -- spawnX (terminal config ++ " -t Notes -e notes new")
- bind xK_n $ do
- (justMod -|- noMod) $
- doc "Go to the next window in the history" historyNext
-
- bind xK_c $ do
- shiftMod $
- doc "Kill all other copies of a window."
- CopyWindow.killAllOtherCopies
-
- bind xK_e $ do
- (justMod -|- noMod) $
- doc "Select an emoji" $
- spawnX "emoji-select.sh"
-
- (shiftMod -|- rawMask shiftMask) $
- doc "Select an emoticon" $
- spawnX "emoticon-select.sh"
-
- bind xK_a $
- (justMod -|- noMod) $
- doc "Move the audio sink for an application." $
- spawnX "set-sink.sh"
-
- bind xK_w $
- (justMod -|- noMod) $
- doc "Select a network to connect to." $
- spawnX "networkmanager_dmenu"
-
- bind xK_o $
- (justMod -|- noMod) $
- doc "Open a file from the library" $
- spawnX "library-view.sh"
-
- bind xK_s $
- (justMod -|- noMod) $
- doc "Toggle the ability for terminals to swallow child windows."
- toggleSwallowEnabled
-
- bind xK_v $ do
- (justMod -|- noMod) $
- doc "Set the volume via rofi." $
- spawnX "set-volume.sh"
- (shiftMod -|- rawMask shiftMask) $
- doc "Set the volume of an application via rofi." $
- spawnX "set-volume.sh -a"
-
- -- Double-tap Z to toggle zoom.
- bind xK_z $ do
- noMod -|- justMod $
- doc "Toggle zoom on the current window." $
- sendMessage ToggleZoom
-
- -- Z is reserved to create sub keybindings to do various things.
- -- I don't really use these at the moment.
- bind xK_h $ noMod mediaPrevDoc
- bind xK_j $ noMod playPauseDoc
- bind xK_l $ noMod mediaNextDoc
-
- -- Centers the current focused window. i.e. toggles the Zoom layout
- -- modifier.
- shiftMod $
- doc "Toggle zoom on the current window." $
- sendMessage ToggleZoom
-
- bind xF86XK_Calculator $ do
- noMod $ spawnX $ terminal config ++ " -t Floating\\ Term -e /usr/bin/env python3"
-
- bind xF86XK_AudioLowerVolume $ do
- noMod $ spawnX "pactl set-sink-volume @DEFAULT_SINK@ -1%"
- justMod mediaPrevDoc
-
- bind xF86XK_AudioRaiseVolume $ do
- noMod $ spawnX "pactl set-sink-volume @DEFAULT_SINK@ +1%"
- justMod mediaNextDoc
-
- bind xF86XK_AudioMute $ do
- noMod $ spawnX "pactl set-sink-mute @DEFAULT_SINK@ toggle"
-
- bind xF86XK_AudioPlay $ do
- noMod playPauseDoc
-
- bind xF86XK_AudioNext $ do
- noMod mediaNextDoc
-
- bind xF86XK_AudioPrev $ do
- noMod mediaPrevDoc
-
- bind xF86XK_AudioPrev $ do
- noMod mediaPrevDoc
-
- bind xF86XK_MonBrightnessUp $ do
- noMod $ spawnX "set-backlight.sh +0.05"
- justMod $ spawnX "set-backlight.sh 1"
-
- bind xF86XK_MonBrightnessDown $ do
- noMod $ spawnX "set-backlight.sh -0.05"
- justMod $ spawnX "set-backlight.sh 0.01"
- rawMask shiftMask $ spawnX "set-backlight.sh 0"
-
-mouseMap :: ButtonsMap l
-mouseMap = runButtons $ do
- config <- getConfig
-
- let x button = Map.lookup button (mouseMap config)
-
- let defaultButtons button = fromMaybe (\w -> return ()) $
- Map.lookup button (mouseMap config)
- subMouse = submapButtonsWithKey defaultButtons . flip runButtons config
-
-
- let continuous :: [(Button, X ())] -> Button -> Window -> X ()
- continuous actions button w = do
- case find ((==button) . fst) actions of
- Just (_, action) -> action
- Nothing -> return ()
-
- (subMouse $
- forM_ (map fst actions) $ \b ->
- bind b $ noMod $ \w -> continuous actions b w) w
-
- bind button1 $ do
- justMod $ \w -> focus w >> mouseMoveWindow w >> windows W.shiftMaster
-
- bind button2 $ do
- justMod $ windows . (W.shiftMaster .) . W.focusWindow
-
- bind button3 $ do
- justMod $ \w -> focus w >> mouseResizeWindow w >> windows W.shiftMaster
-
- bind button6 $
- justMod $ noWindow (withRelativeWorkspace prev W.greedyView)
-
- bind button7 $
- justMod $ noWindow (withRelativeWorkspace next W.greedyView)
-
- bind button8 $
- justMod $ noWindow mediaPrev
-
- bind button9 $
- justMod $ noWindow mediaNext
-
- bind button14 $ do
- noMod $ subMouse $ do
-
- bind button3 $
- noMod $ noWindow (gotoWorkspace 's')
-
- bind button13 $ do
- noMod $ noWindow $ click >> CopyWindow.kill1
-
- bind button14 $ do
- noMod $ noWindow $ click >> sendMessage ToggleZoom
-
- bind button15 $ do
- noMod $ noWindow $ spawnX "pavucontrol"
-
- let mediaButtons = [
- (button4, increaseVolume),
- (button5, decreaseVolume),
- (button2, playPause),
- (button9, historyNext),
- (button8, historyPrev),
- (button6, mediaPrev),
- (button7, mediaNext)
- ]
-
- forM_ (map fst mediaButtons) $ \b ->
- bind b $ noMod $ continuous mediaButtons b
-
- bind button13 $ noMod $ subMouse $ do
- bind button1 $ noMod mouseMoveWindow
- bind button2 $ noMod $ windows . W.sink
- bind button3 $ noMod mouseResizeWindow
-
- bind button13 $ noMod $ subMouse $ do
- bind button13 $ noMod $ subMouse $ do
- bind button13 $ noMod $ noWindow $ spawnX "xsecurelock"
- bind button1 $ noMod $ noWindow $
- spawnX "sudo -A systemctl suspend && xsecurelock"
-
- bind button15 $ do
-
- noMod $ subMouse $ do
- bind button13 $ noMod $ noWindow gotoAccompaningWorkspace
-
- bind button15 $ do
- noMod $ noWindow jumpToLast
-
-
- let workspaceButtons = [
- (button2, swapMaster),
-
- (button9, withRelativeWorkspace next W.greedyView),
- (button8, withRelativeWorkspace prev W.greedyView),
-
- (button4, windows W.focusUp),
- (button5, windows W.focusDown),
-
- (button7, windows screenRotateForward),
- (button6, windows screenRotateBackward)
- ]
-
- forM_ (map fst workspaceButtons) $ \b ->
- bind b $ noMod $ continuous workspaceButtons b
-
--- Bindings specific to a window. These are set similarly to th ekeymap above,
--- but uses a Query monad to tell which windows the keys will apply to.
---
--- This is useful to create hotkeys in applications where hot keys are not
--- configurable, or to remove keybindings that are irritating (looking at you,
--- ctrl+w in Chrome!!).
-windowSpecificBindings ::
- XConfig l -> WriterT (Map (KeyMask, KeySym) (X ())) Query ()
-windowSpecificBindings config = do
-
- w <- lift ask
-
- let configureIf b k = tell =<< lift (b --> return (keyBindingToKeymap (runKeys k) config))
- emitKey = flip sendKey w
-
- configureIf (flip elem browsers <$> className) $ do
-
- -- if the window is a browser, configure these bindings. Lots of browsers
- -- make up their own garbage bindings that are not standard across many
- -- other applications. This alleviates the issue.
- --
- -- Consistency with terminal:
- --
- -- Ctrl+h is backspace
- -- Ctrl+w is ctrl+backspace
- -- Ctrl+u is ctrl+shift+backspace
- --
- -- Consistency with Vim/Emacs-ish:
- --
- -- Alt+{Shift,Ctrl,}+{h,j,k,l} -> {Shift,Ctrl,}+{Left,Down,Up,Right}
- -- Ctrl+b -> Ctrl+Left
- -- Ctrl+e -> Ctrl+Right
- -- Ctrl+$ -> End
- -- Ctrl+^ -> Home
- --
- -- Ctrl+d -> Delete current tab.
-
-
- let mods = permuteMods [shiftMask, controlMask, 0]
-
- bind xK_h $ do
- rawMask controlMask $ emitKey (0, xK_BackSpace)
- forM_ mods $ \mask ->
- rawMask (altMask .|. mask) $ emitKey (mask, xK_Left)
-
- bind xK_j $
- forM_ mods $ \mask ->
- rawMask (altMask .|. mask) $ emitKey (mask, xK_Down)
-
- bind xK_k $
- forM_ mods $ \mask ->
- rawMask (altMask .|.mask) $ emitKey (mask, xK_Up)
-
- bind xK_l $
- forM_ mods $ \mask ->
- rawMask (altMask .|. mask) $ emitKey (mask, xK_Right)
-
- bind xK_u $
- rawMask controlMask $ emitKey (controlMask .|. shiftMask, xK_BackSpace)
-
- bind xK_w $
- rawMask controlMask $ emitKey (controlMask, xK_BackSpace)
-
- bind xK_b $ do
- rawMask controlMask $ emitKey (controlMask, xK_Left)
- rawMask (controlMask .|. shiftMask) $
- emitKey (controlMask .|. shiftMask, xK_Left)
-
- bind xK_e $ do
- rawMask controlMask $ emitKey (controlMask, xK_Right)
- rawMask (controlMask .|. shiftMask) $
- emitKey (controlMask .|. shiftMask, xK_Right)
-
- bind xK_dollar $
- rawMask controlMask $ emitKey (0, xK_End)
-
- bind xK_at $
- rawMask (controlMask .|. shiftMask) $ emitKey (0, xK_Home)
-
- bind xK_d $
- rawMask controlMask $ emitKey (controlMask, xK_w)
-
- bind xK_F2 $
- -- Experimental.
- noMod $ logs "This is a test"
-
- -- Add a binding to xev as a test.
- configureIf (title =? "Event Tester") $
- bind xK_F2 $
- noMod $ emitKey (controlMask, xK_F2)
-
- where
- browsers = ["Google-chrome", "Brave-browser", "firefox-default"]
-
- -- Create a permutation from a list of modifiers.
- --
- -- i.e. permuteMods [C, S, M] will return
- --
- -- [C, S, M, C + M, C + S, M + S, C + S + M, 0]
- permuteMods = map (foldl' (.|.) 0) . filterM (const [True, False])
-
-windowBindings :: XConfig l -> XConfig l
-windowBindings xconfig =
- xconfig {
- startupHook = do
- forAllWindows (runQuery doQuery)
- startupHook xconfig,
-
- manageHook = (doQuery >> return (Endo id)) <> manageHook xconfig
- }
-
- where
- doQuery :: Query ()
- doQuery = do
- map <- execWriterT $ windowSpecificBindings xconfig
- w <- ask
-
- liftX $ logs $ printf "For Window: %s" (show w)
- forM_ (Map.toList map) $ \(key, action) -> do
- liftX $ logs $ printf " -- remap: %s" (show key)
- remapKey key action
-
-applyKeys :: XConfig l -> IO (XConfig l)
-applyKeys config =
- return $ windowBindings $ config { keys = keyBindingToKeymap keymap, mouseBindings = mouseMap }
-
-click :: X ()
-click = do
- (dpy, root) <- asks $ (,) <$> display <*> theRoot
- (_, _, window, _, _, _, _, _) <- io $ queryPointer dpy root
- focus window
-
-modifyWindowBorder :: Integer -> SpacingModifier
-modifyWindowBorder i = ModifyWindowBorder $ \(Border a b c d) ->
- Border (clip $ a + i) (clip $ b + i) (clip $ c + i) (clip $ d + i)
-
- where clip i | i < 0 = 0
- clip i = i
diff --git a/src/Internal/KeysM.hs b/src/Internal/KeysM.hs
deleted file mode 100644
index e490b89..0000000
--- a/src/Internal/KeysM.hs
+++ /dev/null
@@ -1,497 +0,0 @@
-{-# Language GeneralizedNewtypeDeriving, MultiParamTypeClasses,
- FunctionalDependencies, FlexibleInstances, TypeFamilies, FlexibleContexts #-}
-module Internal.KeysM where
-
-import Data.List
-import Data.Bits ((.&.))
-import Control.Monad.Writer
-import Text.Printf
-import Control.Arrow (second, first)
-import Control.Monad (void)
-import Control.Monad.State (State(..), modify', get, execState)
-import XMonad
-import Data.Map (Map)
-import qualified Data.Map as Map
-
-data Documented t = Documented String t
-
-data KeyBinding =
- Action (X ()) |
- Submap KeyBindings |
- Repeat KeyBindings
-
-type KeyBindings = Map (KeyMask, KeySym) (Documented KeyBinding)
-
-type ButtonBinding = Window -> X ()
-type ButtonBindings = Map (KeyMask, Button) ButtonBinding
-
-{- Module that defines a DSL for binding keys. -}
-newtype KeysM l a = KeysM (State (XConfig l, KeyBindings) a)
- deriving (Functor, Applicative, Monad)
-
-newtype ButtonsM l a = ButtonsM (State (XConfig l, ButtonBindings) a)
- deriving (Functor, Applicative, Monad)
-
-newtype BindingBuilder b a = BindingBuilder (State (KeyMask, [(KeyMask, b)]) a)
- deriving (Functor, Applicative, Monad)
-
-class HasConfig m where
- getConfig :: m l (XConfig l)
-
-class Bindable k where
- type BindableValue k :: *
- type BindableMonad k :: (* -> *) -> * -> *
-
- bind :: k -> BindingBuilder (BindableValue k) a -> BindableMonad k l ()
- -- section :: String -> BindableMonad k l () -> BindableMonad k l ()
-
-class Binding k b where
- toB :: k -> b
-
- rawMask :: KeyMask -> k -> BindingBuilder b ()
- rawMask m x = BindingBuilder $ modify' (second ((m, toB x):))
-
-instance Binding (X ()) (Documented KeyBinding) where
- toB = Documented "" . Action
-
-instance Binding KeyBindings (Documented KeyBinding) where
- toB = Documented "" . Submap
-
-instance Binding a (Documented a) where
- toB = Documented ""
-
-instance Binding a a where
- toB = id
-
-doc :: (Binding k (Documented KeyBinding)) => String -> k -> Documented KeyBinding
-doc str k = let (Documented _ t) = toB k in Documented str t
-
-runKeys :: KeysM l a -> XConfig l -> KeyBindings
-runKeys (KeysM stateM) config =
- snd $ execState stateM (config, Map.empty)
-
-runButtons :: ButtonsM l a -> XConfig l -> ButtonBindings
-runButtons (ButtonsM stateM) config =
- snd $ execState stateM (config, Map.empty)
-
-instance HasConfig KeysM where
- getConfig = fst <$> KeysM get
-
-instance HasConfig ButtonsM where
- getConfig = fst <$> ButtonsM get
-
-{- Generally it is assumed that the mod key shoud be pressed, but not always. -}
-noMod :: (Binding k b) => k -> BindingBuilder b ()
-noMod = rawMask 0
-
-maskMod :: (Binding k b) => KeyMask -> k -> BindingBuilder b ()
-maskMod mask action = do
- modMask <- fst <$> BindingBuilder get
- rawMask (modMask .|. mask) action
-
-altMask :: KeyMask
-altMask = mod1Mask
-
-hyperMask :: KeyMask
-hyperMask = mod3Mask
-
-altgrMask :: KeyMask
-altgrMask = 0x80
-
-superMask :: KeyMask
-superMask = mod4Mask
-
-justMod :: (Binding k b) => k -> BindingBuilder b ()
-justMod = maskMod 0
-
-instance Bindable KeySym where
- type BindableValue KeySym = Documented KeyBinding
- type BindableMonad KeySym = KeysM
-
- -- bind :: KeySym -> BindingBuilder (X x) a -> KeysM l ()
- bind key (BindingBuilder stM) = do
- m <- modMask <$> getConfig
- let (_, values) = execState stM (m, [])
-
- KeysM $ modify' $ second $
- flip (<>) (Map.fromList (map (\(m, v) -> ((m, key), v)) values))
-
-
-instance Bindable Button where
- type BindableValue Button = ButtonBinding
- type BindableMonad Button = ButtonsM
-
- -- bind :: KeySym -> BindingBuilder (Window -> X ()) a -> ButtonsM l ()
- bind button (BindingBuilder stM) = do
- m <- modMask <$> getConfig
- let (_, values) = execState stM (m, [])
-
- ButtonsM $ modify' $ second $
- flip (<>) (Map.fromList (map (\(m, v) -> ((m, button), v)) values))
-
-shiftControlAltSuperHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltSuperHyperAltgrMod =
- maskMod (shiftMask .|. controlMask .|. altMask .|. superMask .|. hyperMask .|. altgrMask)
-
-shiftControlAltSuperHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltSuperHyperMod =
- maskMod (shiftMask .|. controlMask .|. altMask .|. superMask .|. hyperMask)
-
-shiftControlAltSuperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltSuperAltgrMod =
- maskMod (shiftMask .|. controlMask .|. altMask .|. superMask .|. altgrMask)
-
-shiftControlAltSuperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltSuperMod =
- maskMod (shiftMask .|. controlMask .|. altMask .|. superMask)
-
-shiftControlAltHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltHyperAltgrMod =
- maskMod (shiftMask .|. controlMask .|. altMask .|. hyperMask .|. altgrMask)
-
-shiftControlAltHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltHyperMod =
- maskMod (shiftMask .|. controlMask .|. altMask .|. hyperMask)
-
-shiftControlAltAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltAltgrMod =
- maskMod (shiftMask .|. controlMask .|. altMask .|. altgrMask)
-
-shiftControlAltMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltMod =
- maskMod (shiftMask .|. controlMask .|. altMask)
-
-shiftControlSuperHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlSuperHyperAltgrMod =
- maskMod (shiftMask .|. controlMask .|. superMask .|. hyperMask .|. altgrMask)
-
-shiftControlSuperHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlSuperHyperMod =
- maskMod (shiftMask .|. controlMask .|. superMask .|. hyperMask)
-
-shiftControlSuperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlSuperAltgrMod =
- maskMod (shiftMask .|. controlMask .|. superMask .|. altgrMask)
-
-shiftControlSuperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlSuperMod =
- maskMod (shiftMask .|. controlMask .|. superMask)
-
-shiftControlHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlHyperAltgrMod =
- maskMod (shiftMask .|. controlMask .|. hyperMask .|. altgrMask)
-
-shiftControlHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlHyperMod =
- maskMod (shiftMask .|. controlMask .|. hyperMask)
-
-shiftControlAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlAltgrMod =
- maskMod (shiftMask .|. controlMask .|. altgrMask)
-
-shiftControlMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftControlMod =
- maskMod (shiftMask .|. controlMask)
-
-shiftAltSuperHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltSuperHyperAltgrMod =
- maskMod (shiftMask .|. altMask .|. superMask .|. hyperMask .|. altgrMask)
-
-shiftAltSuperHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltSuperHyperMod =
- maskMod (shiftMask .|. altMask .|. superMask .|. hyperMask)
-
-shiftAltSuperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltSuperAltgrMod =
- maskMod (shiftMask .|. altMask .|. superMask .|. altgrMask)
-
-shiftAltSuperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltSuperMod =
- maskMod (shiftMask .|. altMask .|. superMask)
-
-shiftAltHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltHyperAltgrMod =
- maskMod (shiftMask .|. altMask .|. hyperMask .|. altgrMask)
-
-shiftAltHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltHyperMod =
- maskMod (shiftMask .|. altMask .|. hyperMask)
-
-shiftAltAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltAltgrMod =
- maskMod (shiftMask .|. altMask .|. altgrMask)
-
-shiftAltMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltMod =
- maskMod (shiftMask .|. altMask)
-
-shiftSuperHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftSuperHyperAltgrMod =
- maskMod (shiftMask .|. superMask .|. hyperMask .|. altgrMask)
-
-shiftSuperHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftSuperHyperMod =
- maskMod (shiftMask .|. superMask .|. hyperMask)
-
-shiftSuperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftSuperAltgrMod =
- maskMod (shiftMask .|. superMask .|. altgrMask)
-
-shiftSuperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftSuperMod =
- maskMod (shiftMask .|. superMask)
-
-shiftHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftHyperAltgrMod =
- maskMod (shiftMask .|. hyperMask .|. altgrMask)
-
-shiftHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftHyperMod =
- maskMod (shiftMask .|. hyperMask)
-
-shiftAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftAltgrMod =
- maskMod (shiftMask .|. altgrMask)
-
-shiftMod :: (Binding k b) => k -> BindingBuilder b ()
-shiftMod = maskMod shiftMask
-
-controlAltSuperHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltSuperHyperAltgrMod =
- maskMod (controlMask .|. altMask .|. superMask .|. hyperMask .|. altgrMask)
-
-controlAltSuperHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltSuperHyperMod =
- maskMod (controlMask .|. altMask .|. superMask .|. hyperMask)
-
-controlAltSuperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltSuperAltgrMod =
- maskMod (controlMask .|. altMask .|. superMask .|. altgrMask)
-
-controlAltSuperMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltSuperMod =
- maskMod (controlMask .|. altMask .|. superMask)
-
-controlAltHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltHyperAltgrMod =
- maskMod (controlMask .|. altMask .|. hyperMask .|. altgrMask)
-
-controlAltHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltHyperMod =
- maskMod (controlMask .|. altMask .|. hyperMask)
-
-controlAltAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltAltgrMod =
- maskMod (controlMask .|. altMask .|. altgrMask)
-
-controlAltMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltMod =
- maskMod (controlMask .|. altMask)
-
-controlSuperHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-controlSuperHyperAltgrMod =
- maskMod (controlMask .|. superMask .|. hyperMask .|. altgrMask)
-
-controlSuperHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-controlSuperHyperMod =
- maskMod (controlMask .|. superMask .|. hyperMask)
-
-controlSuperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-controlSuperAltgrMod =
- maskMod (controlMask .|. superMask .|. altgrMask)
-
-controlSuperMod :: (Binding k b) => k -> BindingBuilder b ()
-controlSuperMod =
- maskMod (controlMask .|. superMask)
-
-controlHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-controlHyperAltgrMod =
- maskMod (controlMask .|. hyperMask .|. altgrMask)
-
-controlHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-controlHyperMod =
- maskMod (controlMask .|. hyperMask)
-
-controlAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-controlAltgrMod =
- maskMod (controlMask .|. altgrMask)
-
-controlMod :: (Binding k b) => k -> BindingBuilder b ()
-controlMod = maskMod controlMask
-
-altSuperHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-altSuperHyperAltgrMod =
- maskMod (altMask .|. superMask .|. hyperMask .|. altgrMask)
-
-altSuperHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-altSuperHyperMod =
- maskMod (altMask .|. superMask .|. hyperMask)
-
-altSuperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-altSuperAltgrMod =
- maskMod (altMask .|. superMask .|. altgrMask)
-
-altSuperMod :: (Binding k b) => k -> BindingBuilder b ()
-altSuperMod =
- maskMod (altMask .|. superMask)
-
-altHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-altHyperAltgrMod =
- maskMod (altMask .|. hyperMask .|. altgrMask)
-
-altHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-altHyperMod =
- maskMod (altMask .|. hyperMask)
-
-altAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-altAltgrMod =
- maskMod (altMask .|. altgrMask)
-
-altMod :: (Binding k b) => k -> BindingBuilder b ()
-altMod = maskMod altMask
-
-superHyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-superHyperAltgrMod =
- maskMod (superMask .|. hyperMask .|. altgrMask)
-
-superHyperMod :: (Binding k b) => k -> BindingBuilder b ()
-superHyperMod =
- maskMod (superMask .|. hyperMask)
-
-superAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-superAltgrMod =
- maskMod (superMask .|. altgrMask)
-
-superMod :: (Binding k b) => k -> BindingBuilder b ()
-superMod = maskMod superMask
-
-hyperAltgrMod :: (Binding k b) => k -> BindingBuilder b ()
-hyperAltgrMod =
- maskMod (hyperMask .|. altgrMask)
-
-hyperMod :: (Binding k b) => k -> BindingBuilder b ()
-hyperMod = maskMod hyperMask
-
-altgrMod :: (Binding k b) => k -> BindingBuilder b ()
-altgrMod = maskMod altgrMask
-
-{- Can combine two or more of the functions above to apply the same action to
- - multiple masks. -}
-(-|-) :: (Binding k b) =>
- (k -> BindingBuilder b ()) ->
- (k -> BindingBuilder b ()) ->
- k -> BindingBuilder b ()
-(-|-) fn1 fn2 f = fn1 f >> fn2 f
-
-{- Meant for submapping, binds all alphanumeric charactes to (fn c). -}
-mapNumbersAndAlpha :: KeyMask -> (Char -> X ()) -> KeysM l ()
-mapNumbersAndAlpha km fn = do
- mapNumbers km fn
- mapAlpha km fn
-
-{- Meant for submapping. This binds all numbers to (fn x) where x is the number
- - pressed and fn is the function provided. -}
-mapNumbers :: KeyMask -> (Char -> X ()) -> KeysM l ()
-mapNumbers km fn = do
- mapM_ (\(key, ch) -> bind key $ rawMask km (fn ch))
- [ (xK_0, '0')
- , (xK_1, '1')
- , (xK_2, '2')
- , (xK_3, '3')
- , (xK_4, '4')
- , (xK_5, '5')
- , (xK_6, '6')
- , (xK_7, '7')
- , (xK_8, '8')
- , (xK_9, '9')
- -- Programmer Dvorak shifts the numbers so I have to map to their unshifted
- -- form.
- , (xK_bracketright, '6')
- , (xK_exclam, '8')
- , (xK_bracketleft, '7')
- , (xK_braceleft, '5')
- , (xK_braceright, '3')
- , (xK_parenleft, '1')
- , (xK_equal, '9')
- , (xK_asterisk, '0')
- , (xK_parenright, '2')
- , (xK_plus, '4') ]
-
-{- Meant for submapping. This binds all alpha charactes to (fn c) where c is the
- - character pressed and fn is the function provided. -}
-mapAlpha :: KeyMask -> (Char -> X ()) -> KeysM l ()
-mapAlpha km fn =
- mapM_ (\(key, ch) -> bind key $ rawMask km (fn ch)) [
- (xK_a, 'a')
- , (xK_b, 'b')
- , (xK_c, 'c')
- , (xK_d, 'd')
- , (xK_e, 'e')
- , (xK_f, 'f')
- , (xK_g, 'g')
- , (xK_h, 'h')
- , (xK_i, 'i')
- , (xK_j, 'j')
- , (xK_k, 'k')
- , (xK_l, 'l')
- , (xK_m, 'm')
- , (xK_n, 'n')
- , (xK_o, 'o')
- , (xK_p, 'p')
- , (xK_q, 'q')
- , (xK_r, 'r')
- , (xK_s, 's')
- , (xK_t, 't')
- , (xK_u, 'u')
- , (xK_v, 'v')
- , (xK_w, 'w')
- , (xK_x, 'x')
- , (xK_y, 'y')
- , (xK_z, 'z')
- ]
-
-
-documentation :: KeyBindings -> String
-documentation = execWriter . document' ""
- where
- document' pref keybindings =
- forM_ (sortOn (map (\(a, b) -> (b, a)) . snd . snd) $ Map.toList (keyBindingsToList keybindings)) $ \(doc, (thing, keys)) -> do
- when ((not $ null doc) || hasSubmap thing) $
- tell $ printf "%s%s: %s\n" pref (intercalate " or " $ map prettyShow keys) doc
- case thing of
- Action _ -> return ()
- Submap submap -> document' (pref ++ " ") submap
- Repeat submap -> do
- tell pref
- tell " (repeatable):\n"
- document' (pref ++ " ") submap
-
- keyBindingsToList :: KeyBindings -> Map String (KeyBinding, [(KeyMask, KeySym)])
- keyBindingsToList b =
- fmap (\list -> ((\(_, Documented _ t) -> t) (head list), map fst list)) $
- group (\(_, Documented doc _) -> doc) (sortOn (snd . fst) $ Map.toList b)
-
- prettyShow :: (KeyMask, KeySym) -> String
- prettyShow (mask, key) = printf "<%s%s>" (showMask mask) (keysymToString key)
-
- hasSubmap b = case b of
- Action _ -> False
- _ -> True
-
-
- showMask :: KeyMask -> String
- showMask mask =
- let masks = [(shiftMask, "S"),
- (altMask, "A"),
- (mod3Mask, "H"),
- (mod4Mask, "M"),
- (altgrMask, "AGr"),
- (controlMask, "C")] in
-
- concatMap ((++"-") . snd) $ filter ((/=0) . (.&.mask) . fst) masks
-
-
- group :: (Ord b) => (a -> b) -> [a] -> (Map b [a])
- group fn = Map.fromListWith (++) . map (first fn . (\a -> (a, [a])))
-
-
diff --git a/src/Internal/Layout.hs b/src/Internal/Layout.hs
deleted file mode 100644
index 229e958..0000000
--- a/src/Internal/Layout.hs
+++ /dev/null
@@ -1,326 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, ViewPatterns, FlexibleInstances, KindSignatures, DataKinds, GADTs, RankNTypes, PolyKinds #-}
-module Internal.Layout where
-
-import GHC.TypeLits
-
-import Data.Proxy (Proxy(..))
-import Internal.CornerLayout (Corner(..))
-import Control.Arrow (second)
-import XMonad.Hooks.ManageDocks
-import XMonad.Layout.Circle
-import XMonad.Layout.Accordion
-import Control.Applicative
-import XMonad.Layout.Spacing
-import Data.List
-import XMonad.Layout.Spiral
-import XMonad.Layout.ThreeColumns
-import XMonad.Layout.Grid
-import XMonad.Layout.Dishes
-import XMonad.Layout.MosaicAlt
-import XMonad.Layout.Fullscreen
-import qualified XMonad.Layout.Dwindle as D
-import XMonad.Layout
-import XMonad.Layout.LayoutModifier
-import XMonad
-import XMonad.Core
-import XMonad.Layout.NoBorders (smartBorders, noBorders)
-
-import Internal.LayoutList
-import Internal.Windows
-
-import qualified Data.Map as M
-import qualified XMonad.StackSet as W
-
-myLayout =
- fullscreenFull $
- avoidStruts $
- spacingRaw True (Border 5 5 5 5) True (Border 5 5 5 5) True $
- layoutZipper $
- mods (reinterpretIncMaster $ spiral (6/7)) |:
- mods (modifyMosaic (MosaicAlt M.empty :: MosaicAlt Window)) |:
- mods (reinterpretIncMaster $ Corner (3/4) (3/100)) |:
- mods (ModifyDescription TallDescriptionModifier (Tall 1 (3/100) (1/2))) |:
- mods (ModifyDescription ThreeColDescMod (ThreeCol 1 (3/100) (1/2))) |:
- mods Grid |:
- mods (Dishes 2 (1/6)) |:
- mods (reinterpretIncMaster $ D.Dwindle D.R D.CW 1.5 1.1) |:
- nil
-
--- This is a type class that defines how to reinterpret a message. One can think
--- of this as a kind of type-level function. It lets one associate a function
--- (reinterpretMessage) with a type construct, which for the case below is a
--- Symbol.
---
--- It would be nice to attach this function to the LayoutModifier directly as a
--- value, however LayoutModifiers must be Show-able and Read-able and functions
--- are not. However encoding in the typesystem itsef which function is to be
--- called is the best alternative I have.
-class DoReinterpret (k :: t) where
- reinterpretMessage ::
- Proxy k -> SomeMessage -> X (Maybe SomeMessage)
-
--- Mosaic doesn't have the concept of a "Master Space", so reinterpret messages
--- intended to modify the master space and instead have those messages expand
--- and shrink the current window.
---
--- "ForMosaic" is an instance of the Symbol kind. This is some neat type-system
--- hacking one can do in Haskell.
-instance DoReinterpret "ForMosaic" where
-
- -- IncMaster message
- reinterpretMessage _ (fromMessage -> Just (IncMasterN n)) = do
- fmap (SomeMessage .
- (if n > 0
- then expandWindowAlt
- else shrinkWindowAlt)) <$> getFocusedWindow
-
- -- ResizeMaster message
- reinterpretMessage _ (fromMessage -> Just m) = do
- fmap (SomeMessage .
- (case m of
- Expand -> expandWindowAlt
- Shrink -> shrinkWindowAlt)) <$> getFocusedWindow
-
- -- Messages that don't match the above, just leave it unmodified.
- reinterpretMessage _ m = return (Just m)
-
-instance DoReinterpret "IncMasterToResizeMaster" where
- reinterpretMessage _ (fromMessage -> Just (IncMasterN n)) =
- return $ Just $
- if n > 0
- then SomeMessage Expand
- else SomeMessage Shrink
- reinterpretMessage _ m = return (Just m)
-
--- Data construct for association a DoReinterpret function with a concrete
--- construct that can be used in the LayoutModifier instance.
---
--- It wolud be nice to have ReinterpretMessage hold the function as a value
--- rather than delegate to this kind-instance, however, it won't work because
--- LayoutModifiers have to be Read-able and Show-able, and functions are neither
--- of those, so a value-level function may not be a member of a LayoutModifier,
--- thus I have to settle for delegating to a hard-coded instance using
--- type-classes.
-data ReinterpretMessage k a = ReinterpretMessage
- deriving (Show, Read)
-
--- Instance for ReinterpretMessage as a Layout modifier.
-instance (DoReinterpret k) =>
- LayoutModifier (ReinterpretMessage k) a where
-
- handleMessOrMaybeModifyIt self message = do
-
- -- Delegates to the reinterpretMessage function associatied with the
- -- type-variable k.
- newMessage <- reinterpretMessage (ofProxy self) message
- case newMessage of
- Just m -> return $ Just $ Right m
- Nothing -> return $ Just $ Left self
- where
- -- ofProxy just provides reifies the phantom type k so the type system can
- -- figure out what instance to go to.
- ofProxy :: ReinterpretMessage k a -> Proxy k
- ofProxy _ = Proxy
-
-modifyMosaic :: l a -> ModifiedLayout (ReinterpretMessage "ForMosaic") l a
-modifyMosaic = ModifiedLayout ReinterpretMessage
-
-reinterpretIncMaster ::
- l a -> ModifiedLayout (ReinterpretMessage "IncMasterToResizeMaster") l a
-reinterpretIncMaster = ModifiedLayout ReinterpretMessage
-
-mods =
- ModifiedLayout (Zoomable False 0.05 0.05) .
- ModifiedLayout (Flippable False) .
- ModifiedLayout (HFlippable False) .
- ModifiedLayout (Rotateable False)
-
-
-data ModifyDescription m l a = ModifyDescription m (l a)
- deriving (Show, Read)
-
-data TallDescriptionModifier = TallDescriptionModifier
- deriving (Show, Read)
-
-data ThreeColDescMod = ThreeColDescMod
- deriving (Show, Read)
-
-class DescriptionModifier m l where
- newDescription :: m -> l a -> String -> String
-
-instance (Typeable m, Show m, DescriptionModifier m l, LayoutClass l a) => LayoutClass (ModifyDescription m l) a where
- runLayout (W.Workspace t (ModifyDescription m l) a) rect = do
- (rects, maybeNewLayout) <- runLayout (W.Workspace t l a) rect
- return (rects, fmap (ModifyDescription m) maybeNewLayout)
-
- doLayout (ModifyDescription m l) a s = do
- (rects, maybeNewLayout) <- doLayout l a s
- return (rects, fmap (ModifyDescription m) maybeNewLayout)
-
- pureLayout (ModifyDescription m l) a s = pureLayout l a s
-
- emptyLayout (ModifyDescription m l) a = do
- (rects, maybeNewLayout) <- emptyLayout l a
- return (rects, fmap (ModifyDescription m) maybeNewLayout)
-
- handleMessage (ModifyDescription m l) a = do
- maybeNewLayout <- handleMessage l a
- return (ModifyDescription m <$> maybeNewLayout)
-
- pureMessage (ModifyDescription m l) a =
- let maybeNewLayout = pureMessage l a in
- ModifyDescription m <$> maybeNewLayout
-
- description (ModifyDescription m l) = newDescription m l (description l)
-
-instance DescriptionModifier TallDescriptionModifier Tall where
- newDescription _ (Tall mast _ _) _ = "Tall(" ++ show mast ++ ")"
-
-instance DescriptionModifier ThreeColDescMod ThreeCol where
- newDescription _ (ThreeCol mast _ _) _ = "ThreeCol(" ++ show mast ++ ")"
- newDescription _ (ThreeColMid mast _ _) _ = "ThreeColMid(" ++ show mast ++ ")"
-
-data ResizeZoom = ShrinkZoom | ExpandZoom deriving (Typeable)
-
-instance Message ResizeZoom where
-
-newtype Flippable a = Flippable Bool -- True if flipped
- deriving (Show, Read)
-
-newtype HFlippable a = HFlippable Bool -- True if flipped
- deriving (Show, Read)
-
-newtype Rotateable a = Rotateable Bool -- True if rotated
- deriving (Show, Read)
-
-data FlipLayout = FlipLayout deriving (Typeable)
-
-data HFlipLayout = HFlipLayout deriving (Typeable)
-
-data DoRotate = DoRotate deriving (Typeable)
-
-data Zoomable a = Zoomable Bool Float Float -- True if zooming in on the focused window.
- deriving (Show, Read)
-
--- Toggles if the current window should be zoomed or not. Set the boolean
--- to set the zoom.mhar
-data ZoomModifier =
- ToggleZoom |
- Zoom |
- Unzoom
- deriving (Typeable)
-
-instance Message FlipLayout where
-
-instance Message HFlipLayout where
-
-instance Message ZoomModifier where
-
-instance Message DoRotate where
-
-instance (Eq a) => LayoutModifier Rotateable a where
- pureModifier (Rotateable rotate) (Rectangle x' y' sw sh) _ returned =
- if rotate
- then (map (second (unzero . scaleRect . mirrorRect . zero)) returned, Nothing)
- else (returned, Nothing)
- where
- zero (Rectangle x y w h) = Rectangle (x - x') (y - y') w h
- unzero (Rectangle x y w h) = Rectangle (x + x') (y + y') w h
-
- scaleRect (Rectangle x y w h) =
- Rectangle (x * fi sw `div` fi sh)
- (y * fi sh `div` fi sw)
- (w * sw `div` sh)
- (h * sh `div` sw)
-
- fi = fromIntegral
-
-
- pureMess (Rotateable rot) mess =
- fmap (\DoRotate -> Rotateable (not rot)) (fromMessage mess)
-
- modifyDescription (Rotateable rot) underlying =
- let descr = description underlying in
- if rot
- then descr ++ " Rotated"
- else descr
-
-instance (Eq a) => LayoutModifier Flippable a where
- pureModifier (Flippable flip) (Rectangle sx _ sw _) stack returned =
- if flip
- then (map (second doFlip) returned, Nothing)
- else (returned, Nothing)
- where
- doFlip (Rectangle x y w h) =
- Rectangle ((sx + fromIntegral sw) - x - fromIntegral w + sx) y w h
-
- pureMess (Flippable flip) message =
- case fromMessage message of
- Just FlipLayout -> Just (Flippable (not flip))
- Nothing -> Nothing
-
- modifyDescription (Flippable flipped) underlying =
- let descr = description underlying in
- if flipped
- then descr ++ " Flipped"
- else descr
-
-instance (Eq a) => LayoutModifier HFlippable a where
- pureModifier (HFlippable flip) (Rectangle _ sy _ sh) stack returned =
- if flip
- then (map (second doFlip) returned, Nothing)
- else (returned, Nothing)
- where
- doFlip (Rectangle x y w h) =
- Rectangle x ((sy + fromIntegral sh) - y - fromIntegral h + sy) w h
-
- pureMess (HFlippable flip) message =
- case fromMessage message of
- Just HFlipLayout -> Just (HFlippable (not flip))
- Nothing -> Nothing
-
- modifyDescription (HFlippable flipped) underlying =
- let descr = description underlying in
- if flipped
- then descr ++ " HFlipped"
- else descr
-
-
-instance (Eq a) => LayoutModifier Zoomable a where
- redoLayout (Zoomable doit ws hs) (Rectangle x y w h) stack returned =
- if doit
- then
- let focused = W.focus <$> stack
- (zoomed, rest) = partition ((==focused) . Just . fst) returned
- in case zoomed of
- [] -> return (rest, Nothing)
- ((fwin, _):_) -> return ((fwin, Rectangle (x + wp) (y + hp) (w - fromIntegral (wp * 2)) (h - fromIntegral (hp * 2))) : rest, Nothing)
-
- else return (returned, Nothing)
- where
- wp = floor $ fromIntegral w * ws
- hp = floor $ fromIntegral h * hs
-
- handleMessOrMaybeModifyIt self@(Zoomable showing sw sh) mess =
- return $
- (handleResize <$> fromMessage mess)
- <|> (Left . handleZoom <$> fromMessage mess)
- where
- handleResize r =
- if showing
- then Left $ Zoomable showing (guard $ sw + d) (guard $ sh + d)
- else Right $ case r of
- ShrinkZoom -> SomeMessage Shrink
- ExpandZoom -> SomeMessage Expand
-
- where d = (case r of
- ShrinkZoom -> -1
- ExpandZoom -> 1) * 0.02
-
- handleZoom ToggleZoom = Zoomable (not showing) sw sh
- handleZoom Zoom = Zoomable True sw sh
- handleZoom Unzoom = Zoomable False sw sh
-
- guard f | f > 1 = 1
- | f < 0 = 0
- | otherwise = f
diff --git a/src/Internal/LayoutDraw.hs b/src/Internal/LayoutDraw.hs
deleted file mode 100644
index a105c98..0000000
--- a/src/Internal/LayoutDraw.hs
+++ /dev/null
@@ -1,155 +0,0 @@
-{-# LANGUAGE FlexibleInstances, FlexibleContexts, MultiParamTypeClasses,
-ScopedTypeVariables, BangPatterns #-}
-module Internal.LayoutDraw (drawLayout) where
-
-import Control.Monad
-
-import Control.Arrow (second)
-import Control.Concurrent (threadDelay)
-import Control.Exception (handle)
-import Control.Monad.Writer (execWriter, tell)
-import Data.Foldable (find)
-import Data.Maybe (fromMaybe)
-import Internal.Hash (quickHash)
-import Internal.Layout (ZoomModifier(..))
-import System.Directory (createDirectoryIfMissing, doesFileExist)
-import System.FilePath ((</>))
-import Text.Printf (printf)
-import XMonad.Layout.Spacing (SpacingModifier(..), Border(..))
-
-import XMonad (X,
- Rectangle(..),
- Dimension,
- LayoutClass,
- Message,
- Window,
- SomeMessage(..))
-
-import qualified XMonad as X
-import qualified XMonad.StackSet as S
-
--- Draws and returns an XPM for the current layout.
---
--- Returns
--- - Bool - true if the xpm has already been written, and is thus cached.
--- - String - description of the current layout
--- - String - the text to send to XMobar
---
--- This function actually runs the current layout's doLayout function to
--- generate the XPM, so it's completely portable to all layouts.
---
--- Note this function is impure and running the layout to create the XPM is also
--- impure. While in-practice most layouts are pure, it should be kept in mind.
-drawLayout :: X (Bool, String, String)
-drawLayout = do
- winset <- X.gets X.windowset
- let layout = S.layout $ S.workspace $ S.current winset
-
- -- Gotta reset the layout to a consistent state.
- layout' <- foldM (flip ($)) layout [
- handleMessage' $ ModifyWindowBorder $ const $ Border 0 0 0 0,
- handleMessage' Unzoom
- ]
-
- (cached, xpm) <- drawXpmIO layout'
-
- return (cached , X.description layout, printf "<icon=%s/>" xpm)
-
--- Returns true if a point is inside a rectangle (inclusive).
-pointInRect :: (Dimension, Dimension) -> Rectangle -> Bool
-pointInRect (x, y) (Rectangle x' y' w h) =
- x <= (fi x' + fi w) && x >= fi x' && y <= (fi y' + fi h) && y >= fi y'
- where
- fi :: (Integral a, Num b) => a -> b
- fi = fromIntegral
-
--- Scale factory. Scaling the rectangles before writing the XPM helps to reduce
--- noise from things like AvoidStruts, as there is unfortunately no way to force
--- avoid struts to be off, one can only toggle it.
-sf :: (Integral a) => a
-sf = 1024
-
-handleMessage' ::
- (LayoutClass layout a, Message m) => m -> layout a -> X (layout a)
-handleMessage' message layout = do
- fromMaybe layout <$> X.handleMessage layout (SomeMessage message)
-
--- Creates the XPM for the given layout and returns the path to it.
---
--- This function does run doLayout on the given layout, and that should be
--- accounted for.
-drawXpmIO :: (LayoutClass layout Window) => layout Window -> X (Bool, String)
-drawXpmIO l = do
- dir <- X.getXMonadDir
-
- let shrinkAmt = 5 -- amount to shrink the windows by to make pretty gaps.
-
- let (w, h) = (56, 24)
- let descr = X.description l
- let iconCacheDir = dir </> "icons" </> "cache"
- let iconPath = iconCacheDir </> (quickHash descr ++ ".xpm")
-
- let colors = [
- "#cc9a9a", "#cc9999", "#cc8080", "#cc6666",
- "#cc4c4c", "#cc3232", "#cc1818", "#cc0000" ]
-
- (rects', _) <-
- X.runLayout
- (S.Workspace "0" l (S.differentiate [1 .. 5]))
- (Rectangle 0 0 ((w + shrinkAmt) * sf) ((h + shrinkAmt) * sf))
-
- let rects = flip map rects' $ \(_, Rectangle x y w h) ->
- Rectangle (x `div` sf) (y `div` sf) (w `div` sf) (h `div` sf)
-
- X.liftIO $ do
- exists <- doesFileExist iconPath
- createDirectoryIfMissing True iconCacheDir
-
- unless exists $ do
- let xpmText = drawXpm (w, h) (zip (cycle colors) rects) 4
- writeFile iconPath xpmText
-
- return (exists, iconPath)
-
---
--- Create's an XPM, purely. Returns a string with the XPM contents.
--- Takes as arguments
---
--- - dimensions of the icon.
--- - list of (color, rectangle) pairs.
--- - The amount to shrink the windows by for those pretty gaps.
---
-drawXpm ::
- (Dimension, Dimension) -> [(String, Rectangle)] -> Dimension -> String
-drawXpm (w, h) rects' shrinkAmt = execWriter $ do
- tell "/* XPM */\n"
- tell "static char *out[] = {\n"
- tell $ printf "\"%d %d %d 1 \",\n" w h (length rects + 1)
-
- let zipRects = zip ['A' .. 'Z'] rects
-
- forM_ zipRects $ \(char, (color, _)) -> do
- tell $ printf "\"%c c %s\",\n" char color
- tell "\"% c None\"a,\n"
-
- forM_ [0 .. h - 1] $ \y -> do
- tell "\""
- forM_ [0 .. w - 1] $ \x ->
- (case find (matches x y) zipRects of
- Nothing -> tell "%"
- Just (chr, _) -> tell [chr])
- tell "\""
- when (y /= h - 1 - shrinkAmt) (tell ",")
- tell "\n"
- tell "};\n"
-
- where
- matches x y (_, (_, r)) = pointInRect (x, y) r
- rects = map (second (shrink shrinkAmt)) rects'
- guard a b = if a <= shrinkAmt then 1 else b
- shrink amt (Rectangle x y w h) =
- Rectangle
- x
- y
- (guard w $ w - fromIntegral amt)
- (guard h $ h - fromIntegral amt)
diff --git a/src/Internal/LayoutList.hs b/src/Internal/LayoutList.hs
deleted file mode 100644
index 2405f71..0000000
--- a/src/Internal/LayoutList.hs
+++ /dev/null
@@ -1,297 +0,0 @@
-{-# LANGUAGE GADTs, RankNTypes, FlexibleInstances, MultiParamTypeClasses,
- FlexibleContexts, UndecidableInstances, ViewPatterns, StandaloneDeriving,
- RankNTypes, TupleSections, TypeFamilies #-}
-
-{-
- - This module provides a more powerful version of the "Choose" layout that can
- - be bidirectionally navigated.
- -
- - The indexing uses a type-safe zipper to keep track of the currently-selected
- - layout.
- -}
-module Internal.LayoutList (
- LayoutList,
- layoutZipper,
- LCons,
- LNil,
- toNextLayout,
- toPreviousLayout,
- toFirstLayout,
- (|:),
- nil
- )where
-
-import Control.Applicative ((<|>))
-import Data.Void
-import Control.Monad.Identity (runIdentity)
-import Data.Maybe (fromMaybe, fromJust)
-import Control.Arrow (second)
-import XMonad
-import qualified XMonad.StackSet as W
-import Data.Proxy
-
--- Type-level lists. LNil is the final of the list. LCons contains a layout and a
--- tail.
-data LNil a = LNil deriving (Read, Show)
-data LCons l t a = LCons (l a) (t a) deriving (Read, Show)
-
--- Sel - This defines a structure where either this selected, or some
--- other element is selected.
---
--- These types can be composed to create what is effectively a bounded integer.
--- I.e. there can be a type like
---
--- Sel (Sel (Sel (Sel End)))
---
--- Such a type is equivalent to an integer bounded at 4, because this type can
--- exist in no more than 4 states:
---
--- Sel
--- Skip Sel
--- Skip (Skip Sel)
--- Skip (Skip (Skip Sel))
---
--- Note that a type (Sel End) can only be in the Sel as End may not be
--- construted (without using undefined).
-data Sel l =
- Sel |
- (Selector l) => Skip l
-deriving instance (Read l, Selector l) => Read (Sel l)
-deriving instance (Show l, Selector l) => Show (Sel l)
-deriving instance (Eq l, Selector l) => Eq (Sel l)
-
--- Reimplement Void as End, just to keep the two separate, but End is for all
--- intents and purposes Void.
-data End
-deriving instance Read End
-deriving instance Show End
-deriving instance Eq End
-
-
--- Types that constitute a selection. Selections can be moved to the next
--- selection, moved to the previous selection, optionally there could be a
--- previous selection and they may be currently selected.
-class (Eq c) => Selector c where
- -- Increments the selection to the next state
- --
- -- Returns Nothing if the selection class is in the final state and cannot be
- -- incremented any farther. (This is helpful to facilitate modular
- -- arithmatic)
- increment :: c -> Maybe c
-
- -- Decrements the selection to the previous state. Returns Nothing if the
- -- state is already in its initial setting.
- decrement :: c -> Maybe c
-
- -- The initial state.
- initial :: Maybe c
-
- -- The final state.
- final :: Maybe c
-
---
--- Is selelected can be in two states:
---
--- 1. The current element is selected
--- 2. The current element is not selected and another element deeper in the
--- structure is selected.
-instance (Selector t) => Selector (Sel t) where
- -- If the current element is not selected, increment the tail.
- increment (Skip l) = Skip <$> increment l
- -- If the current element is selected, the increment is just the initial of
- -- the tail.
- increment Sel = Skip <$> initial
-
- -- For a selection, the initial is just this in the Sel state.
- initial = Just Sel
-
- -- Looks ahead at the tail, sees if it is selected, if so, select this one
- -- instead, if the one ahead isn't selected, then decrement that one.
- decrement (Skip t) = Just $ maybe Sel Skip (decrement t)
- decrement Sel = Nothing
-
- -- Navigates to the end of the structure to find the final form.
- final = Just $ maybe Sel Skip final
-
--- The End structure (which is equivalent to Void) is the "null" selector; the
--- basecase that the Sel selector terminates at.
-instance Selector End where
-
- -- Incrementing the End Selector doesn't do anything.
- increment = const Nothing
-
- -- Decrementing the End Selector doesn't do anythig
- decrement = const Nothing
-
- -- There is no initial value for the End selector.
- initial = Nothing
-
- -- There is not final state for the End selector.
- final = Nothing
-
--- Increment a selector, but cyclicly
-incrementCycle :: (Selector c) => c -> c
-incrementCycle c =
- case increment c of
- Nothing -> fromMaybe c initial
- Just x -> x
-
--- Add two selectors together, incrementing the first until the second cannot be
--- incremented anymore.
-addSelector :: (Selector c) => c -> c -> c
-addSelector c1 c2 = addSel c1 (decrement c2)
- where
- addSel c1 Nothing = c1
- addSel c1 (Just c2) = addSel (incrementCycle c1) (decrement c2)
-
--- Turn an int into a selector by repeatably incrementing.
-intToSelector :: (Selector c) => Int -> c
-intToSelector 0 = fromJust initial
-intToSelector n = incrementCycle $ intToSelector (n - 1)
-
--- A LayoutList consists of a LayoutSelect type and a corresponding Selector.
-data LayoutList l a where
- LayoutList ::
- (LayoutSelect l a, Selector (SelectorFor l)) =>
- SelectorFor l -> l a -> LayoutList l a
-
-deriving instance (LayoutSelect l a) => Show (LayoutList l a)
-deriving instance (LayoutSelect l a) => Read (LayoutList l a)
-
-(|:) :: (LayoutSelect t a, LayoutClass l a) => l a -> t a -> LCons l t a
-(|:) = LCons
-
-infixr 5 |:
-
--- Constructs a LayoutList. This function enforces that the SelectorFor l
--- is a 'Sel' type. Essentially this enforces that there must be at least one
--- underlying layout, otherwise a LayoutList cannot be constructed.
-layoutZipper :: (LayoutSelect l a, SelectorFor l ~ Sel n) =>
- l a -> LayoutList l a
-layoutZipper = LayoutList Sel
-
--- The termination of a layout zipper.
-nil :: LNil a
-nil = LNil
-
--- Message to navigate to a layout.
-newtype NavigateLayout =
- -- Sets the layout based on the given function.
- NavigateLayout {
- changeLayoutFn :: forall c. (Selector c) => c -> c
- }
- deriving (Typeable)
-
--- NavigateLayout instance to move to the next layout, circularly.
-toNextLayout :: NavigateLayout
-toNextLayout = NavigateLayout $ addSelector (intToSelector 1)
-
--- NavigateLayout instance to move to the previous layout, circularly.
-toPreviousLayout :: NavigateLayout
-toPreviousLayout = NavigateLayout $ \c -> fromMaybe c (decrement c <|> final)
-
--- NavigateLayotu instance to move to the first layout.
-toFirstLayout :: NavigateLayout
-toFirstLayout = NavigateLayout (`fromMaybe` initial)
-
-instance Message NavigateLayout where
-
--- LayoutSelect class Describes a type that can be used to select a layout using
--- the associated type SelectorFor.
---
--- Instances of this class are LCons and LNil.
-class (Show (l a),
- Read (l a),
- Read (SelectorFor l),
- Show (SelectorFor l),
- Selector (SelectorFor l)) => LayoutSelect l a where
-
- -- The selector that is used to update the layout corresponding to the
- -- selector. This selector must be an instance of the Selector class.
- type SelectorFor l :: *
-
- -- Update applies a functor to the selected layout and maybe returns a result
- -- and an updated layout.
- update :: forall r m. (Monad m) =>
- -- The selector for this type. Determines which layout the function is
- -- applied to.
- SelectorFor l ->
- -- The LayoutSelect being modified.
- l a ->
- -- Higher-ordered function to generically apply to the Layout associated
- -- with the Selector. Works on all LayoutClass's.
- (forall l'. (LayoutClass l' a) => l' a -> m (r, Maybe (l' a))) ->
-
- -- Returns a result r, and an updated LayoutSelect.
- m (Maybe (r, l a))
-
--- Instance for LayoutSelect for cons
-instance (Read (l a),
- LayoutClass l a,
- LayoutSelect t a,
- Show (SelectorFor t),
- Read (SelectorFor t)) =>
- LayoutSelect (LCons l t) a where
-
- -- The SelectorFor Cons is Sel (SelectorFor t). This creates the structure
- -- Sel (Sel (Sel ( ... (Sel End) .. ))) where the number of Sel's match the
- -- number of Cons in this structure enforcing safe selection.
- type SelectorFor (LCons l t) = Sel (SelectorFor t)
-
- -- The current layout in this Cons-list is selected.
- update Sel (LCons layout t) fn = do
- (r, layout') <- fn layout
- return $ Just (r, LCons (fromMaybe layout layout') t)
-
- -- The current layout is not selected. Move on to another layout.
- update (Skip s) (LCons l t) fn =
- fmap (second $ \t' -> LCons l t') <$> update s t fn
-
--- LNil is a layout select. It doesn't do anything. Indeed update really can't
--- be called on on this because that would require instantiating a End type.
-instance LayoutSelect LNil a where
- type SelectorFor LNil = End -- LNil cannot be selected.
- update _ _ _ = return Nothing
-
--- Instance of layout class for LayoutList. The implementation for this
--- just delegates to the underlying LayoutSelect class using the generic
--- update method.
-instance (Show (l a), Typeable l, LayoutSelect l a) =>
- LayoutClass (LayoutList l) a where
-
- runLayout (W.Workspace i (LayoutList idx l) ms) r = do
- r <- update idx l $ \layout ->
- runLayout (W.Workspace i layout ms) r
- case r of
- Nothing -> return ([], Nothing)
- Just (r, la) -> return (r, Just (LayoutList idx la))
-
- pureLayout (LayoutList idx l) r s = runIdentity $ do
- r <- update idx l $ \layout -> return (pureLayout layout r s, Nothing)
- case r of
- Nothing -> return []
- Just (r, a) -> return r
-
- emptyLayout (LayoutList idx l) r = do
- r <- update idx l $ \layout -> emptyLayout layout r
- case r of
- Nothing -> return ([], Nothing)
- Just (r, la) -> return (r, Just (LayoutList idx la))
-
- handleMessage (LayoutList idx l) (fromMessage -> Just (NavigateLayout fn)) =
- return $ Just (LayoutList (fn idx) l)
-
- handleMessage (LayoutList idx l) m = do
- r <- update idx l $ \layout -> ((),) <$> handleMessage layout m
- return $ LayoutList idx . snd <$> r
-
- pureMessage (LayoutList idx l) m = runIdentity $ do
- r <- update idx l $ \layout -> return ((), pureMessage layout m)
- return $ LayoutList idx . snd <$> r
-
- description (LayoutList idx l) = runIdentity $ do
- r <- update idx l $ \l -> return (description l, Nothing)
- return $
- case r of
- Nothing -> "No Layout"
- Just (descr, _) -> descr
diff --git a/src/Internal/Lib.hs b/src/Internal/Lib.hs
deleted file mode 100644
index fdbc9a5..0000000
--- a/src/Internal/Lib.hs
+++ /dev/null
@@ -1,160 +0,0 @@
-{-# LANGUAGE RankNTypes #-}
-module Internal.Lib where
-
-import Prelude hiding ((!!))
-
-import XMonad.Actions.DynamicWorkspaces
-import XMonad.Util.Run
-import XMonad.Prompt
-import XMonad.Prompt.Input
-import XMonad.Prompt.Shell
-
-import Internal.PromptConfig
-
-import Data.Char
-import Data.List hiding ((!!))
-import Data.List.Safe ((!!))
-import Data.Maybe
-import Internal.Marking
-import Text.Printf
-import XMonad hiding (workspaces, Screen)
-import XMonad.StackSet hiding (filter, focus)
-import qualified Data.Map as Map
-import Internal.DMenu
-import Data.Ord (comparing)
-
-import qualified XMonad.StackSet as S
-import Internal.Windows
-
-type WorkspaceName = Char
-newtype Selector = Selector (forall a. (Eq a) => a -> [a] -> a)
-
-data WinPrompt = WinPrompt
-
-instance XPrompt WinPrompt where
- showXPrompt _ = "[Window] "
- commandToComplete _ = id
-
-data WorkspaceState = Current | Hidden | Visible
- deriving (Ord, Eq, Enum)
-
--- Returns all the workspaces that are either visible, current or Hidden but
--- have windows and that workspace's state.
---
--- In other words, filters out workspaces that have no windows and are not
--- visible.
---
--- This function will sort the result by the workspace tag.
-getPopulatedWorkspaces ::
- (Ord i) => S.StackSet i l a sid sd -> [(WorkspaceState, S.Workspace i l a)]
-getPopulatedWorkspaces (S.StackSet (S.Screen cur _ _) vis hi _) =
- sortOn (tag . snd) $
- mapMaybe (\w@(S.Workspace _ _ s) -> fmap (const (Hidden, w)) s) hi ++
- map (\(S.Screen w _ _) -> (Visible, w)) vis ++
- [(Current, cur)]
-
-getHorizontallyOrderedScreens ::
- StackSet wid l a ScreenId ScreenDetail ->
- [Screen wid l a ScreenId ScreenDetail]
--- ^ Returns a list of screens ordered from leftmost to rightmost.
-getHorizontallyOrderedScreens windowSet =
- flip sortBy screens $ \sc1 sc2 ->
- let (SD (Rectangle x1 _ _ _)) = screenDetail sc1
- (SD (Rectangle x2 _ _ _)) = screenDetail sc2
- in x1 `compare` x2
- where
- screens = current windowSet : visible windowSet
-
-getCurrentWorkspace :: X WorkspaceName
-getCurrentWorkspace = withWindowSet $
- \(StackSet (Screen (Workspace t _ _) _ _) _ _ _) -> do
- return (head t)
-
-gotoAccompaningWorkspace :: X ()
-gotoAccompaningWorkspace = do
- cur <- getCurrentWorkspace
- if isUpper cur
- then gotoWorkspace (toLower cur)
- else gotoWorkspace (toUpper cur)
-
-gotoWorkspace :: WorkspaceName -> X ()
-gotoWorkspace ch = pushHistory $ do
- addHiddenWorkspace [ch]
- windows $ greedyView $ return ch
-
-shiftToWorkspace :: WorkspaceName -> X ()
-shiftToWorkspace ch = do
- addHiddenWorkspace [ch]
- (windows . shift . return) ch
-
-swapWorkspace :: WorkspaceName -> X ()
-swapWorkspace toWorkspaceName = do
- addHiddenWorkspace [toWorkspaceName]
- windows $ \ss -> do
- let fromWorkspace = tag $ workspace $ current ss
- toWorkspace = [toWorkspaceName] in
- StackSet (swapSc fromWorkspace toWorkspace $ current ss)
- (map (swapSc fromWorkspace toWorkspace) $ visible ss)
- (map (swapWs fromWorkspace toWorkspace) $ hidden ss)
- (floating ss)
- where
- swapSc fromWorkspace toWorkspace (Screen ws a b) =
- Screen (swapWs fromWorkspace toWorkspace ws) a b
-
- swapWs fromWorkspace toWorkspace ws@(Workspace t' l s)
- | t' == fromWorkspace = Workspace toWorkspace l s
- | t' == toWorkspace = Workspace fromWorkspace l s
- | otherwise = ws
-
-fuzzyCompletion :: String -> String -> Bool
-fuzzyCompletion str0 str1 =
- all (`isInfixOf`l0) ws
- where
- ws = filter (not . all isSpace) $ words (map toLower str0)
- l0 = map toLower str1
-
-getString :: Window -> X String
-getString = runQuery $ do
- t <- title
- a <- appName
- return $
- if map toLower a `isInfixOf` map toLower t
- then t
- else printf "%s - %s" t a
-
-withRelativeWorkspace :: Selector -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
-withRelativeWorkspace (Selector selector) fn =
- windows $ \ss ->
- let tags = sort (tag . snd <$> filter (\x -> fst x /= Visible ) (getPopulatedWorkspaces ss))
- from = tag $ workspace $ current ss
- to = selector from tags
- in fn to ss
-
-next :: Selector
-next = Selector $ \a l -> select a l l
- where select n (x:y:xs) _ | n == x = y
- select n [x] (y:_) | n == x = y
- select n (x:xs) orig = select n xs orig
- select n _ _ = n
-
-prev :: Selector
-prev = Selector $ \a l ->
- let (Selector fn) = next in fn a (reverse l)
-
-withScreen :: (WorkspaceId -> WindowSet -> WindowSet) -> Int -> X ()
-withScreen fn n = do
- windows $ \windowSet ->
- case getHorizontallyOrderedScreens windowSet !! n of
- Nothing -> windowSet
- Just screen -> fn (tag $ workspace screen) windowSet
-
-windowJump :: X ()
-windowJump = pushHistory $ do
- windowTitlesToWinId <- withWindowSet $ \ss ->
- Map.fromList <$> mapM (\wid -> (,) <$> getString wid <*> return wid) (allWindows ss)
-
- windowId <- runDMenuPromptWithMap "Window" (Just "#f542f5") windowTitlesToWinId
-
- case windowId of
- Nothing -> return ()
- Just wid -> focus wid
diff --git a/src/Internal/Logger.hs b/src/Internal/Logger.hs
deleted file mode 100644
index e5824a4..0000000
--- a/src/Internal/Logger.hs
+++ /dev/null
@@ -1,32 +0,0 @@
-module Internal.Logger where
-
-import XMonad
-import qualified XMonad.Util.ExtensibleState as XS
-import System.IO
-
-import Internal.NoPersist
-
-newtype LoggerState =
- LoggerState {
- logHandle :: Maybe (NoPersist Handle)
- }
-
-instance ExtensionClass LoggerState where
- initialValue = LoggerState Nothing
-
-logs :: String -> X ()
-logs s = do
- LoggerState handle' <- XS.get
-
- handle <-
- case handle' of
- Nothing -> do
- handle <- io $ openFile "/tmp/xmonad.log" AppendMode
- XS.put $ LoggerState $ Just $ NoPersist handle
- return handle
-
- Just (NoPersist h) -> return h
-
- io $ do
- hPutStrLn handle s
- hFlush handle
diff --git a/src/Internal/Marking.hs b/src/Internal/Marking.hs
deleted file mode 100644
index 3ffb411..0000000
--- a/src/Internal/Marking.hs
+++ /dev/null
@@ -1,204 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
-module Internal.Marking (
- historyNext, historyPrev,
- markCurrentWindow, pushHistory,
- jumpToMark, jumpToLast, swapWithLastMark,
- swapWithMark
- ) where
-
-import Internal.Windows (mapWindows, findWindow, getLocationWorkspace)
-import XMonad
-import XMonad.StackSet hiding (focus)
-import Data.IORef
-import Data.Map (Map)
-import Control.Monad (when)
-
-import System.FilePath
-import System.IO
-import Control.Exception
-import System.Environment
-import qualified Data.Sequence as Seq
-import Data.Sequence (Seq(..))
-
-import qualified XMonad.Util.ExtensibleState as XS
-
-import qualified Data.Map as Map
-
-{- Submodule that handles marking windows so they can be jumped back to. -}
-
-type Mark = Char
-
-historySize = 100 -- max number of history elements the tail.
-
-data History a = History [a] (Seq a)
- deriving (Read, Show)
-
-instance Default (History a) where
-
- def = History [] Seq.empty
-
-seqPush :: a -> Seq a -> Seq a
-seqPush elem s@(seq :|> _) | Seq.length s >= historySize = elem :<| seq
-seqPush elem s = elem :<| s
-
-historyForward :: History a -> History a
-historyForward (History (a:as) tail) = History as (seqPush a tail)
-historyForward z = z
-
-historyBackward :: History a -> History a
-historyBackward (History head (a :<| as)) = History (a : head) as
-historyBackward z = z
-
-historyCurrent :: History a -> Maybe a
-historyCurrent (History (a:_) _) = Just a
-historyCurrent _ = Nothing
-
-historyPush :: (Eq a) => a -> History a -> History a
-historyPush a h@(History (w : _) _) | a == w = h
-historyPush a (History (w : _) tail) = History [a] (seqPush w tail)
-historyPush a (History _ tail) = History [a] tail
-
-historySwap :: History a -> History a
-historySwap (History (a:as) (t :<| ts)) = History (t : as) (seqPush a ts)
-historySwap z = z
-
-historyLast :: History a -> Maybe a
-historyLast (History _ (t :<| _)) = Just t
-historyLast _ = Nothing
-
-data Spot =
- WindowSpot Window | -- Focus is on a window.
- TagSpot String -- Focus is on an (empty) tag
- deriving (Read, Show, Eq, Ord)
-
-greedyFocus :: Spot -> X ()
-greedyFocus (WindowSpot win) = do
- ws <- withWindowSet $ \ss ->
- return $ getLocationWorkspace =<< findWindow ss win
-
- mapM_ (windows . greedyView . tag) ws
- focus win
-greedyFocus (TagSpot tag) =
- windows $ greedyView tag
-
-data MarkState =
- MarkState {
- markStateMap :: Map Mark Window
- , windowHistory :: History Spot
- } deriving (Read, Show)
-
-
-instance ExtensionClass MarkState where
- initialValue = MarkState Map.empty def
- extensionType = PersistentExtension
-
-changeHistory :: (History Spot -> History Spot) -> (MarkState -> MarkState)
-changeHistory fn ms = ms { windowHistory = fn (windowHistory ms)}
-
-withMaybeFocused :: (Maybe Window -> X ()) -> X ()
-withMaybeFocused f = withWindowSet $ f . peek
-
-normalizeWindows :: X ()
-normalizeWindows = do
- MarkState { windowHistory = h } <- XS.get
- mapM_ greedyFocus (historyCurrent h)
-
--- greedyFocus :: Window -> X ()
--- greedyFocus win = do
--- ws <- withWindowSet $ \ss ->
--- return $ getLocationWorkspace =<< findWindow ss win
---
--- mapM_ (windows . greedyView . tag) ws
--- focus win
-
-markCurrentWindow :: Mark -> X ()
-markCurrentWindow mark = do
- withFocused $ \win ->
- XS.modify $ \state@MarkState {markStateMap = ms} ->
- state {
- markStateMap = Map.insert mark win ms
- }
-
-pushHistory :: X () -> X ()
-pushHistory fn = do
- withMaybeFocused $ \maybeWindowBefore -> do
- case maybeWindowBefore of
- (Just windowBefore) ->
- XS.modify $ changeHistory (historyPush (WindowSpot windowBefore))
- Nothing ->
- withWindowSet $ \ws ->
- XS.modify $ changeHistory (historyPush (TagSpot (currentTag ws)))
-
- fn
-
- withMaybeFocused $ \maybeWindowAfter ->
- case maybeWindowAfter of
- Just windowAfter ->
- XS.modify $ changeHistory (historyPush $ WindowSpot windowAfter)
- Nothing ->
- withWindowSet $ \ws ->
- XS.modify $ changeHistory (historyPush $ TagSpot $ currentTag ws)
-
-withHistory :: (History Spot -> X ()) -> X ()
-withHistory fn = do
- MarkState { windowHistory = w } <- XS.get
- fn w
-
-jumpToLast :: X ()
-jumpToLast = do
- XS.modify (changeHistory historySwap)
- normalizeWindows
-
-jumpToMark :: Mark -> X ()
-jumpToMark mark = do
- MarkState {markStateMap = m} <- XS.get
- case Map.lookup mark m of
- Nothing -> return ()
- Just w -> pushHistory $
- greedyFocus (WindowSpot w)
-
-setFocusedWindow :: a -> StackSet i l a s sd -> StackSet i l a s sd
-setFocusedWindow
- window
- (StackSet (Screen (Workspace t l stack) a b) vis hid float) =
- let newStack =
- case stack of
- Nothing -> Nothing
- Just (Stack _ up down) -> Just (Stack window up down) in
- StackSet (Screen (Workspace t l newStack) a b) vis hid float
-
-swapWithFocused :: (Ord a) => a -> StackSet i l a s sd -> StackSet i l a s sd
-swapWithFocused winToSwap stackSet =
- case peek stackSet of
- Nothing -> stackSet
- Just focused -> do
- setFocusedWindow winToSwap $
- mapWindows (
- \w -> if w == winToSwap then focused else w) stackSet
-
-swapWithLastMark :: X ()
-swapWithLastMark = pushHistory $ withHistory $ \hist -> do
-
- case historyLast hist of
- Just (WindowSpot win) ->
- windows $ swapWithFocused win
- Nothing -> return ()
-
-swapWithMark :: Mark -> X ()
-swapWithMark mark = pushHistory $ do
- MarkState {markStateMap = m} <- XS.get
-
- case Map.lookup mark m of
- Nothing -> return ()
- Just winToSwap -> do
- windows $ swapWithFocused winToSwap
-
-historyPrev :: X ()
-historyPrev = do
- XS.modify $ changeHistory historyBackward
- normalizeWindows
-
-historyNext :: X ()
-historyNext = do
- XS.modify $ changeHistory historyForward
- normalizeWindows
diff --git a/src/Internal/MouseMotion.hs b/src/Internal/MouseMotion.hs
deleted file mode 100644
index c72c824..0000000
--- a/src/Internal/MouseMotion.hs
+++ /dev/null
@@ -1,97 +0,0 @@
-{-# LANGUAGE ViewPatterns, BangPatterns #-}
-module Internal.MouseMotion where
-
-import XMonad
-
-import Control.Monad (void, forever)
-import Text.Printf
-import Internal.Submap
-import Control.Monad.Loops (iterateWhile)
-import Control.Monad.Fix (fix)
-import Internal.Logger
-
-import Linear.V2
-import Linear.Metric
-
-data Quadrant = NE | SE | SW | NW deriving (Enum, Show)
-data Direction = CW | CCW deriving (Enum, Show)
-
-getQuadrant :: (Num a, Ord a) => (a, a) -> Quadrant
-getQuadrant (x, y) | x >= 0 && y >= 0 = NE
-getQuadrant (x, y) | x < 0 && y >= 0 = SE
-getQuadrant (x, y) | x < 0 && y < 0 = SW
-getQuadrant (x, y) = NW
-
-
-getDirection :: Quadrant -> Quadrant -> Maybe Direction
-getDirectory a b | a == b = Nothing
-getDirection SW SE = Just CCW
-getDirection SE NE = Just CCW
-getDirection NE NW = Just CCW
-getDirection NW SW = Just CCW
-getDirection _ _ = Just CW
-
-
-liftMouseMotionM :: X a -> MouseMotionM a
-liftMouseMotionM = MouseMotionM . fmap Just
-
-motion :: MouseMotionM (V2 Int)
-motion = MouseMotionM $ do
- ev <- nextMotionOrButton
- case ev of
- Right button -> do
- logs ("Button " ++ show button)
- return Nothing
-
- Left motion -> return (Just $ uncurry V2 motion)
-
-motionSize :: Int -> MouseMotionM (V2 Int)
-motionSize size = do
- let fsize = fromIntegral size
-
- !firstmotion <- fmap fromIntegral <$> motion
-
- let get = do
- !next <- motion
- if distance (fmap fromIntegral next) firstmotion >= fsize
- then return next
- else get
-
- get
-
-runMouseMotionM :: MouseMotionM a -> X (Maybe a)
-runMouseMotionM (MouseMotionM a) = a
-
-execMouseMotionM :: MouseMotionM () -> X ()
-execMouseMotionM = void . runMouseMotionM
-
--- Monad for capturing mouse motion. Terminates and holds Nothing when a
--- button is pressed.
-newtype MouseMotionM a = MouseMotionM (X (Maybe a))
-
-instance Functor MouseMotionM where
- fmap fn (MouseMotionM xma) = MouseMotionM (fmap (fmap fn) xma)
-
-instance Applicative MouseMotionM where
- mf <*> ma = do
- !f <- mf
- !a <- ma
- return (f a)
-
- pure = return
-
-instance Monad MouseMotionM where
- return a = MouseMotionM (return (Just a))
- (MouseMotionM !xa) >>= fn = MouseMotionM $ do
- !ma <- xa
- case ma of
- Just !a ->
- let (MouseMotionM !xb) = fn a in xb
- Nothing -> return Nothing
-
-mouseRotateMotion :: X () -> X () -> X ()
-mouseRotateMotion clockWise counterClockwise = execMouseMotionM doMouse
- where
- doMouse = forever $ do
- v <- motion
- liftMouseMotionM $ logs $ "Motion: " ++ show v
diff --git a/src/Internal/NoPersist.hs b/src/Internal/NoPersist.hs
deleted file mode 100644
index a67e649..0000000
--- a/src/Internal/NoPersist.hs
+++ /dev/null
@@ -1,23 +0,0 @@
--- Module for not persisting XMonad state. To be used with ExtensibleState
--- for data types that cannot be persisted.
-module Internal.NoPersist where
-
-import Data.Default (Default, def)
-import Data.Typeable
-
-import XMonad (ExtensionClass(..))
-
-newtype NoPersist a = NoPersist a
- deriving (Typeable)
-
-instance Show (NoPersist a) where
- show (NoPersist _) = show ()
-
-instance (Default a) => Read (NoPersist a) where
- readsPrec i s = map (\(_, s) -> (NoPersist def, s)) (readsPrec i s :: [((), String)])
-
-instance (Default a) => Default (NoPersist a) where
- def = NoPersist def
-
-instance (Default a, Typeable a) => ExtensionClass (NoPersist a) where
- initialValue = NoPersist def
diff --git a/src/Internal/PassMenu.hs b/src/Internal/PassMenu.hs
deleted file mode 100644
index 5b031c0..0000000
--- a/src/Internal/PassMenu.hs
+++ /dev/null
@@ -1,13 +0,0 @@
-module Internal.PassMenu where
-
-import XMonad
-import XMonad.Util.Run
-import Control.Monad
-
-runPassMenu :: X ()
-runPassMenu = void $
- safeSpawn "rofi-pass" [
- "-p", "Password ",
- "-theme-str",
- "* {theme-color: #f54245;}"]
-
diff --git a/src/Internal/PromptConfig.hs b/src/Internal/PromptConfig.hs
deleted file mode 100644
index 0db3027..0000000
--- a/src/Internal/PromptConfig.hs
+++ /dev/null
@@ -1,12 +0,0 @@
-module Internal.PromptConfig where
-
-import XMonad.Prompt
-
-xpConfig :: XPConfig
-xpConfig = def {
- font = "xft:Source Code Pro:size=10"
- , bgColor = "#404040"
- , fgColor = "#8888ff"
- , promptBorderWidth = 0
- , height = 40
- }
diff --git a/src/Internal/RebindKeys.hs b/src/Internal/RebindKeys.hs
deleted file mode 100644
index 38af754..0000000
--- a/src/Internal/RebindKeys.hs
+++ /dev/null
@@ -1,119 +0,0 @@
-
--- Module for intercepting key presses not explicity mapped in the key bindings.
--- This uses some deep magic with grabKey and windows and everything else, but
--- it makes window-specific key bindings awesome!
-module Internal.RebindKeys where
-
-import XMonad
-
-import Text.Printf
-import Control.Monad.Trans.Class (lift)
-import Control.Monad (forM, forM_)
-import Data.Default (Default, def)
-import Data.Map (Map)
-import qualified Data.Map as Map
-import qualified XMonad.Util.ExtensibleState as XS
-import Data.Monoid (All(..))
-
-import Internal.Logger
-import Internal.NoPersist
-
-type WindowHook = Query ()
-
-newtype InterceptState =
- InterceptState (NoPersist (Map (KeyMask, KeySym) (X ())))
-
-newtype RemapState =
- RemapState (NoPersist (Map (Window, (KeyMask, KeySym)) (X ())))
-
-instance ExtensionClass InterceptState where
- initialValue = InterceptState def
-
-instance ExtensionClass RemapState where
- initialValue = RemapState def
-
-remapHook :: Event -> X All
-remapHook event = do
- RemapState (NoPersist map) <- XS.get
-
- case event of
- KeyEvent { ev_window = win, ev_event_type = typ, ev_keycode = code, ev_state = m }
- | typ == keyPress-> do
- XConf {display = dpy, theRoot = rootw} <- ask
- keysym <- io $ keycodeToKeysym dpy code 0
-
- case Map.lookup (win, (m, keysym)) map of
-
- Just xdo -> do
- xdo
- return (All False)
-
- Nothing -> return (All True)
-
- _ -> return (All True)
-
-getKeyCodesForKeysym :: Display -> KeySym -> IO [KeyCode]
-getKeyCodesForKeysym dpy keysym = do
- let (minCode, maxCode) = displayKeycodes dpy
- allCodes = [fromIntegral minCode .. fromIntegral maxCode]
-
- syms <- forM allCodes $ \code -> keycodeToKeysym dpy code 0
- let keysymMap' = Map.fromListWith (++) (zip syms [[code] | code <- allCodes])
-
- -- keycodeToKeysym returns noSymbol for all unbound keycodes, and we don't
- -- want to grab those whenever someone accidentally uses def :: KeySym
- let keysymMap = Map.delete noSymbol keysymMap'
- let keysymToKeycodes sym = Map.findWithDefault [] keysym keysymMap
-
- return $ keysymToKeycodes keysym
-
-
-doGrab :: Display -> Window -> (KeyMask, KeySym) -> X ()
-doGrab dpy win (keyMask, keysym) = do
- let grab kc m = io $ grabKey dpy kc m win True grabModeAsync grabModeAsync
-
- codes <- io $ getKeyCodesForKeysym dpy keysym
-
- forM_ codes $ \kc ->
- mapM_ (grab kc . (keyMask .|.)) =<< extraModifiers
-
-disableKey :: (KeyMask, KeySym) -> WindowHook
-disableKey key = remapKey key (return ())
-
-remapKey :: (KeyMask, KeySym) -> X () -> WindowHook
-remapKey keyFrom action = do
- window <- ask
- Query $ lift $ do
- XConf { display = disp, theRoot = rootw } <- ask
- doGrab disp window keyFrom
-
- XS.modify $ \(RemapState (NoPersist keyMap)) -> RemapState $ NoPersist $
- Map.insert (window, keyFrom) action keyMap
-
--- sendKey, but as a query.
-sendKeyQ :: (KeyMask, KeySym) -> Query ()
-sendKeyQ key = do
- win <- ask
- liftX (sendKey key win)
-
-sendKey :: (KeyMask, KeySym) -> Window -> X ()
-sendKey (keymask, keysym) w = do
- XConf { display = disp, theRoot = rootw } <- ask
-
- codes <- io $ getKeyCodesForKeysym disp keysym
-
- case codes of
- (keycode:_) ->
- io $ allocaXEvent $ \xEv -> do
- setEventType xEv keyPress
- setKeyEvent xEv w rootw none keymask keycode True
- sendEvent disp w True keyPressMask xEv
-
- setEventType xEv keyRelease
- sendEvent disp w True keyReleaseMask xEv
-
- _ -> return ()
-
-rebindKey :: (KeyMask, KeySym) -> (KeyMask, KeySym) -> WindowHook
-rebindKey keyFrom keyTo =
- (remapKey keyFrom . sendKey keyTo) =<< ask
diff --git a/src/Internal/ScreenRotate.hs b/src/Internal/ScreenRotate.hs
deleted file mode 100644
index 8108381..0000000
--- a/src/Internal/ScreenRotate.hs
+++ /dev/null
@@ -1,19 +0,0 @@
-module Internal.ScreenRotate where
-
-import XMonad.StackSet as W
-
-screenRotateBackward :: W.StackSet i l a sid sd -> W.StackSet i l a sid sd
-screenRotateBackward (W.StackSet current visible others floating) = do
- let screens = current : visible
- workspaces = tail $ cycle $ map W.workspace screens
- (current':visible') = zipWith (\s w -> s {workspace = w} ) screens workspaces
- in W.StackSet current' visible' others floating
-
-screenRotateForward :: W.StackSet i l a sid sd -> W.StackSet i l a sid sd
-screenRotateForward (W.StackSet current visible others floating) = do
- let screens = current : visible
- workspaces = rcycle $ map W.workspace screens
- (current':visible') = zipWith (\s w -> s {workspace = w} ) screens workspaces
- in W.StackSet current' visible' others floating
-
- where rcycle l = last l : l
diff --git a/src/Internal/Submap.hs b/src/Internal/Submap.hs
deleted file mode 100644
index 0e54c43..0000000
--- a/src/Internal/Submap.hs
+++ /dev/null
@@ -1,104 +0,0 @@
-module Internal.Submap (
- mapNextString,
- mapNextStringWithKeysym,
- submapButtonsWithKey,
- nextButton,
- nextMotion,
- nextMotionOrButton,
- module X) where
-
-import XMonad hiding (keys)
-import Control.Monad.Fix (fix)
-import qualified Data.Map as Map
-import Data.Map (Map)
-
-import XMonad.Actions.Submap as X
-
-{-
- - Like submap fram XMonad.Actions.Submap, but sends the string from
- - XLookupString to the function along side the keysym.
- -
- - This function allows mappings where the mapped string might be important,
- - but also allows submappings for keys that may not have a character associated
- - with them (for example, the function keys).
- -}
-mapNextStringWithKeysym :: (KeyMask -> KeySym -> String -> X a) -> X a
-mapNextStringWithKeysym fn = do
- XConf { theRoot = root, display = d } <- ask
- io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
-
- (m, str, keysym) <- io $ allocaXEvent $ \p -> fix $ \nextkey -> do
- maskEvent d keyPressMask p
- KeyEvent { ev_keycode = code, ev_state = m } <- getEvent p
- keysym <- keycodeToKeysym d code 0
- (_, str) <- lookupString (asKeyEvent p)
-
- if isModifierKey keysym
- then nextkey
- else return (m, str, keysym)
-
- io $ ungrabKeyboard d currentTime
-
- fn m keysym str
-
-{- Like submap, but on the character typed rather than the kysym. -}
-mapNextString :: (KeyMask -> String -> X a) -> X a
-mapNextString fn = mapNextStringWithKeysym (\m _ s -> fn m s)
-
-{- Grabs the mouse and returns the next button press. -}
-nextButton :: X (ButtonMask, Button)
-nextButton = do
- XConf { theRoot = root, display = d } <- ask
- io $ grabPointer d root False buttonPressMask grabModeAsync grabModeAsync 0 0 currentTime
-
- ret <- io $ allocaXEvent $ \xEv -> do
- maskEvent d buttonPressMask xEv
- ButtonEvent { ev_button = button, ev_state = m } <- getEvent xEv
- return (m, button)
-
- io $ ungrabPointer d currentTime
-
- return ret
-
-{- Grabs the mouse and reports the next mouse motion. -}
-nextMotion :: X (Int, Int)
-nextMotion = do
- XConf { theRoot = root, display = d } <- ask
- io $ grabPointer d root False pointerMotionMask grabModeAsync grabModeAsync 0 0 currentTime
-
- ret <- io $ allocaXEvent $ \xEv -> do
- maskEvent d pointerMotionMask xEv
- MotionEvent { ev_x = x, ev_y = y } <- getEvent xEv
- return (fromIntegral x, fromIntegral y)
-
- io $ ungrabPointer d currentTime
-
- return ret
-
-{- Grabs the mouse and reports the next mouse motion or button press. -}
-nextMotionOrButton :: X (Either (Int, Int) (ButtonMask, Button))
-nextMotionOrButton = do
- XConf { theRoot = root, display = d } <- ask
- io $ grabPointer d root False (pointerMotionMask .|. buttonPressMask) grabModeAsync grabModeAsync 0 0 currentTime
-
- ret <- io $ allocaXEvent $ \xEv -> do
- maskEvent d (pointerMotionMask .|. buttonPressMask) xEv
- ev <- getEvent xEv
- case ev of
- MotionEvent { ev_x = x, ev_y = y } ->
- return $ Left (fromIntegral x, fromIntegral y)
- ButtonEvent { ev_button = button, ev_state = m } ->
- return $ Right (m, button)
-
- io $ ungrabPointer d currentTime
-
- return ret
-
-submapButtonsWithKey ::
- ((ButtonMask, Button) -> Window -> X ()) -> Map (ButtonMask, Button) (Window -> X ()) -> Window -> X ()
-submapButtonsWithKey defaultAction actions window = do
- arg <- nextButton
-
- case Map.lookup arg actions of
- Nothing -> defaultAction arg window
- Just fn -> fn window
diff --git a/src/Internal/Swallow.hs b/src/Internal/Swallow.hs
deleted file mode 100644
index 3e4112f..0000000
--- a/src/Internal/Swallow.hs
+++ /dev/null
@@ -1,29 +0,0 @@
-module Internal.Swallow (
- swallowHook, setSwallowEnabled, isSwallowEnabled, toggleSwallowEnabled) where
-
-import XMonad
-import Data.Monoid (All)
-import XMonad.Hooks.WindowSwallowing
-import XMonad.Util.ExtensibleState as XS
-
-data DisableSwallow = DisableSwallow Bool deriving (Show)
-
-swallowHook :: Event -> X All
-swallowHook = swallowEventHook (className =? "Alacritty") $
- liftX $ do
- (DisableSwallow disable) <- XS.get
- return (not disable)
-
-isSwallowEnabled :: X Bool
-isSwallowEnabled = do
- (DisableSwallow b) <- XS.get
- return (not b)
-
-setSwallowEnabled :: Bool -> X ()
-setSwallowEnabled enable = XS.modify $ const $ DisableSwallow $ not enable
-
-toggleSwallowEnabled :: X ()
-toggleSwallowEnabled = (setSwallowEnabled . not) =<< isSwallowEnabled
-
-instance ExtensionClass DisableSwallow where
- initialValue = DisableSwallow False
diff --git a/src/Internal/SwapMaster.hs b/src/Internal/SwapMaster.hs
deleted file mode 100644
index e7ade19..0000000
--- a/src/Internal/SwapMaster.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{- Swap window with the master, but save it. -}
-module Internal.SwapMaster (swapMaster) where
-
-import qualified XMonad.StackSet as W
-
-import Internal.Windows (mapWindows, getMaster, swapWindows)
-import Control.Monad.Trans.Maybe
-import XMonad (Window, ExtensionClass(..), X(..), windows, windowset)
-import Control.Monad (void)
-import Control.Monad.Trans (lift)
-import Data.Maybe (fromMaybe)
-import Control.Monad.State (gets)
-
-import qualified XMonad.Util.ExtensibleState as XS
-
-newtype LastWindow = LastWindow {
- lastWindow :: Maybe Window
- } deriving (Show, Read)
-
-instance ExtensionClass LastWindow where
- initialValue = LastWindow Nothing
-
-hoist :: (Monad m) => Maybe a -> MaybeT m a
-hoist = MaybeT . return
-
-swapMaster :: X ()
-swapMaster = void $ runMaybeT $ do
- ss <- gets windowset
-
- focused <- hoist $ W.peek ss
- master <- hoist $ getMaster ss
-
- if focused == master
- then do
- lw <- MaybeT $ lastWindow <$> XS.get
- lift $ windows (swapWindows focused lw)
- else lift $ windows (swapWindows focused master)
-
- lift $ do
- XS.put (LastWindow $ Just master)
- windows W.focusMaster
diff --git a/src/Internal/Windows.hs b/src/Internal/Windows.hs
deleted file mode 100644
index 35f093c..0000000
--- a/src/Internal/Windows.hs
+++ /dev/null
@@ -1,86 +0,0 @@
-module Internal.Windows where
-
-import XMonad (windowset, X, Window, get)
-
-import Control.Applicative ((<|>))
-import XMonad.StackSet (Stack(..), StackSet(..), Screen(..), Workspace(..), peek, integrate, integrate', allWindows)
-import Data.Maybe (listToMaybe, catMaybes)
-import qualified Data.Map as Map
-
-mapWindows :: (Ord a, Ord b) => (a -> b) -> StackSet i l a s sd -> StackSet i l b s sd
-mapWindows fn (StackSet cur vis hid float) =
- StackSet
- (mapWindowsScreen cur)
- (map mapWindowsScreen vis)
- (map mapWindowsWorkspace hid)
- (Map.mapKeys fn float)
- where
- mapWindowsScreen (Screen work a b) = Screen (mapWindowsWorkspace work) a b
- mapWindowsWorkspace (Workspace t l stack) =
- Workspace t l (fmap (mapStack fn) stack)
-
--- | What genius decided to hide the instances for the Stack type!!???
-mapStack :: (a -> b) -> Stack a -> Stack b
-mapStack fn (Stack focus up down) = Stack (fn focus) (map fn up) (map fn down)
-
-getMaster :: StackSet i l a s sd -> Maybe a
-getMaster (StackSet (Screen (Workspace _ _ ss) _ _) _ _ _) =
- head . integrate <$> ss
-
-swapWindows :: (Ord a) => a -> a -> StackSet i l a s d -> StackSet i l a s d
-swapWindows wa wb = mapWindows $ \w ->
- case w of
- _ | w == wa -> wb
- _ | w == wb -> wa
- _ -> w
-
-data WindowLocation i l a s sd =
- OnScreen (Screen i l a s sd) |
- OnHiddenWorkspace (Workspace i l a) |
- Floating
-
-getLocationWorkspace :: WindowLocation i l a s sd -> Maybe (Workspace i l a)
-getLocationWorkspace (OnScreen (Screen w _ _)) = Just w
-getLocationWorkspace (OnHiddenWorkspace w) = Just w
-getLocationWorkspace _ = Nothing
-
-workspaceMember :: (Eq a) => Workspace i l a -> a -> Bool
-workspaceMember (Workspace _ _ s) w = w `elem` integrate' s
-
-forAllWindows :: (Window -> X ()) -> X ()
-forAllWindows fn = do
- stackSet <- windowset <$> get
- mapM_ fn (allWindows stackSet)
-
-getFocusedWindow :: X (Maybe Window)
-getFocusedWindow = do
- peek . windowset <$> get
-
-{- Finds a Window and returns the screen its on and the workspace its on.
- - Returns nothing if the window doesn't exist.
- -
- - If the window is not a screen Just (Nothing, workspace) is returned.
- - If the window is a floating window Just (Nothing, Nothing) is returned. -}
-findWindow ::
- (Eq a) => StackSet i l a s sd -> a -> Maybe (WindowLocation i l a s sd)
-findWindow (StackSet cur vis hid float) win =
- listToMaybe . catMaybes $
- map findWindowScreen (cur : vis) ++
- map findWindowWorkspace hid ++
- [findWindowFloat]
-
- where
- findWindowScreen s@(Screen ws _ _) =
- if workspaceMember ws win
- then Just (OnScreen s)
- else Nothing
-
- findWindowWorkspace w =
- if workspaceMember w win
- then Just (OnHiddenWorkspace w)
- else Nothing
-
- findWindowFloat =
- if win `elem` Map.keys float
- then Just Floating
- else Nothing
diff --git a/src/Internal/XMobarLog.hs b/src/Internal/XMobarLog.hs
deleted file mode 100644
index c0aa2a7..0000000
--- a/src/Internal/XMobarLog.hs
+++ /dev/null
@@ -1,78 +0,0 @@
-module Internal.XMobarLog ( XMobarLog, spawnXMobar, xMobarLogHook ) where
-
-import Control.Arrow (second)
-import Control.Monad (forM_)
-import Control.Monad.Writer (tell, execWriter)
-import Data.List (sortBy)
-import Data.Maybe (mapMaybe)
-import Data.Ord (comparing)
-import Internal.LayoutDraw (drawLayout)
-import System.IO (Handle, hSetEncoding, hPutStrLn, utf8)
-import XMonad.Util.NamedWindows (getName)
-import XMonad.Util.Run (spawnPipe)
-import XMonad (X)
-import Internal.Lib (getPopulatedWorkspaces, WorkspaceState(..))
-
-import qualified XMonad as X
-import qualified XMonad.StackSet as S
-
-data XMobarLog = XMobarLog Handle
-
--- The log hook for XMobar. This is a custom log hook that does not use any
--- of the Xmonad dynamic log libraries.
---
--- This is because the given dynamic log libraries don't handle unicode properly
--- and this has been causing issues. It is also more flexible and frankly easier
--- to just DIY.
-
-spawnXMobar :: IO XMobarLog
-spawnXMobar = do
- pipe <- spawnPipe "xmobar"
- hSetEncoding pipe utf8
- return (XMobarLog pipe)
-
-
--- XMonad Log Hook meant to be used with the XMonad config logHook.
-xMobarLogHook :: XMobarLog -> X ()
-xMobarLogHook (XMobarLog xmproc) = do
- (_, _, layoutXpm) <- drawLayout
-
- winset <- X.gets X.windowset
- title <- maybe (pure "") (fmap show . getName) . S.peek $ winset
- let wss = getPopulatedWorkspaces winset
-
- X.liftIO $ do
- hPutStrLn xmproc $ trunc 80 $ execWriter $ do
- tell layoutXpm
- tell $ "<fc=#404040> │ </fc>"
-
- forM_ wss $ \(t, ws) -> do
- case t of
- Current -> tell "<fn=1><fc=#ff8888>"
- Visible -> tell "<fn=6><fc=#8888ff>"
- Hidden -> tell "<fn=2><fc=#888888>"
- tell (S.tag ws)
- tell " </fc></fn>"
-
- tell $ "<fc=#404040>│ </fc><fc=#a0a0a0><fn=3>"
- tell $ title
- tell $ "</fn></fc>"
-
--- Truncate an XMobar string to the provided number of _visible_ characters.
--- This is to keep long window titles from overrunning the whole bar.
-trunc :: Int -> String -> String
-trunc amt str = reverse $ trunc' False amt str []
- where
- 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)