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