xmonad-config/lib/XMonad/Internal/Command/Desktop.hs

322 lines
9.9 KiB
Haskell
Raw Normal View History

2020-03-28 18:38:38 -04:00
--------------------------------------------------------------------------------
-- | General commands
2020-04-01 20:17:47 -04:00
module XMonad.Internal.Command.Desktop
( myTerm
2022-07-03 01:11:32 -04:00
, playSound
-- commands
2020-04-01 20:17:47 -04:00
, runTerm
2021-06-17 01:17:59 -04:00
, runTMux
2020-04-01 20:17:47 -04:00
, runCalc
, runBrowser
, runEditor
, runFileManager
, runTogglePlay
, runPrevTrack
, runNextTrack
, runStopPlay
, runVolumeDown
, runVolumeUp
, runVolumeMute
, runToggleBluetooth
2020-05-28 23:17:17 -04:00
, runToggleEthernet
2020-04-01 20:17:47 -04:00
, runRestart
, runRecompile
, runAreaCapture
, runScreenCapture
, runDesktopCapture
, runCaptureBrowser
2021-02-04 21:46:04 -05:00
, runStartISyncTimer
, runStartISyncService
2021-10-24 13:30:30 -04:00
, runNotificationClose
, runNotificationCloseAll
, runNotificationHistory
, runNotificationContext
2022-07-03 01:11:32 -04:00
-- daemons
, runNetAppDaemon
, runFlameshotDaemon
, runNotificationDaemon
2020-04-01 20:17:47 -04:00
) where
2021-11-11 00:11:15 -05:00
import Control.Monad (void)
2021-11-20 01:15:04 -05:00
import Control.Monad.IO.Class
2020-04-01 20:17:47 -04:00
import System.Directory
( createDirectoryIfMissing
, getHomeDirectory
)
import System.Environment
import System.FilePath
2020-03-28 18:38:38 -04:00
2022-03-05 18:18:16 -05:00
import XMonad (asks)
2020-03-28 18:38:38 -04:00
import XMonad.Actions.Volume
2021-11-11 00:11:15 -05:00
import XMonad.Core hiding (spawn)
import XMonad.Internal.Dependency
2020-04-01 20:17:47 -04:00
import XMonad.Internal.Notify
import XMonad.Internal.Process
2021-11-20 01:15:04 -05:00
import XMonad.Internal.Shell
2020-03-28 18:38:38 -04:00
import XMonad.Operations
--------------------------------------------------------------------------------
2021-06-19 00:17:47 -04:00
-- | My Executables
2020-03-28 18:38:38 -04:00
2020-04-01 20:17:47 -04:00
myTerm :: String
myTerm = "urxvt"
2021-06-19 00:17:47 -04:00
myBrowser :: String
myBrowser = "brave-accel"
myEditor :: String
myEditor = "emacsclient"
myMultimediaCtl :: String
myMultimediaCtl = "playerctl"
myBluetooth :: String
myBluetooth = "bluetoothctl"
myCapture :: String
myCapture = "flameshot"
myImageBrowser :: String
myImageBrowser = "feh"
2021-10-24 13:30:30 -04:00
myNotificationCtrl :: String
myNotificationCtrl = "dunstctl"
2022-07-03 01:11:32 -04:00
myNotificationDaemon :: String
myNotificationDaemon = "dunst"
2021-06-19 00:17:47 -04:00
--------------------------------------------------------------------------------
-- | Misc constants
volumeChangeSound :: FilePath
volumeChangeSound = "smb_fireball.wav"
ethernetIface :: String
ethernetIface = "enp7s0f1"
2020-03-28 18:38:38 -04:00
2021-06-19 00:17:47 -04:00
--------------------------------------------------------------------------------
-- | Some nice apps
runTerm :: SometimesX
2022-06-28 23:27:55 -04:00
runTerm = sometimesExe "terminal" "urxvt" True myTerm
2021-06-19 00:17:47 -04:00
runTMux :: SometimesX
2022-07-02 17:09:21 -04:00
runTMux = sometimesIO_ "terminal multiplexer" "tmux" deps act
2021-06-17 01:17:59 -04:00
where
deps = listToAnds (sysExe myTerm) $ fmap sysExe ["tmux", "bash"]
act = spawn
2021-06-19 00:17:47 -04:00
$ "tmux has-session"
#!&& fmtCmd myTerm ["-e", "bash", "-c", singleQuote c]
#!|| fmtNotifyCmd defNoteError { body = Just $ Text msg }
2021-06-17 01:17:59 -04:00
c = "exec tmux attach-session -d"
msg = "could not connect to tmux session"
runCalc :: SometimesX
2022-07-02 17:09:21 -04:00
runCalc = sometimesIO_ "calculator" "R" deps act
where
deps = toAnd (sysExe myTerm) (sysExe "R")
act = spawnCmd myTerm ["-e", "R"]
2020-03-28 18:38:38 -04:00
runBrowser :: SometimesX
2022-06-28 23:27:55 -04:00
runBrowser = sometimesExe "web browser" "brave" False myBrowser
2020-03-28 18:38:38 -04:00
runEditor :: SometimesX
2022-06-28 23:27:55 -04:00
runEditor = sometimesExeArgs "text editor" "emacs" True myEditor
2021-06-17 01:17:59 -04:00
["-c", "-e", doubleQuote "(select-frame-set-input-focus (selected-frame))"]
2020-03-28 18:38:38 -04:00
runFileManager :: SometimesX
2022-06-28 23:27:55 -04:00
runFileManager = sometimesExe "file browser" "pcmanfm" True "pcmanfm"
2020-03-28 18:38:38 -04:00
--------------------------------------------------------------------------------
-- | Multimedia Commands
runMultimediaIfInstalled :: String -> String -> SometimesX
2022-06-28 23:27:55 -04:00
runMultimediaIfInstalled n cmd = sometimesExeArgs (n ++ " multimedia control")
"playerctl" True myMultimediaCtl [cmd]
2020-03-28 18:38:38 -04:00
runTogglePlay :: SometimesX
runTogglePlay = runMultimediaIfInstalled "play/pause" "play-pause"
2020-03-28 18:38:38 -04:00
runPrevTrack :: SometimesX
runPrevTrack = runMultimediaIfInstalled "previous track" "previous"
2020-03-28 18:38:38 -04:00
runNextTrack :: SometimesX
runNextTrack = runMultimediaIfInstalled "next track" "next"
2020-03-28 18:38:38 -04:00
runStopPlay :: SometimesX
runStopPlay = runMultimediaIfInstalled "stop playback" "stop"
2020-03-28 18:38:38 -04:00
2021-11-20 01:15:04 -05:00
--------------------------------------------------------------------------------
-- | Volume Commands
soundDir :: FilePath
soundDir = "sound"
playSound :: MonadIO m => FilePath -> m ()
playSound file = do
2022-03-05 18:18:16 -05:00
-- manually look up directories to avoid the X monad
p <- io $ (</> soundDir </> file) . cfgDir <$> getDirectories
2021-11-20 01:15:04 -05:00
-- paplay seems to have less latency than aplay
spawnCmd "paplay" [p]
2020-05-31 20:56:57 -04:00
featureSound :: String -> FilePath -> X () -> X () -> SometimesX
featureSound n file pre post =
2022-07-02 17:09:21 -04:00
sometimesIO_ ("volume " ++ n ++ " control") "paplay" (Only_ $ sysExe "paplay")
2021-11-20 01:15:04 -05:00
$ pre >> playSound file >> post
2020-03-28 18:38:38 -04:00
runVolumeDown :: SometimesX
runVolumeDown = featureSound "up" volumeChangeSound (return ()) $ void (lowerVolume 2)
2021-11-20 01:15:04 -05:00
runVolumeUp :: SometimesX
runVolumeUp = featureSound "down" volumeChangeSound (return ()) $ void (raiseVolume 2)
2021-11-20 01:15:04 -05:00
runVolumeMute :: SometimesX
runVolumeMute = featureSound "mute" volumeChangeSound (void toggleMute) $ return ()
2020-03-28 18:38:38 -04:00
2021-10-24 13:30:30 -04:00
--------------------------------------------------------------------------------
-- | Notification control
2022-07-03 01:11:32 -04:00
runNotificationDaemon :: Sometimes (IO ProcessHandle)
runNotificationDaemon = sometimesIO_ "notification daemon" "dunst" tree cmd
where
tree = Only_ $ sysExe myNotificationDaemon
cmd = snd <$> spawnPipe myNotificationDaemon
runNotificationCmd :: String -> FilePath -> SometimesX
2022-07-03 01:11:32 -04:00
runNotificationCmd n arg = sometimesIO_ (n ++ " control") "dunstctl" tree cmd
where
tree = And_ (Only_ $ IOSometimes_ runNotificationDaemon)
(Only_ $ sysExe myNotificationCtrl)
cmd = spawnCmd myNotificationCtrl [arg]
2021-10-24 13:30:30 -04:00
runNotificationClose :: SometimesX
runNotificationClose = runNotificationCmd "close notification" "close"
2021-10-24 13:30:30 -04:00
runNotificationCloseAll :: SometimesX
runNotificationCloseAll =
runNotificationCmd "close all notifications" "close-all"
2021-10-24 13:30:30 -04:00
runNotificationHistory :: SometimesX
runNotificationHistory =
runNotificationCmd "see notification history" "history-pop"
2021-10-24 13:30:30 -04:00
runNotificationContext :: SometimesX
runNotificationContext =
runNotificationCmd "open notification context" "context"
2021-10-24 13:30:30 -04:00
2020-03-28 18:38:38 -04:00
--------------------------------------------------------------------------------
-- | System commands
2022-07-03 01:11:32 -04:00
-- this is required for some vpn's to work properly with network-manager
runNetAppDaemon :: Sometimes (IO ProcessHandle)
runNetAppDaemon = sometimesIO_ "network applet" "NM-applet" tree cmd
where
tree = Only_ $ localExe "nm-applet"
cmd = snd <$> spawnPipe "nm-applet"
runToggleBluetooth :: SometimesX
runToggleBluetooth =
2022-07-02 17:09:21 -04:00
sometimesIO_ "bluetooth toggle" "bluetoothctl" (Only_ $ sysExe myBluetooth)
$ spawn
2021-06-19 00:17:47 -04:00
$ myBluetooth ++ " show | grep -q \"Powered: no\""
2020-03-28 18:38:38 -04:00
#!&& "a=on"
#!|| "a=off"
2021-06-19 00:17:47 -04:00
#!>> fmtCmd myBluetooth ["power", "$a", ">", "/dev/null"]
2020-03-28 18:38:38 -04:00
#!&& fmtNotifyCmd defNoteInfo { body = Just $ Text "bluetooth powered $a" }
runToggleEthernet :: SometimesX
2022-07-02 17:09:21 -04:00
runToggleEthernet = sometimesIO_ "ethernet toggle" "nmcli" (Only_ $ sysExe "nmcli")
$ spawn
2020-05-28 23:17:17 -04:00
$ "nmcli -g GENERAL.STATE device show " ++ ethernetIface ++ " | grep -q disconnected"
#!&& "a=connect"
#!|| "a=disconnect"
#!>> fmtCmd "nmcli" ["device", "$a", ethernetIface]
#!&& fmtNotifyCmd defNoteInfo { body = Just $ Text "ethernet \"$a\"ed" }
runStartISyncTimer :: SometimesX
2022-07-02 17:09:21 -04:00
runStartISyncTimer = sometimesIO_ "isync timer" "mbsync timer"
2022-06-28 23:27:55 -04:00
(Only_ $ sysdUser "mbsync.timer")
$ spawn
2021-02-04 21:46:04 -05:00
$ "systemctl --user start mbsync.timer"
#!&& fmtNotifyCmd defNoteInfo { body = Just $ Text "Isync timer started" }
#!|| fmtNotifyCmd defNoteError { body = Just $ Text "Isync timer failed to start" }
2021-02-04 21:46:04 -05:00
runStartISyncService :: SometimesX
2022-07-02 17:09:21 -04:00
runStartISyncService = sometimesIO_ "isync" "mbsync service"
2022-06-28 23:27:55 -04:00
(Only_ $ sysdUser "mbsync.service")
$ spawn
2021-02-04 21:46:04 -05:00
$ "systemctl --user start mbsync.service"
#!&& fmtNotifyCmd defNoteInfo { body = Just $ Text "Isync completed" }
#!|| fmtNotifyCmd defNoteError { body = Just $ Text "Isync failed" }
2021-02-04 21:46:04 -05:00
2020-03-28 18:38:38 -04:00
--------------------------------------------------------------------------------
-- | Configuration commands
runRestart :: X ()
runRestart = restart "xmonad" True
runRecompile :: X ()
runRecompile = do
-- assume that the conf directory contains a valid stack project
2022-03-05 18:18:16 -05:00
confDir <- asks (cfgDir . directories)
spawnAt confDir $ fmtCmd "stack" ["install"]
#!&& fmtNotifyCmd defNoteInfo { body = Just $ Text "compilation succeeded" }
#!|| fmtNotifyCmd defNoteError { body = Just $ Text "compilation failed" }
-- runRecompile :: X ()
-- runRecompile = do
-- -- assume that the conf directory contains a valid stack project
-- -- TODO this is hacky AF
-- confDir <- getXMonadDir
-- spawnCmdAt confDir "stack" ["install"]
2020-04-01 20:17:47 -04:00
--------------------------------------------------------------------------------
-- | Screen capture commands
getCaptureDir :: IO FilePath
getCaptureDir = do
e <- lookupEnv "XDG_DATA_HOME"
parent <- case e of
Nothing -> fallback
Just path
| isRelative path -> fallback
| otherwise -> return path
let fullpath = parent </> "screenshots"
createDirectoryIfMissing True fullpath
return fullpath
where
fallback = (</> ".local/share") <$> getHomeDirectory
2020-04-01 20:17:47 -04:00
2022-07-03 01:11:32 -04:00
runFlameshotDaemon :: Sometimes (IO ProcessHandle)
runFlameshotDaemon = sometimesIO_ "screen capture daemon" "flameshot" tree cmd
where
tree = Only_ $ sysExe myCapture
cmd = snd <$> (spawnPipe' $ (shell myCapture) { std_err = NoStream })
runFlameshot :: String -> String -> SometimesX
2022-07-03 01:11:32 -04:00
runFlameshot n mode = sometimesIO_ n myCapture
(Only_ $ IOSometimes_ runFlameshotDaemon) $ spawnCmd myCapture [mode]
2020-04-01 20:17:47 -04:00
-- TODO this will steal focus from the current window (and puts it
-- in the root window?) ...need to fix
runAreaCapture :: SometimesX
runAreaCapture = runFlameshot "screen area capture" "gui"
2020-04-01 20:17:47 -04:00
-- myWindowCap = "screencap -w" --external script
runDesktopCapture :: SometimesX
runDesktopCapture = runFlameshot "fullscreen capture" "full"
runScreenCapture :: SometimesX
runScreenCapture = runFlameshot "screen capture" "screen"
2021-06-19 00:54:01 -04:00
runCaptureBrowser :: SometimesX
2022-07-02 17:09:21 -04:00
runCaptureBrowser = sometimesIO_ "screen capture browser" "feh"
2022-06-28 23:27:55 -04:00
(Only_ $ sysExe myImageBrowser) $ do
dir <- io getCaptureDir
2021-06-19 00:17:47 -04:00
spawnCmd myImageBrowser [dir]