tianbar 0.2.0.0 → 0.2.1.0
raw patch · 8 files changed
+253/−16 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.md +56/−0
- scripts/location_shim.js +20/−0
- scripts/time.js +34/−0
- scripts/weather.js +50/−0
- scripts/xmonad.js +31/−0
- src/System/Tianbar/WebKit.hs +28/−10
- src/System/Tianbar/XMonadLog.hs +28/−5
- tianbar.cabal +6/−1
+ README.md view
@@ -0,0 +1,56 @@+Tianbar+=======++Tianbar is a status bar for XMonad and possibly similar window managers. It is+using WebKit as its rendering engine, meaning that the entire look and feel is+customizable using HTML, CSS and JavaScript.++Usage+-----++Tianbar will show `index.html` from its [XDG configuration directory][xdg]+(usually `$HOME/.config/taffybar`). It it up to you to create that, add styles,+widgets and other behavior.++Widgets+-------++A small collection of widgets written in JavaScript is bundled with Tianbar,+see `scripts` directory. To include them on your page, use `tianbar:` URL+scheme, e.g. `tianbar:scripts/time.js`.++Currently widgets require [jQuery][jquery] and [RequireJS][requirejs], and+neither of those is distributed with Tianbar -- you will have to obtain them+manually.++XMonad integration+------------------++XMonad status widget works by listening on DBus for messages sent by the+provided `logHook`, see `System.Tianbar.XMonadLog` documentation for details.++Quirks+------++* AJAX requests from Tianbar are not subject to the same origin policy. This+ makes it easier to interact with various Web services. You can also make+ requests to the local files, for example, to extract CPU activity statistics+ from `/proc/stat`.+* HTML5 geolocation API does not work. A shim, which uses+ [freegeoip.net][freegeoip], is provided instead.+* Interaction with the displayed Web page is limited. For example, text fields+ are not active if there are other windows on the screen, and opening new+ windows does not work.++Acknowledgements+----------------++The project is essentially a fork of [Taffybar][taffybar], stripped down of+Haskell configuration and widgets and not yet having achieved functional parity+with it.++[freegeoip]: http://freegeoip.net/+[jquery]: http://jquery.com/+[requirejs]: http://requirejs.org/+[taffybar]: https://github.com/travitch/taffybar+[xdg]: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+ scripts/location_shim.js view
@@ -0,0 +1,20 @@+/*+ * Basic HTML5 geolocation shim.+ *+ * Requires 'jquery' to be available through RequireJS.+ */+define(['jquery'], function ($) {+ var my_geolocation;++ navigator.geolocation = {};+ navigator.geolocation.getCurrentPosition = function (cb) {+ if (my_geolocation) {+ cb(my_geolocation);+ } else {+ $.getJSON('http://freegeoip.net/json/').success(function (loc) {+ my_geolocation = { coords: loc };+ cb(my_geolocation);+ });+ }+ };+});
+ scripts/time.js view
@@ -0,0 +1,34 @@+/*+ * Clock plugin using Moment.js (http://momentjs.com/) to+ * format the time and date.+ *+ * The only exposed property, 'format', determines the+ * format (see Moment.js documentation) to display time and date.+ *+ * The plugin requires 'jquery', 'moment' and 'moment/lang' to be+ * available through RequireJS.+ */+define(['jquery', 'moment', 'moment/lang'], function ($, moment) {+ var config = {+ format: 'llll'+ };++ function updateClock() {+ var dt = moment();+ var clockText = dt.format(config.format);+ $('.widget-time').text(clockText);+ }++ $(document).ready(function () {+ var lang = navigator.language;+ if (moment.langData(lang)) {+ moment.lang(lang);+ } else {+ moment.lang(navigator.language.replace(/-.+/, ''));+ }+ updateClock();+ setInterval(updateClock, 1000);+ });++ return config;+});
+ scripts/weather.js view
@@ -0,0 +1,50 @@+/*+ * Weather plugin using Yahoo! Weather API.+ *+ * The plugin requires 'jquery' to be available through RequireJS.+ *+ * At least on webkit-0.12.4, geolocation needed by this plugin is not+ * functional, so location_shim.js is required to be loaded before.+ */+define(['jquery'], function ($) {+ var api_key = 'a54ebf597a8e77198d9a47c798d42c51';+ var woeid;++ function unescapeHTML(html) {+ return $('<span/>').html(html).text();+ }++ function updateWeather() {+ $.ajax('http://weather.yahooapis.com/forecastrss?' ++ 'w=' + woeid + '&u=c')+ .success(function (weather) {+ var temp = $('condition', weather).attr('temp');+ var units = $('units', weather).attr('temperature');+ units = " °" + units;+ var forecast = $('forecast', weather).map(function (k, el) {+ el = $(el);+ return el.attr('day') + ": " + el.attr('text') + ", " ++ el.attr('low') + "–" + el.attr('high') ++ units;+ });+ forecast = Array.prototype.join.call(forecast, ' ');+ $('.widget-weather').html(temp + units);+ $('.widget-weather').attr('title', unescapeHTML(forecast));+ });+ }++ $(document).ready(function () {+ navigator.geolocation.getCurrentPosition(function (pos) {+ $.getJSON('http://query.yahooapis.com/v1/public/yql?q=' ++ 'select%20place.woeid%20from%20flickr.places%20where%20' ++ 'lat%3D' + pos.coords.latitude + '%20and%20' ++ 'lon%3D' + pos.coords.longitude + '%20and%20' ++ 'api_key=%22' + api_key + '%22&format=json')+ .success(function (yloc) {+ woeid = yloc.query.results.places.place.woeid;+ updateWeather();+ setInterval(updateWeather, 5 * 60 * 1000);+ });+ });+ });+});
+ scripts/xmonad.js view
@@ -0,0 +1,31 @@+/*+ * XMonad status plugin, receiving workspace status over DBus.+ * To send status, use dbusLog or dbusLogWithMarkup from+ * System.Tianbar.XMonadLog as your XMonad logHook.+ *+ * The status appears in elements matching class 'widget-xmonad'.+ *+ * The plugin requires 'jquery' to be available through RequireJS.+ */+define(['jquery'], function ($) {+ function setStatus(st) {+ $('.widget-xmonad').html(st);+ }++ // Currently, a check for this function (and if it doesn't exist,+ // window.XMonadStatus) is hardcoded in Tianbar. A better solution+ // would be to expose an interface for subscribing to DBus connections+ // from JavaScript.+ window.setXMonadStatus = function (st) {+ window.XMonadStatus = undefined;+ setStatus(st);+ };++ $(document).ready(function () {+ window.setTimeout(function () {+ if (window.XMonadStatus) {+ window.setXMonadStatus(window.XMonadStatus);+ }+ }, 1000);+ });+});
src/System/Tianbar/WebKit.hs view
@@ -20,15 +20,37 @@ import System.Tianbar.Configuration +import Paths_tianbar+ gsettingsGet :: String -> String -> IO String gsettingsGet schema key = do output <- readProcess "gsettings" ["get", schema, key] [] let len = length output return $ drop 1 $ take (len - 2) output -gsettingsPrefix :: String-gsettingsPrefix = "gsettings:"+type UriOverride = String -> Maybe (IO String) +withPrefix :: String -> (String -> IO String) -> UriOverride+withPrefix prefix func uri+ | prefix `isPrefixOf` uri = Just $ func $ drop (length prefix) uri+ | otherwise = Nothing++gsettingsUriOverride :: UriOverride+gsettingsUriOverride = withPrefix "gsettings:" $ \path -> do+ let [schema, key] = splitOn "/" path+ setting <- gsettingsGet schema key+ return $ "data:text/plain," ++ setting++dataFileOverride :: UriOverride+dataFileOverride = withPrefix "tianbar:" $ \path -> do+ liftM ("file://" ++) $ getDataFileName path++uriOverrides :: [UriOverride]+uriOverrides = [gsettingsUriOverride, dataFileOverride]++allOverrides :: UriOverride+allOverrides = foldr mplus Nothing . flip map uriOverrides . flip ($)+ setupWebkitLog :: WebView -> IO () setupWebkitLog wk = do let matcher = matchAny { matchSender = Nothing@@ -45,15 +67,11 @@ _ <- on wk resourceRequestStarting $ \_ _ nreq _ -> case nreq of Nothing -> return () (Just req) -> do- uri_ <- networkRequestGetUri req- case uri_ of+ uri <- networkRequestGetUri req+ let override_ = uri >>= allOverrides+ case override_ of Nothing -> return ()- Just uri -> when (gsettingsPrefix `isPrefixOf` uri) $ do- let path = drop (length gsettingsPrefix) uri- let [schema, key] = splitOn "/" path- setting <- gsettingsGet schema key- networkRequestSetUri req $- "data:text/plain," ++ setting+ (Just override) -> override >>= networkRequestSetUri req htmlFile <- getUserConfigFile appName "index.html" html <- readFile htmlFile
src/System/Tianbar/XMonadLog.hs view
@@ -1,3 +1,14 @@+-- | A hook for XMonad window manager to send updates to the+-- corresponding Tianbar widget.+--+-- You must include tianbar:scripts/xmonad.js in Tianbar configuration to+-- receive the updates.+--+-- A "Renderer" can be used to fully customize the output. A renderer is a+-- function receiving all the status information and returning HTML+-- which will be displayed in the corresponding element of the status bar.+--+-- For convenience, a renderer returning 'Markup' can be used as well. module System.Tianbar.XMonadLog ( dbusLog , dbusLogWithMarkup , dbusLogWithRenderer@@ -23,24 +34,29 @@ import XMonad.Util.NamedWindows import XMonad.Util.WorkspaceCompare --- | A DBus-based logger with a default pretty-print configuration-dbusLog :: Client -> X ()-dbusLog client = dbusLogWithMarkup client tianbarMarkup- sig :: Signal sig = signal (fromJust $ parseObjectPath "/org/xmonad/Log") (fromJust $ parseInterfaceName "org.xmonad.Log") (fromJust $ parseMemberName "Update") +-- | Workspace information. data WindowSpaceInfo = WindowSpaceInfo { wsTag :: String+ -- ^ workspace tag , wsCurrent :: Bool+ -- ^ whether the workspace is current , wsHidden :: Bool+ -- ^ whether the workspace is hidden , wsUrgent :: Bool+ -- ^ whether the workspace has any+ -- urgent windows , wsEmpty :: Bool+ -- ^ whether the workspace is empty+ -- (has no windows) } +-- | A function to format the status information. type Renderer a = String -- ^ layout description- -> String -- ^ window title+ -> String -- ^ active window title -> [WindowSpaceInfo] -- ^ workspaces -> [Window] -- ^ urgent windows -> WindowSet -- ^ all windows@@ -48,6 +64,11 @@ type MarkupRenderer = Renderer Markup +-- | Tianbar logger with a default renderer.+dbusLog :: Client -> X ()+dbusLog client = dbusLogWithMarkup client tianbarMarkup++-- | Tianbar logger with a renderer emitting a string. dbusLogWithRenderer :: Client -> Renderer String -> X () dbusLogWithRenderer client renderer = do winset <- gets windowset@@ -69,11 +90,13 @@ let html = renderer ld wt (map wsinfo ws) urgents winset liftIO $ emit client sig { signalBody = [ toVariant html ] } +-- | Tianbar logger with a Blaze renderer. dbusLogWithMarkup :: Client -> MarkupRenderer -> X () dbusLogWithMarkup client renderer = dbusLogWithRenderer client renderer' where renderer' ld wt wksp urgent winset = renderMarkup $ renderer ld wt wksp urgent winset +-- | Default Tianbar renderer. tianbarMarkup :: MarkupRenderer tianbarMarkup layout title workspaces _ _ = do H.span ! A.class_ (toValue "workspaces") $
tianbar.cabal view
@@ -1,5 +1,5 @@ name: tianbar-version: 0.2.0.0+version: 0.2.1.0 synopsis: A desktop bar based on WebKit description: A desktop bar using WebKit for rendering as much as possible.@@ -12,6 +12,11 @@ category: System build-type: Simple cabal-version: >=1.10+data-files: README.md+ , scripts/location_shim.js+ , scripts/time.js+ , scripts/weather.js+ , scripts/xmonad.js executable tianbar default-language: Haskell2010