-------------------------------------------------------------------------------- -- | General commands module XMonad.Internal.Command.Desktop ( myTerm , runTerm , runTMux , runCalc , runBrowser , runEditor , runFileManager , runTogglePlay , runPrevTrack , runNextTrack , runStopPlay , runVolumeDown , runVolumeUp , runVolumeMute , runToggleBluetooth , runIncBacklight , runDecBacklight , runMinBacklight , runMaxBacklight , runToggleDPMS , runToggleEthernet , runRestart , runRecompile , runAreaCapture , runScreenCapture , runDesktopCapture , runCaptureBrowser , runStartISyncTimer , runStartISyncService ) where import Control.Monad (void) import System.Directory ( createDirectoryIfMissing , getHomeDirectory ) import System.Environment import System.FilePath import XMonad.Actions.Volume import XMonad.Core hiding (spawn) import XMonad.Internal.DBus.IntelBacklight import XMonad.Internal.DBus.Screensaver import XMonad.Internal.Notify import XMonad.Internal.Process import XMonad.Internal.Shell import XMonad.Operations -------------------------------------------------------------------------------- -- | Some nice apps myTerm :: String myTerm = "urxvt" runTerm :: X () runTerm = spawn myTerm runTMux :: X () runTMux = spawn $ "tmux has-session" #!&& fmtCmd myTerm ["-e", "bash", "-c", singleQuote c] #!|| fmtNotifyCmd defNoteError { body = Just $ Text msg } where c = "exec tmux attach-session -d" msg = "could not connect to tmux session" runCalc :: X () runCalc = spawnCmd myTerm ["-e", "R"] runBrowser :: X () runBrowser = spawn "brave-accel" runEditor :: X () runEditor = spawnCmd "emacsclient" ["-c", "-e", doubleQuote "(select-frame-set-input-focus (selected-frame))"] runFileManager :: X () runFileManager = spawn "pcmanfm" -------------------------------------------------------------------------------- -- | Multimedia Commands myMultimediaCtl :: String myMultimediaCtl = "playerctl" runTogglePlay :: X () runTogglePlay = spawnCmd myMultimediaCtl ["play-pause"] runPrevTrack :: X () runPrevTrack = spawnCmd myMultimediaCtl ["previous"] runNextTrack :: X () runNextTrack = spawnCmd myMultimediaCtl ["next"] runStopPlay :: X () runStopPlay = spawnCmd myMultimediaCtl ["stop"] volumeChangeSound :: FilePath volumeChangeSound = "smb_fireball.wav" runVolumeDown :: X () runVolumeDown = spawnSound volumeChangeSound >> void (lowerVolume 2) runVolumeUp :: X () runVolumeUp = spawnSound volumeChangeSound >> void (raiseVolume 2) runVolumeMute :: X () runVolumeMute = void toggleMute >> spawnSound volumeChangeSound -------------------------------------------------------------------------------- -- | System commands runToggleBluetooth :: X () runToggleBluetooth = spawn $ "bluetoothctl show | grep -q \"Powered: no\"" #!&& "a=on" #!|| "a=off" #!>> fmtCmd "bluetoothctl" ["power", "$a", ">", "/dev/null"] #!&& fmtNotifyCmd defNoteInfo { body = Just $ Text "bluetooth powered $a" } runIncBacklight :: X () runIncBacklight = io $ void callIncBrightness runDecBacklight :: X () runDecBacklight = io $ void callDecBrightness runMinBacklight :: X () runMinBacklight = io $ void callMinBrightness runMaxBacklight :: X () runMaxBacklight = io $ void callMaxBrightness runToggleDPMS :: X () runToggleDPMS = io $ void callToggle ethernetIface :: String ethernetIface = "enp7s0f1" runToggleEthernet :: X () runToggleEthernet = spawn $ "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 :: X () runStartISyncTimer = spawn $ "systemctl --user start mbsync.timer" #!&& fmtNotifyCmd defNoteInfo { body = Just $ Text "Isync timer started" } #!|| fmtNotifyCmd defNoteError { body = Just $ Text "Isync timer failed to start" } runStartISyncService :: X () runStartISyncService = spawn $ "systemctl --user start mbsync.service" #!&& fmtNotifyCmd defNoteInfo { body = Just $ Text "Isync completed" } #!|| fmtNotifyCmd defNoteError { body = Just $ Text "Isync failed" } -------------------------------------------------------------------------------- -- | Configuration commands runRestart :: X () runRestart = restart "xmonad" True runRecompile :: X () runRecompile = do -- assume that the conf directory contains a valid stack project confDir <- getXMonadDir 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"] -------------------------------------------------------------------------------- -- | 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 runFlameshot :: String -> X () runFlameshot mode = do ssDir <- io getCaptureDir spawnCmd "flameshot" $ mode : ["-p", ssDir] -- TODO this will steal focus from the current window (and puts it -- in the root window?) ...need to fix runAreaCapture :: X () runAreaCapture = runFlameshot "gui" -- myWindowCap = "screencap -w" --external script runScreenCapture :: X () runScreenCapture = runFlameshot "screen" runDesktopCapture :: X () runDesktopCapture = runFlameshot "full" runCaptureBrowser :: X () runCaptureBrowser = do dir <- io getCaptureDir spawnCmd "feh" [dir]