{-# LANGUAGE OverloadedStrings #-} module Main where import Common import Data.Bool import Data.Text (lines, pack) import Turtle 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 bool (airplaneModeOff cards) (airplaneModeOn cards) isAirplaneOn where airplaneModeOn cards = do liftIO $ putStrLn "\61554"; handleClick Deactivate cards airplaneModeOff cards = do liftIO $ putStrLn "\61554 x"; handleClick Activate cards 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