diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | README | 20 | ||||
-rw-r--r-- | src/Localize.hsc | 85 | ||||
-rw-r--r-- | src/Plugins/DateZone.hs | 50 | ||||
-rw-r--r-- | xmobar.cabal | 2 |
5 files changed, 140 insertions, 20 deletions
@@ -6,7 +6,8 @@ _New features_ - New brightness monitor, courtesy of Martin Perner. - - New DateZone plugin, for 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]). @@ -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 plugin. + Requires [timezone-olson] and [timezone-series] package. `all_extensions` : Enables all the extensions above. @@ -872,15 +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 <fc=#ee9a00>%H:%M:%S</fc>" "date" 10` -`Date 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/ +- If Locale is "" the default locale of the system is used, otherwise the given + 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 "<fc=#ee9a00>%H:%M:%S</fc>" "viennaDate" "Europa/Vienna" 10` - + `Run DateZone "<fc=#ee9a00>%H:%M:%S</fc>" "GMT+1" "Europe/Vienna" "viennaTime" 10` `CommandReader "/path/to/program" Alias` @@ -1109,4 +1112,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/Localize.hsc b/src/Localize.hsc new file mode 100644 index 0000000..b302cd4 --- /dev/null +++ b/src/Localize.hsc @@ -0,0 +1,85 @@ +{-# LANGUAGE ForeignFunctionInterface #-} +----------------------------------------------------------------------------- +-- | +-- Module : Localize +-- Copyright : (C) 2011 Martin Perner +-- License : BSD-style (see LICENSE) +-- +-- Maintainer : Martin Perner <martin@perner.cc> +-- Stability : unstable +-- Portability : unportable +-- +-- This module provides an interface to locale information e.g. for DateL +-- +----------------------------------------------------------------------------- + +module Localize + ( setupTimeLocale, + getTimeLocale + ) where + +import Foreign.C +import qualified System.Locale as L + +#ifdef UTF8 +import Codec.Binary.UTF8.String +#endif + +-- get localized strings +type NlItem = CInt + +#include <langinfo.h> +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_7 \ + , DAY_1, DAY_7 \ + , ABMON_1, ABMON_12 \ + , MON_1, MON_12\ + } + +getLangInfo :: NlItem -> IO String +getLangInfo item = do + itemStr <- nl_langinfo item +#ifdef UTF8 + str <- peekCString itemStr + return $ decodeString str +#else + peekCString itemStr +#endif + +#include <locale.h> +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 :: 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/DateZone.hs b/src/Plugins/DateZone.hs index 4d5ce6a..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 localization 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/xmobar.cabal b/xmobar.cabal index 029dce8..39b64dc 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, |