{-# LANGUAGE OverloadedStrings #-} module Main where import Common import Data.Bool import Data.Text (lines, pack) import Data.Text.IO (putStrLn) import Prelude hiding (putStrLn) import Turtle import System.Environment (getArgs) import qualified Data.Text as Text import Data.Maybe type CardName = Text type CardDev = Text data BlockType = Soft | Hard | SoftAndHard | NotBlocked deriving (Eq, Show) type Index = Int data Card = Card { index :: Index, cardName :: CardName, cardDev :: CardDev, blockType :: BlockType } deriving Show data AirplaneAction = Activate | Deactivate deriving (Eq, Show) main :: IO () main = sh $ do rfkill <- rfkill' let cards = head $ match (parseCards rfkill) rfkill let isAirplaneOn = isAirplaneMode cards icons <- liftIO getArgs bool (airplaneModeOff icons cards) (airplaneModeOn icons cards) isAirplaneOn where airplaneModeOn icons cards = do liftIO $ putStrLn $ fromMaybe "Airplane On" $ getAirplaneOnIcon icons handleClick Deactivate cards airplaneModeOff icons cards = do liftIO $ putStrLn $ fromMaybe "Airplane Off" $ getAirplaneOffIcon icons handleClick Activate cards getAirplaneOffIcon :: [String] -> Maybe Text getAirplaneOffIcon icons = case icons of airplaneOffIcon : _ -> Just $ Text.pack airplaneOffIcon _ -> Nothing getAirplaneOnIcon :: [String] -> Maybe Text getAirplaneOnIcon icons = case icons of _ : airplaneOnIcon : _ -> Just $ Text.pack airplaneOnIcon _ -> Nothing handleClick :: AirplaneAction -> [Card] -> Shell [ExitCode] handleClick action cards = do leftClicked <- buttonClicked LeftClick bool (return []) (sequence $ blockCards action cards) leftClicked blockCards :: AirplaneAction -> [Card] -> [Shell ExitCode] blockCards act cards = actionCard act . index <$> cards actionCard :: (MonadIO io, Show a) => AirplaneAction -> a -> io ExitCode actionCard Deactivate i = shell (pack $ "rfkill unblock " ++ show i) empty actionCard Activate i = shell (pack $ "rfkill block " ++ show i) empty isAirplaneMode :: [Card] -> Bool isAirplaneMode = all ((/= NotBlocked) . blockType) parseCards :: Text -> Pattern [Card] parseCards rfkill = let cardCount = countCards rfkill in bounded cardCount cardCount parseCard where countCards = (`div` linesPerCard) . length . Data.Text.lines linesPerCard = 3 parseCard :: Pattern Card parseCard = do index' <- decimal <* separator cardDev' <- star alphaNum <* separator cardName' <- chars1 <* newline soft <- tab *> "Soft blocked" *> separator *> ("yes" <|> "no") <* newline hard <- tab *> "Hard blocked" *> separator *> ("yes" <|> "no") <* newline return $ Card index' cardName' cardDev' (toBlockType soft hard) where separator = skip (":" *> spaces1) toBlockType "yes" "yes" = SoftAndHard toBlockType "yes" _ = Soft toBlockType _ "yes" = Hard toBlockType _ _ = NotBlocked rfkill' :: Shell Text rfkill' = strict $ inshell (pack "rfkill list") empty