summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorslotThe <soliditsallgood@tuta.io>2020-01-09 15:54:47 +0100
committerjao <jao@gnu.org>2020-01-16 15:05:22 +0000
commit1f1f0bd8b811740c84215f9ed4fa5ebd8309a990 (patch)
tree998ac613e08a115bfcceb7e1d93388a028980e6e
parent36c69246f1a19af2a0713a8d8c7ab59ad108736f (diff)
downloadxmobar-1f1f0bd8b811740c84215f9ed4fa5ebd8309a990.tar.gz
xmobar-1f1f0bd8b811740c84215f9ed4fa5ebd8309a990.tar.bz2
Use a single Manager across the whole application
-rw-r--r--src/Xmobar/Plugins/Monitors/Common/Types.hs9
-rw-r--r--src/Xmobar/Plugins/Monitors/UVMeter.hs30
-rw-r--r--src/Xmobar/Plugins/Monitors/Weather.hs62
-rw-r--r--xmobar.cabal8
4 files changed, 66 insertions, 43 deletions
diff --git a/src/Xmobar/Plugins/Monitors/Common/Types.hs b/src/Xmobar/Plugins/Monitors/Common/Types.hs
index c36a562..8662ba3 100644
--- a/src/Xmobar/Plugins/Monitors/Common/Types.hs
+++ b/src/Xmobar/Plugins/Monitors/Common/Types.hs
@@ -25,8 +25,9 @@ module Xmobar.Plugins.Monitors.Common.Types ( Monitor
, io
) where
-import Data.IORef
-import Control.Monad.Reader
+import Data.IORef (IORef, modifyIORef, newIORef, readIORef)
+import Control.Monad.Reader (ReaderT, ask, liftIO)
+import Network.HTTP.Conduit (Manager, newManager, tlsManagerSettings)
type Monitor a = ReaderT MConfig IO a
@@ -55,6 +56,7 @@ data MConfig =
, naString :: IORef String
, maxTotalWidth :: IORef Int
, maxTotalWidthEllipsis :: IORef String
+ , manager :: IORef Manager
}
-- | from 'http:\/\/www.haskell.org\/hawiki\/MonadState'
@@ -102,7 +104,8 @@ mkMConfig tmpl exprts =
na <- newIORef "N/A"
mt <- newIORef 0
mtel <- newIORef ""
- return $ MC nc l lc h hc t e p d mn mx mel pc pr bb bf bw up na mt mtel
+ man <- newIORef =<< newManager tlsManagerSettings
+ return $ MC nc l lc h hc t e p d mn mx mel pc pr bb bf bw up na mt mtel man
data Opts = HighColor String
| NormalColor String
diff --git a/src/Xmobar/Plugins/Monitors/UVMeter.hs b/src/Xmobar/Plugins/Monitors/UVMeter.hs
index 079177f..3756856 100644
--- a/src/Xmobar/Plugins/Monitors/UVMeter.hs
+++ b/src/Xmobar/Plugins/Monitors/UVMeter.hs
@@ -18,14 +18,14 @@ module Xmobar.Plugins.Monitors.UVMeter where
import Xmobar.Plugins.Monitors.Common
import qualified Control.Exception as CE
-import Network.HTTP.Conduit
- (parseRequest, newManager, tlsManagerSettings, httpLbs,
- responseBody)
+import Network.HTTP.Conduit (httpLbs, parseRequest, responseBody)
import Data.ByteString.Lazy.Char8 as B
import Text.Read (readMaybe)
import Text.Parsec
import Text.Parsec.String
import Control.Monad (void)
+import Control.Monad.Reader (asks)
+import Data.IORef (readIORef)
uvConfig :: IO MConfig
@@ -40,16 +40,18 @@ newtype UvInfo = UV { index :: String }
uvURL :: String
uvURL = "https://uvdata.arpansa.gov.au/xml/uvvalues.xml"
-getData :: IO String
-getData =
- CE.catch (do request <- parseRequest uvURL
- manager <- newManager tlsManagerSettings
- res <- httpLbs request manager
- return $ B.unpack $ responseBody res)
- errHandler
- where errHandler
- :: CE.SomeException -> IO String
- errHandler _ = return "<Could not retrieve data>"
+-- | Get the UV data from the given url.
+getData :: Monitor String
+getData = do
+ man <- io =<< readIORef <$> asks manager
+ io $ CE.catch
+ (do request <- parseRequest uvURL
+ res <- httpLbs request man
+ return $ B.unpack $ responseBody res)
+ errHandler
+ where
+ errHandler :: CE.SomeException -> IO String
+ errHandler _ = return "<Could not retrieve data>"
textToXMLDocument :: String -> Either ParseError [XML]
textToXMLDocument = parse document ""
@@ -73,7 +75,7 @@ getUVRating _ [] = Nothing
runUVMeter :: [String] -> Monitor String
runUVMeter [] = return "N.A."
runUVMeter (s:_) = do
- resp <- io getData
+ resp <- getData
case textToXMLDocument resp of
Right doc -> formatUVRating (getUVRating s doc)
Left _ -> getConfigValue naString
diff --git a/src/Xmobar/Plugins/Monitors/Weather.hs b/src/Xmobar/Plugins/Monitors/Weather.hs
index 07d8cc4..250c258 100644
--- a/src/Xmobar/Plugins/Monitors/Weather.hs
+++ b/src/Xmobar/Plugins/Monitors/Weather.hs
@@ -19,11 +19,13 @@ import Xmobar.Plugins.Monitors.Common
import qualified Control.Exception as CE
-import Network.HTTP.Conduit
-import Network.HTTP.Types.Status
-import Network.HTTP.Types.Method
+import Control.Monad.Reader (asks)
import qualified Data.ByteString.Lazy.Char8 as B
import Data.Char (toLower)
+import Data.IORef (readIORef)
+import Network.HTTP.Conduit
+import Network.HTTP.Types.Method (methodHead)
+import Network.HTTP.Types.Status
import Text.ParserCombinators.Parsec
import System.Console.GetOpt (ArgDescr(ReqArg), OptDescr(Option))
@@ -208,15 +210,18 @@ defUrl = "https://tgftp.nws.noaa.gov/data/observations/metar/decoded/"
stationUrl :: String -> String
stationUrl station = defUrl ++ station ++ ".TXT"
-getData :: String -> IO String
-getData station = CE.catch (do
- manager <- newManager tlsManagerSettings
- request <- parseUrlThrow $ stationUrl station
- res <- httpLbs request manager
- return $ B.unpack $ responseBody res
- ) errHandler
- where errHandler :: CE.SomeException -> IO String
- errHandler _ = return "<Could not retrieve data>"
+-- | Get the decoded weather data from the given station.
+getData :: String -> Monitor String
+getData station = do
+ man <- io =<< readIORef <$> asks manager
+ io $ CE.catch ( do
+ request <- parseUrlThrow $ stationUrl station
+ res <- httpLbs request man
+ return $ B.unpack $ responseBody res
+ ) errHandler
+ where
+ errHandler :: CE.SomeException -> IO String
+ errHandler _ = return "<Could not retrieve data>"
formatSk :: Eq p => [(p, p)] -> p -> p
formatSk ((a,b):sks) sk = if a == sk then b else formatSk sks sk
@@ -242,27 +247,38 @@ showWeather :: String -> String -> String
showWeather "" d = d
showWeather s _ = s
+-- | Run the 'Weather' monitor.
runWeather :: [String] -> Monitor String
runWeather = runWeather' []
-runWeather' :: [(String, String)] -> [String] -> Monitor String
+-- | Run the 'WeatherX' monitor.
+runWeather'
+ :: [(String, String)] -- ^ 'SkyConditionS' replacement strings
+ -> [String] -- ^ User supplied arguments
+ -> Monitor String
runWeather' sks args =
- do d <- io $ getData $ head args
+ do d <- getData $ head args
o <- io $ parseOptsWith options defaultOpts args
i <- io $ runP parseData d
formatWeather o sks i
+-- | Test internet connectivity before executing the monitor.
weatherReady :: [String] -> Monitor Bool
weatherReady str = do
initRequest <- parseUrlThrow $ stationUrl $ head str
let request = initRequest{method = methodHead}
+ man <- io =<< readIORef <$> asks manager
io $ CE.catch ( do
- manager <- newManager tlsManagerSettings
- res <- httpLbs request manager
- return $ checkResult $responseStatus res ) errHandler
- where errHandler :: CE.SomeException -> IO Bool
- errHandler _ = return False
- checkResult status
- | statusIsServerError status = False
- | statusIsClientError status = False
- | otherwise = True
+ res <- httpLbs request man
+ return $ checkResult $ responseStatus res ) errHandler
+ where
+ -- | If any exception occurs, indicate that the monitor is not ready.
+ errHandler :: CE.SomeException -> IO Bool
+ errHandler _ = return False
+
+ -- | Check for and indicate any errors in the http response.
+ checkResult :: Status -> Bool
+ checkResult status
+ | statusIsServerError status = False
+ | statusIsClientError status = False
+ | otherwise = True
diff --git a/xmobar.cabal b/xmobar.cabal
index 1eff7ba..176a18d 100644
--- a/xmobar.cabal
+++ b/xmobar.cabal
@@ -176,7 +176,8 @@ library
parsec-numbers >= 0.1.0,
stm >= 2.3 && < 2.6,
extensible-exceptions == 0.1.*,
- async
+ async,
+ http-conduit
if impl(ghc < 8.0.2)
-- Disable building with GHC before 8.0.2.
@@ -250,11 +251,11 @@ library
if flag(with_weather) || flag(all_extensions)
exposed-modules: Xmobar.Plugins.Monitors.Weather
cpp-options: -DWEATHER
- build-depends: http-conduit, http-types
+ build-depends: http-types
if flag(with_uvmeter)
exposed-modules: Xmobar.Plugins.Monitors.UVMeter
- build-depends: http-conduit, http-types
+ build-depends: http-types
cpp-options: -DUVMETER
if os(freebsd)
@@ -310,6 +311,7 @@ test-suite XmobarTest
async,
temporary,
hspec == 2.*,
+ http-conduit,
xmobar
other-modules: Xmobar.Plugins.Monitors.CommonSpec