packages feed

libnotify-0.2: example/notify-send.hs

{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
module Main (main) where

import           Data.Bool (bool)
import           Data.Int (Int32)
import           Data.Maybe (catMaybes)
import           Data.Word (Word8)
import qualified Libnotify as L
import           Options.Applicative
import           Prelude hiding (mod)
import           Text.Printf (printf)
import           Text.Read (readEither)


main :: IO ()
main = do
  Options {summary, body, mod} <- parseOpts
  L.display_ (mod <> L.summary summary <> foldMap L.body body)

data Options = Options
  { summary :: String
  , body    :: Maybe String
  , mod     :: L.Mod L.Notification
  }

parseOpts :: IO Options
parseOpts =
  customExecParser (prefs showHelpOnError) (info (helper <*> parser) desc)
 where
  desc =
    fullDesc <> progDesc "Create a notification." <> header "notify-send - an example of the libnotify library"
  parser = do
    summary <- argument str (metavar "SUMMARY")
    body <- optional (argument str (metavar "BODY"))
    mod <- parserMod
    pure Options {..}
  parserMod =
    fmap (mconcat . catMaybes) . traverse optional $
      [ option urgency  (short 'u' <> long "urgency"  <> metavar "LEVEL")
      , option timeout  (short 't' <> long "timeout"  <> metavar "TIME")
      , option appName  (short 'a' <> long "app-name" <> metavar "APP_NAME")
      , option icon     (short 'i' <> long "icon"     <> metavar "ICON")
      , option category (short 'c' <> long "category" <> metavar "TIME")
      , option hint     (short 'h' <> long "hint"     <> metavar "TYPE:NAME:VALUE")
      ]
  urgency =
    eitherReader $ \case
      "low" ->
        pure (L.urgency L.Low)
      "normal" ->
        pure (L.urgency L.Normal)
      "critical" ->
        pure (L.urgency L.Critical)
      urg ->
        Left (printf "Unknown urgency `%s'. Known urgencies: `low', `normal', and `critical'." urg)
  timeout = do
    time <- auto
    pure (L.timeout (bool (L.Custom time) L.Infinite (time == 0)))
  appName = do
    name <- str
    pure (L.appName name)
  icon = do
    name <- str
    pure (L.icon name)
  category = do
    cat <- str
    pure (L.category cat)
  hint :: ReadM (L.Mod L.Notification)
  hint =
    eitherReader $ \typeNameVal ->
      case break (== ':') typeNameVal of
        (type_, ':' : nameVal) ->
          case break (== ':') nameVal of
            (name, ':' : val) ->
              case type_ of
                "int" -> do
                  int <- readEither val
                  pure (L.hint name (int :: Int32))
                "double" -> do
                  double <- readEither val
                  pure (L.hint name (double :: Double))
                "string" ->
                  pure (L.hint name val)
                "byte" -> do
                  byte <- readEither val
                  pure (L.hint name (byte :: Word8))
                _ ->
                  Left (printf "Invalid hint: `%s`" typeNameVal)
            _ ->
              Left (printf "Invalid hint: `%s`" typeNameVal)
        _ ->
          Left (printf "Invalid hint: `%s`" typeNameVal)