From 9718dabe6c6d5979e3f6837ef04a39d3ad8c786c Mon Sep 17 00:00:00 2001 From: Martin Perner Date: Wed, 26 Oct 2011 01:00:32 +0200 Subject: Adding locale support to Date plugins This commits adds support for localized datetime outputs like date(1). --- NEWS | 3 +- README | 27 +++++++++++-- src/Config.hs | 6 ++- src/Localize.hsc | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ src/Plugins/DateL.hs | 35 +++++++++++++++++ src/Plugins/DateZone.hs | 2 +- src/Plugins/DateZoneL.hs | 42 +++++++++++++++++++++ xmobar.cabal | 4 +- 8 files changed, 208 insertions(+), 9 deletions(-) create mode 100644 src/Localize.hsc create mode 100644 src/Plugins/DateL.hs create mode 100644 src/Plugins/DateZoneL.hs diff --git a/NEWS b/NEWS index 05a98f7..0f04c84 100644 --- a/NEWS +++ b/NEWS @@ -6,7 +6,8 @@ _New features_ - New brightness monitor, courtesy of Martin Perner. - - New DateZone plugin, for localized datetimes, also by Martin. + - New DateL, DateZone, DateZoneL plugins, for configurable timezone and + localized datetimes, also by Martin. - New keyboard layout monitor (Kbd). Yes, by Martin. - Rewrite of the event handling ([issue 53], [issue 57]), also by Martin. - Cpu monitor now also reports `iowait` field ([issue 55]). diff --git a/README b/README index 4bacecd..48c48ed 100644 --- a/README +++ b/README @@ -125,8 +125,8 @@ Otherwise, you'll need to install them yourself. [alsa-mixer] package. `with_datezone` -: Support for localized times. Enables the DateZone plugin. Requires - [timezone-olson] and [timezone-series] package. +: Support for other timezones. Enables the DateZone and DateZoneL plugin. + Requires [timezone-olson] and [timezone-series] package. `all_extensions` : Enables all the extensions above. @@ -872,7 +872,7 @@ can be used in the output template as `%mydate%` `strftime` function (or Haskell's `formatCalendarTime`). - Sample usage: `Run Date "%a %b %_d %Y %H:%M:%S" "date" 10` -`Date Format Alias Zone RefreshRate` +`DateZone Format Alias Zone RefreshRate` - Format is a time format string, as accepted by the standard ISO C `strftime` function (or Haskell's `formatCalendarTime`). @@ -881,6 +881,24 @@ can be used in the output template as `%mydate%` - Sample usage: `Run DateZone "%H:%M:%S" "viennaDate" "Europa/Vienna" 10` +`DateL Format Locale Alias RefreshRate` + +- Behaves as Date but localizes the output +- If Locale is "" the default locale of the system is used, otherwise the given + locale +- As this plugin calls `setlocale`, there can only be one locale used, besides + English (default of Haskell, used in Date and DateZone) with DateL and + DateZoneL. If multiple plugin instances, with different locales, are used + the result is a race condition, but consistent between all plugins. +- Usage with system locale: + `Run DateL "%B" "" "date" 10` +- Usage with german locale: + `Run DateL "%B" "de_DE.UTF-8" "date" 10` + +`DateZoneL Format Locale Alias Zone RefreshRate` + +- Behaves as DateZone but localizes the output +- Please check DateL for information's about Locale `CommandReader "/path/to/program" Alias` @@ -1109,4 +1127,7 @@ Copyright © 2010-2011 Jose Antonio Ortega Ruiz [libmpd]: http://hackage.haskell.org/package/libmpd/ [sawfish]: http://sawfish.wikia.com/ [utf8-string]: http://hackage.haskell.org/package/utf8-string/ +[alsa-core]: http://hackage.haskell.org/package/alsa-core [alsa-mixer]: http://hackage.haskell.org/package/alsa-mixer +[timezone-olson]: http://hackage.haskell.org/package/timezone-olson +[timezone-series]: http://hackage.haskell.org/package/timezone-series diff --git a/src/Config.hs b/src/Config.hs index 4405314..cc1692e 100644 --- a/src/Config.hs +++ b/src/Config.hs @@ -27,6 +27,7 @@ import Commands import {-# SOURCE #-} Runnable import Plugins.Monitors import Plugins.Date +import Plugins.DateL import Plugins.PipeReader import Plugins.CommandReader import Plugins.StdinReader @@ -41,6 +42,7 @@ import Plugins.MBox #ifdef DATEZONE import Plugins.DateZone +import Plugins.DateZoneL #endif -- $config @@ -113,12 +115,12 @@ infixr :*: -- the 'Runnable.Runnable' Read instance. To install a plugin just add -- the plugin's type to the list of types (separated by ':*:') appearing in -- this function's type signature. -runnableTypes :: Command :*: Monitors :*: Date :*: PipeReader :*: CommandReader :*: StdinReader :*: XMonadLog :*: EWMH :*: Kbd :*: +runnableTypes :: Command :*: Monitors :*: Date :*: DateL :*: PipeReader :*: CommandReader :*: StdinReader :*: XMonadLog :*: EWMH :*: Kbd :*: #ifdef INOTIFY Mail :*: MBox :*: #endif #ifdef DATEZONE - DateZone :*: + DateZone :*: DateZoneL :*: #endif () runnableTypes = undefined diff --git a/src/Localize.hsc b/src/Localize.hsc new file mode 100644 index 0000000..bfaa6f0 --- /dev/null +++ b/src/Localize.hsc @@ -0,0 +1,98 @@ +{-# LANGUAGE ForeignFunctionInterface #-} +----------------------------------------------------------------------------- +-- | +-- Module : Localize +-- Copyright : (C) 2011 Martin Perner +-- License : BSD-style (see LICENSE) +-- +-- Maintainer : Martin Perner +-- Stability : unstable +-- Portability : unportable +-- +-- This module provides an interface to locale information e.g. for DateL +-- +----------------------------------------------------------------------------- + +module Localize + ( setupTimeLocale, + getTimeLocale + ) where + +import Foreign +import Foreign.C +import qualified System.Locale as L + +#ifdef UTF8 +import Codec.Binary.UTF8.String +#endif + +-- get localized strings +type NlItem = CInt + +#include +foreign import ccall unsafe "langinfo.h nl_langinfo" + nl_langinfo :: NlItem -> IO CString + +#{enum NlItem, + , AM_STR , PM_STR \ + , D_T_FMT , D_FMT , T_FMT , T_FMT_AMPM \ + , ABDAY_1 , ABDAY_2 , ABDAY_3 , ABDAY_4 , ABDAY_5 , ABDAY_6 , ABDAY_7 \ + , DAY_1 , DAY_2 , DAY_3 , DAY_4 , DAY_5 , DAY_6 , DAY_7 \ + , ABMON_1 , ABMON_2 , ABMON_3 , ABMON_4 , ABMON_5 , ABMON_6 , ABMON_7 \ + , ABMON_8 , ABMON_9 , ABMON_10 , ABMON_11 , ABMON_12 \ + , MON_1 , MON_2 , MON_3 , MON_4 , MON_5 , MON_6 , MON_7 , MON_8 , MON_9 \ + , MON_10 , MON_11 , MON_12\ + } + +#let LIST_CTR fst,snd,idx = "( getLangInfo "fst""idx" , getLangInfo "snd""idx" )" + +getLangInfo :: NlItem -> String +#ifdef UTF8 +getLangInfo item = decodeString $ unsafePerformIO $ getLangInfo' item +#else +getLangInfo item = unsafePerformIO $ getLangInfo' item +#endif + +getLangInfo' :: NlItem -> IO String +getLangInfo' item = do + itemStr <- nl_langinfo item + peekCString itemStr + +#include +foreign import ccall unsafe "locale.h setlocale" + setlocale :: CInt -> CString -> IO CString + +setupTimeLocale :: String -> IO () +setupTimeLocale l = withCString l (setlocale #const LC_TIME) >> return () + +getTimeLocale :: L.TimeLocale +getTimeLocale = L.TimeLocale { + L.wDays = [ #{LIST_CTR "day","abday","1"} + , #{LIST_CTR "day","abday","2"} + , #{LIST_CTR "day","abday","3"} + , #{LIST_CTR "day","abday","4"} + , #{LIST_CTR "day","abday","5"} + , #{LIST_CTR "day","abday","6"} + , #{LIST_CTR "day","abday","7"} + ], + L.months = [ #{LIST_CTR "mon","abmon","1"} + , #{LIST_CTR "mon","abmon","2"} + , #{LIST_CTR "mon","abmon","3"} + , #{LIST_CTR "mon","abmon","4"} + , #{LIST_CTR "mon","abmon","5"} + , #{LIST_CTR "mon","abmon","6"} + , #{LIST_CTR "mon","abmon","7"} + , #{LIST_CTR "mon","abmon","8"} + , #{LIST_CTR "mon","abmon","9"} + , #{LIST_CTR "mon","abmon","10"} + , #{LIST_CTR "mon","abmon","11"} + , #{LIST_CTR "mon","abmon","12"} + ], + -- Intervals are not available from this interface + L.intervals = L.intervals L.defaultTimeLocale, + L.amPm = (getLangInfo amStr, getLangInfo pmStr), + L.dateTimeFmt = getLangInfo dTFmt, + L.dateFmt = getLangInfo dFmt, + L.timeFmt = getLangInfo tFmt, + L.time12Fmt = getLangInfo tFmtAmpm + } diff --git a/src/Plugins/DateL.hs b/src/Plugins/DateL.hs new file mode 100644 index 0000000..d8859ed --- /dev/null +++ b/src/Plugins/DateL.hs @@ -0,0 +1,35 @@ +----------------------------------------------------------------------------- +-- | +-- Module : Plugins.DateL +-- Copyright : (c) Andrea Rossato +-- License : BSD-style (see LICENSE) +-- +-- Maintainer : Martin Perner +-- Stability : unstable +-- Portability : unportable +-- +-- A date plugin with localization for Xmobar +-- +----------------------------------------------------------------------------- + +module Plugins.DateL (DateL(..)) where + +import Plugins +import Localize + +import System.Time + +data DateL = DateL String String String Int + deriving (Read, Show) + +instance Exec DateL where + alias (DateL _ _ a _) = a + start (DateL f l _ r) cb = do + setupTimeLocale l + go + where go = date f >>= cb >> tenthSeconds r >> go + +date :: String -> IO String +date format = do + t <- toCalendarTime =<< getClockTime + return $ formatCalendarTime getTimeLocale format t diff --git a/src/Plugins/DateZone.hs b/src/Plugins/DateZone.hs index 4d5ce6a..f6c4f7a 100644 --- a/src/Plugins/DateZone.hs +++ b/src/Plugins/DateZone.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- A date plugin with localization support for Xmobar +-- A date plugin with location support for Xmobar -- -- Based on Plugins.Date -- diff --git a/src/Plugins/DateZoneL.hs b/src/Plugins/DateZoneL.hs new file mode 100644 index 0000000..2b7c467 --- /dev/null +++ b/src/Plugins/DateZoneL.hs @@ -0,0 +1,42 @@ +----------------------------------------------------------------------------- +-- | +-- Module : Plugins.DateZoneL +-- Copyright : (c) Martin Perner +-- License : BSD-style (see LICENSE) +-- +-- Maintainer : Martin Perner +-- Stability : unstable +-- Portability : unportable +-- +-- A date plugin with localization and location support for Xmobar +-- +-- Based on Plugins.DateZone +-- +----------------------------------------------------------------------------- + +module Plugins.DateZoneL (DateZoneL(..)) where + +import Plugins + +import Localize + +import Data.Time.LocalTime +import Data.Time.Format +import Data.Time.LocalTime.TimeZone.Olson +import Data.Time.LocalTime.TimeZone.Series + +data DateZoneL = DateZoneL String String String String Int + deriving (Read, Show) + +instance Exec DateZoneL where + alias (DateZoneL _ _ a _ _) = a + start (DateZoneL f l _ z r) cb = do + setupTimeLocale l + go + where go = date f z >>= cb >> tenthSeconds r >> go + +date :: String -> String -> IO String +date format zone = do + timeZone <- getTimeZoneSeriesFromOlsonFile ("/usr/share/zoneinfo/" ++ zone) + zonedTime <- getZonedTime + return $ formatTime getTimeLocale format $ utcToLocalTime' timeZone $ zonedTimeToUTC zonedTime diff --git a/xmobar.cabal b/xmobar.cabal index 56cbce3..e830c02 100644 --- a/xmobar.cabal +++ b/xmobar.cabal @@ -65,7 +65,7 @@ executable xmobar hs-source-dirs: src main-is: Main.hs other-modules: - Xmobar, Config, Parsers, Commands, XUtil, StatFS, Runnable, + Xmobar, Config, Parsers, Commands, Localize, XUtil, StatFS, Runnable, Plugins, Plugins.CommandReader, Plugins.Date, Plugins.EWMH, Plugins.PipeReader, Plugins.StdinReader, Plugins.XMonadLog, Plugins.Utils, Plugins.Kbd, Plugins.Monitors, @@ -77,7 +77,7 @@ executable xmobar Plugins.Monitors.Swap, Plugins.Monitors.Thermal, Plugins.Monitors.ThermalZone, Plugins.Monitors.Top, Plugins.Monitors.Uptime, Plugins.Monitors.Weather, - Plugins.Monitors.Bright + Plugins.Monitors.Bright, Plugins.DateL, Plugins.DateZoneL ghc-prof-options: -prof -auto-all -- cgit v1.2.3 From f6bb8eb4c4350522367f4ab2dacbfeb0a99cd06d Mon Sep 17 00:00:00 2001 From: Martin Perner Date: Thu, 27 Oct 2011 20:51:19 +0200 Subject: DateZone, Date*L Plugin merges; DateZone API-Change! To support multiple locales, an lock was introduced. Although through this, supporting DateL and DateZoneL would be cumbersome. To simplify the usage, DateZone was replaced with DateZoneL. Additionally the position of the Alias parameter was changed. Using "" as Zone parameter for DateZoneL simulates DateL. Providing also "" for locale simulates Date. --- NEWS | 4 +-- README | 33 ++++++------------- src/Config.hs | 6 ++-- src/Localize.hsc | 83 ++++++++++++++++++++---------------------------- src/Plugins/DateL.hs | 35 -------------------- src/Plugins/DateZone.hs | 50 ++++++++++++++++++++++------- src/Plugins/DateZoneL.hs | 42 ------------------------ xmobar.cabal | 2 +- 8 files changed, 88 insertions(+), 167 deletions(-) delete mode 100644 src/Plugins/DateL.hs delete mode 100644 src/Plugins/DateZoneL.hs diff --git a/NEWS b/NEWS index 0f04c84..dc9576f 100644 --- a/NEWS +++ b/NEWS @@ -6,8 +6,8 @@ _New features_ - New brightness monitor, courtesy of Martin Perner. - - New DateL, DateZone, DateZoneL plugins, for configurable timezone and - localized datetimes, also by Martin. + - New DateZone plugin, for configurable timezone and localized datetimes, also + by Martin. - New keyboard layout monitor (Kbd). Yes, by Martin. - Rewrite of the event handling ([issue 53], [issue 57]), also by Martin. - Cpu monitor now also reports `iowait` field ([issue 55]). diff --git a/README b/README index 48c48ed..f6d0ac0 100644 --- a/README +++ b/README @@ -125,7 +125,7 @@ Otherwise, you'll need to install them yourself. [alsa-mixer] package. `with_datezone` -: Support for other timezones. Enables the DateZone and DateZoneL plugin. +: Support for other timezones. Enables the DateZone plugin. Requires [timezone-olson] and [timezone-series] package. `all_extensions` @@ -872,33 +872,18 @@ can be used in the output template as `%mydate%` `strftime` function (or Haskell's `formatCalendarTime`). - Sample usage: `Run Date "%a %b %_d %Y %H:%M:%S" "date" 10` -`DateZone Format Alias Zone RefreshRate` +`DateZone Format Locale Zone Alias RefreshRate` - Format is a time format string, as accepted by the standard ISO C `strftime` function (or Haskell's `formatCalendarTime`). -- Zone is the name of the TimeZone. Assumes that the tz database is stored in - /usr/share/zoneinfo/ -- Sample usage: - `Run DateZone "%H:%M:%S" "viennaDate" "Europa/Vienna" 10` - -`DateL Format Locale Alias RefreshRate` - -- Behaves as Date but localizes the output - If Locale is "" the default locale of the system is used, otherwise the given - locale -- As this plugin calls `setlocale`, there can only be one locale used, besides - English (default of Haskell, used in Date and DateZone) with DateL and - DateZoneL. If multiple plugin instances, with different locales, are used - the result is a race condition, but consistent between all plugins. -- Usage with system locale: - `Run DateL "%B" "" "date" 10` -- Usage with german locale: - `Run DateL "%B" "de_DE.UTF-8" "date" 10` - -`DateZoneL Format Locale Alias Zone RefreshRate` - -- Behaves as DateZone but localizes the output -- Please check DateL for information's about Locale + locale. If there are more instances of DateZone, using "" as input for Locacle + is not recommended. +- Zone is the name of the TimeZone. It is assumed that the tz database is stored + in /usr/share/zoneinfo/. If "" is given as Zone, the default system time is + used. +- Sample usage: + `Run DateZone "%H:%M:%S" "GMT+1" "Europe/Vienna" "viennaTime" 10` `CommandReader "/path/to/program" Alias` diff --git a/src/Config.hs b/src/Config.hs index cc1692e..4405314 100644 --- a/src/Config.hs +++ b/src/Config.hs @@ -27,7 +27,6 @@ import Commands import {-# SOURCE #-} Runnable import Plugins.Monitors import Plugins.Date -import Plugins.DateL import Plugins.PipeReader import Plugins.CommandReader import Plugins.StdinReader @@ -42,7 +41,6 @@ import Plugins.MBox #ifdef DATEZONE import Plugins.DateZone -import Plugins.DateZoneL #endif -- $config @@ -115,12 +113,12 @@ infixr :*: -- the 'Runnable.Runnable' Read instance. To install a plugin just add -- the plugin's type to the list of types (separated by ':*:') appearing in -- this function's type signature. -runnableTypes :: Command :*: Monitors :*: Date :*: DateL :*: PipeReader :*: CommandReader :*: StdinReader :*: XMonadLog :*: EWMH :*: Kbd :*: +runnableTypes :: Command :*: Monitors :*: Date :*: PipeReader :*: CommandReader :*: StdinReader :*: XMonadLog :*: EWMH :*: Kbd :*: #ifdef INOTIFY Mail :*: MBox :*: #endif #ifdef DATEZONE - DateZone :*: DateZoneL :*: + DateZone :*: #endif () runnableTypes = undefined diff --git a/src/Localize.hsc b/src/Localize.hsc index bfaa6f0..b302cd4 100644 --- a/src/Localize.hsc +++ b/src/Localize.hsc @@ -18,7 +18,6 @@ module Localize getTimeLocale ) where -import Foreign import Foreign.C import qualified System.Locale as L @@ -36,27 +35,21 @@ foreign import ccall unsafe "langinfo.h nl_langinfo" #{enum NlItem, , AM_STR , PM_STR \ , D_T_FMT , D_FMT , T_FMT , T_FMT_AMPM \ - , ABDAY_1 , ABDAY_2 , ABDAY_3 , ABDAY_4 , ABDAY_5 , ABDAY_6 , ABDAY_7 \ - , DAY_1 , DAY_2 , DAY_3 , DAY_4 , DAY_5 , DAY_6 , DAY_7 \ - , ABMON_1 , ABMON_2 , ABMON_3 , ABMON_4 , ABMON_5 , ABMON_6 , ABMON_7 \ - , ABMON_8 , ABMON_9 , ABMON_10 , ABMON_11 , ABMON_12 \ - , MON_1 , MON_2 , MON_3 , MON_4 , MON_5 , MON_6 , MON_7 , MON_8 , MON_9 \ - , MON_10 , MON_11 , MON_12\ + , ABDAY_1, ABDAY_7 \ + , DAY_1, DAY_7 \ + , ABMON_1, ABMON_12 \ + , MON_1, MON_12\ } -#let LIST_CTR fst,snd,idx = "( getLangInfo "fst""idx" , getLangInfo "snd""idx" )" - -getLangInfo :: NlItem -> String +getLangInfo :: NlItem -> IO String +getLangInfo item = do + itemStr <- nl_langinfo item #ifdef UTF8 -getLangInfo item = decodeString $ unsafePerformIO $ getLangInfo' item + str <- peekCString itemStr + return $ decodeString str #else -getLangInfo item = unsafePerformIO $ getLangInfo' item -#endif - -getLangInfo' :: NlItem -> IO String -getLangInfo' item = do - itemStr <- nl_langinfo item peekCString itemStr +#endif #include foreign import ccall unsafe "locale.h setlocale" @@ -65,34 +58,28 @@ foreign import ccall unsafe "locale.h setlocale" setupTimeLocale :: String -> IO () setupTimeLocale l = withCString l (setlocale #const LC_TIME) >> return () -getTimeLocale :: L.TimeLocale -getTimeLocale = L.TimeLocale { - L.wDays = [ #{LIST_CTR "day","abday","1"} - , #{LIST_CTR "day","abday","2"} - , #{LIST_CTR "day","abday","3"} - , #{LIST_CTR "day","abday","4"} - , #{LIST_CTR "day","abday","5"} - , #{LIST_CTR "day","abday","6"} - , #{LIST_CTR "day","abday","7"} - ], - L.months = [ #{LIST_CTR "mon","abmon","1"} - , #{LIST_CTR "mon","abmon","2"} - , #{LIST_CTR "mon","abmon","3"} - , #{LIST_CTR "mon","abmon","4"} - , #{LIST_CTR "mon","abmon","5"} - , #{LIST_CTR "mon","abmon","6"} - , #{LIST_CTR "mon","abmon","7"} - , #{LIST_CTR "mon","abmon","8"} - , #{LIST_CTR "mon","abmon","9"} - , #{LIST_CTR "mon","abmon","10"} - , #{LIST_CTR "mon","abmon","11"} - , #{LIST_CTR "mon","abmon","12"} - ], - -- Intervals are not available from this interface - L.intervals = L.intervals L.defaultTimeLocale, - L.amPm = (getLangInfo amStr, getLangInfo pmStr), - L.dateTimeFmt = getLangInfo dTFmt, - L.dateFmt = getLangInfo dFmt, - L.timeFmt = getLangInfo tFmt, - L.time12Fmt = getLangInfo tFmtAmpm - } +getTimeLocale :: IO L.TimeLocale +getTimeLocale = do + -- assumes that the defined values are increasing by exactly one. + -- as they are defined consecutive in an enum this is reasonable + days <- mapM getLangInfo [day1 .. day7] + abdays <- mapM getLangInfo [abday1 .. abday7] + + mons <- mapM getLangInfo [mon1 .. mon12] + abmons <- mapM getLangInfo [abmon1 .. abmon12] + + amstr <- getLangInfo amStr + pmstr <- getLangInfo pmStr + dtfmt <- getLangInfo dTFmt + dfmt <- getLangInfo dFmt + tfmt <- getLangInfo tFmt + tfmta <- getLangInfo tFmtAmpm + + let t = L.defaultTimeLocale {L.wDays = zip days abdays + ,L.months = zip mons abmons + ,L.amPm = (amstr, pmstr) + ,L.dateTimeFmt = dtfmt + ,L.dateFmt = dfmt + ,L.timeFmt = tfmt + ,L.time12Fmt = tfmta} + return t diff --git a/src/Plugins/DateL.hs b/src/Plugins/DateL.hs deleted file mode 100644 index d8859ed..0000000 --- a/src/Plugins/DateL.hs +++ /dev/null @@ -1,35 +0,0 @@ ------------------------------------------------------------------------------ --- | --- Module : Plugins.DateL --- Copyright : (c) Andrea Rossato --- License : BSD-style (see LICENSE) --- --- Maintainer : Martin Perner --- Stability : unstable --- Portability : unportable --- --- A date plugin with localization for Xmobar --- ------------------------------------------------------------------------------ - -module Plugins.DateL (DateL(..)) where - -import Plugins -import Localize - -import System.Time - -data DateL = DateL String String String Int - deriving (Read, Show) - -instance Exec DateL where - alias (DateL _ _ a _) = a - start (DateL f l _ r) cb = do - setupTimeLocale l - go - where go = date f >>= cb >> tenthSeconds r >> go - -date :: String -> IO String -date format = do - t <- toCalendarTime =<< getClockTime - return $ formatCalendarTime getTimeLocale format t diff --git a/src/Plugins/DateZone.hs b/src/Plugins/DateZone.hs index f6c4f7a..86114bb 100644 --- a/src/Plugins/DateZone.hs +++ b/src/Plugins/DateZone.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE DoAndIfThenElse #-} ----------------------------------------------------------------------------- -- | -- Module : Plugins.DateZone @@ -8,13 +9,13 @@ -- Stability : unstable -- Portability : unportable -- --- A date plugin with location support for Xmobar +-- A date plugin with localization and location support for Xmobar -- -- Based on Plugins.Date -- -- Usage example: in template put -- --- > Run DateZone "%H:%M:%S" "utcDate" "UTC" 10 +-- > Run DateZone "%a %H:%M:%S" "de_DE.UTF-8" "UTC" "utcDate" 10 -- ----------------------------------------------------------------------------- @@ -22,23 +23,50 @@ module Plugins.DateZone (DateZone(..)) where import Plugins -import System.Locale +import Localize + +import Control.Concurrent.STM import Data.Time.LocalTime import Data.Time.Format import Data.Time.LocalTime.TimeZone.Olson import Data.Time.LocalTime.TimeZone.Series -data DateZone = DateZone String String String Int +import System.IO.Unsafe +import System.Locale (TimeLocale) +import System.Time + + + +{-# NOINLINE localeLock #-} +-- ensures that only one plugin instance sets the locale +localeLock :: TMVar Bool +localeLock = unsafePerformIO (newTMVarIO False) + +data DateZone = DateZone String String String String Int deriving (Read, Show) instance Exec DateZone where - alias (DateZone _ a _ _) = a - run (DateZone f _ z _) = date f z - rate (DateZone _ _ _ r) = r + alias (DateZone _ _ _ a _) = a + start (DateZone f l z _ r) cb = do + lock <- atomically $ takeTMVar localeLock + setupTimeLocale l + locale <- getTimeLocale + atomically $ putTMVar localeLock lock + if z /= "" then do + timeZone <- getTimeZoneSeriesFromOlsonFile ("/usr/share/zoneinfo/" ++ z) + go (dateZone f locale timeZone) + else + go (date f locale) + + where go func = func >>= cb >> tenthSeconds r >> go func + +date :: String -> TimeLocale -> IO String +date format loc = do + t <- toCalendarTime =<< getClockTime + return $ formatCalendarTime loc format t -date :: String -> String -> IO String -date format zone = do - timeZone <- getTimeZoneSeriesFromOlsonFile ("/usr/share/zoneinfo/" ++ zone) +dateZone :: String -> TimeLocale -> TimeZoneSeries -> IO String +dateZone format loc timeZone = do zonedTime <- getZonedTime - return $ formatTime defaultTimeLocale format $ utcToLocalTime' timeZone $ zonedTimeToUTC zonedTime + return $ formatTime loc format $ utcToLocalTime' timeZone $ zonedTimeToUTC zonedTime diff --git a/src/Plugins/DateZoneL.hs b/src/Plugins/DateZoneL.hs deleted file mode 100644 index 2b7c467..0000000 --- a/src/Plugins/DateZoneL.hs +++ /dev/null @@ -1,42 +0,0 @@ ------------------------------------------------------------------------------ --- | --- Module : Plugins.DateZoneL --- Copyright : (c) Martin Perner --- License : BSD-style (see LICENSE) --- --- Maintainer : Martin Perner --- Stability : unstable --- Portability : unportable --- --- A date plugin with localization and location support for Xmobar --- --- Based on Plugins.DateZone --- ------------------------------------------------------------------------------ - -module Plugins.DateZoneL (DateZoneL(..)) where - -import Plugins - -import Localize - -import Data.Time.LocalTime -import Data.Time.Format -import Data.Time.LocalTime.TimeZone.Olson -import Data.Time.LocalTime.TimeZone.Series - -data DateZoneL = DateZoneL String String String String Int - deriving (Read, Show) - -instance Exec DateZoneL where - alias (DateZoneL _ _ a _ _) = a - start (DateZoneL f l _ z r) cb = do - setupTimeLocale l - go - where go = date f z >>= cb >> tenthSeconds r >> go - -date :: String -> String -> IO String -date format zone = do - timeZone <- getTimeZoneSeriesFromOlsonFile ("/usr/share/zoneinfo/" ++ zone) - zonedTime <- getZonedTime - return $ formatTime getTimeLocale format $ utcToLocalTime' timeZone $ zonedTimeToUTC zonedTime diff --git a/xmobar.cabal b/xmobar.cabal index e830c02..6d3b32e 100644 --- a/xmobar.cabal +++ b/xmobar.cabal @@ -77,7 +77,7 @@ executable xmobar Plugins.Monitors.Swap, Plugins.Monitors.Thermal, Plugins.Monitors.ThermalZone, Plugins.Monitors.Top, Plugins.Monitors.Uptime, Plugins.Monitors.Weather, - Plugins.Monitors.Bright, Plugins.DateL, Plugins.DateZoneL + Plugins.Monitors.Bright ghc-prof-options: -prof -auto-all -- cgit v1.2.3