El Wed, Mar 04, 2009 at 11:39:17PM +0100, xscript ens deleit� amb les seg�ents paraules: > Ok, here's my try (see attachment).
Forget about last one. This has improved soon/future detection (last was miserably broken). Hope it's useful. apa! -- "And it's much the same thing with knowledge, for whenever you learn something new, the whole world becomes that much richer." -- The Princess of Pure Reason, as told by Norton Juster in The Phantom Tollbooth
---------------------------------------------------------- -- @author Lluis Vilanova <[email protected]> -- @copyright 2009 Lluis Vilanova, licensed under the GPLv2 -- -- Based on: -- * org-awesome by Damien Leone -- * Code by Tassilo Horn ---------------------------------------------------------- -- Usage: -- -- Create the widget: -- require("orgmode") -- w_orgmode = orgmode.new(...) -- -- Add this to your emacs' configuration file in order to regenerate the agenda -- file whenever you write an org-mode file: -- ;; Export the current agenda whenever we update one of its files -- (setq th-org-agenda-file "~/.emacs.d/org-agenda.txt") -- ;; do it whenever I change and save an org file -- (defun th-org-mode-init () -- (add-hook 'after-save-hook 'th-org-update-agenda-file t t)) -- (add-hook 'org-mode-hook 'th-org-mode-init) -- ;; export function -- (defun th-org-update-agenda-file (&optional force) -- (save-excursion -- (save-window-excursion -- (let ((file th-org-agenda-file)) -- (org-agenda-list) -- (org-write-agenda file))))) -- ;; do it once at startup -- (th-org-update-agenda-file t) -- -- Some helpful configurable values: -- edit root directory where I store all my org-mode files -- launch = "emacs ~/plans/" -- for some unknown reason, emacs in batch mode _needs_ to know its config file -- force = "emacs -l ~/.emacs.d/init.el -batch" -- Global environment local os = os local io = io local table = table local string = string local tonumber = tonumber local widget = widget local button = button local awful = awful local naughty = naughty -- Module declaration module("orgmode") -- TODO: this should overload widget's attributes -- TODO: we can only have one orgmode widget (more could allow for multiple different views), but this is not checked local config = { } local function close () if config.note ~= nil then naughty.destroy(config.note) config.note = nil end end local function open () close() -- TODO: does not seem necessary... if config.text == nil then return end -- TODO: there's too much vertical empty space... config.note = naughty.notify({ title = config.title, text = config.text, timeout = config.timeout, hover_timeout = config.hover_timeout, width = config.width, position = config.position, }) end local function colorize (text, color) return "<span color='" .. color .. "'>" .. text .. "</span>" end local function parse () config.text = nil config.count.past = 0 config.count.today = 0 config.count.soon = 0 config.count.future = 0 local fd = io.open(config.agenda, "r") if not fd then return end local text = "" -- %d always uses two digits local today = os.date("^%A *%d %B %Y"):gsub("\*0+", "*") local when = -1 -- <0: past 0: today >0: future for l in fd:lines() do -- check if we're processing today if l:find("^%w") then if l:find(today) then when = 0 elseif when >= 0 then when = when + 1 end end -- TODO: escape '<' symbol (otherwise pango gets confused) if when == 0 then -- TODO: are counts always in days? ('In <num> d.:') if l:find("^ [^:]*: *Sched. *%d+x:") or l:find("^ [^:]*: *In *-%d+ d\.:") then l = colorize(l, config.color.past) config.count.past = config.count.past + 1 elseif l:find("^ [^:]*: *In *%d+ d\.:") then local in_days = l:match("^ [^:]*: *In *(%d+) d\.:") if tonumber(in_days) <= config.soon then l = colorize(l, config.color.soon) config.count.soon = config.count.soon + 1 else l = colorize(l, config.color.future) config.count.future = config.count.future + 1 end elseif l:find("^ [^:]*: *Deadline:") or l:find("^ [^:]*: *Scheduled:") then l = colorize(l, config.color.today) config.count.today = config.count.today + 1 end elseif when > config.soon then if l:find("^ [^:]*: *Deadline:") or l:find("^ [^:]*: *Scheduled:") then l = colorize(l, config.color.future) config.count.future = config.count.future + 1 end elseif when > 0 then if l:find("^ [^:]*: *Deadline:") or l:find("^ [^:]*: *Scheduled:") then l = colorize(l, config.color.soon) config.count.soon = config.count.soon + 1 end end if config.todo and when >= 0 then l = l:gsub(" TODO ", colorize(" TODO ", config.color.past)) end text = text .. l .. "\n" end fd:close() config.text = "<tt>"..text.."</tt>" end local function update () parse() if config.text == nil then return end local format = config.format format = string.gsub(format, "$past" , colorize(config.count.past , config.color.past )) format = string.gsub(format, "$today" , colorize(config.count.today , config.color.today )) format = string.gsub(format, "$soon" , colorize(config.count.soon , config.color.soon )) format = string.gsub(format, "$future", colorize(config.count.future, config.color.future)) config.widget.text = format end --- Create an orgmode widget (a textbox) -- Shows the specified information when the mouse enters the widget region -- -- Bindings: -- * mouse 1 : launch external program -- * mouse 2 : launch external program that forces an 'agenda' update -- * mouse 3 : update orgmode information -- -- @param opts Table with extra options for the widget: -- update : seconds between updates -- default: 600 -- launch : program to run on 'mouse 1' -- default: none (string) -- force : program to run on 'mouse 2' -- default: none (string) -- agenda : file with org-mode agenda information to show -- default: "~/.emacs.d/org-agenda.txt" -- title : see naughty -- default: "Agenda for this week:" -- format : widget's text format -- supports: -- * $past -- * $today -- * $soon -- * $future -- default: "$past/$today/$soon/$future" -- soon : number of days in the future for "soon" (higher is future) -- default: 3 -- todo : highlight the TODO word -- default: true -- color_* : colors for 'format' types -- align : widget's alignment -- default: "right" -- timeout : see naughty -- default: 0 -- hover_timeout: see naughty -- default: 0 -- width : see naughty -- default: 600 -- position : see naughty -- default "top_right" -- @return The new orgmode widget function new(opts) local align = opts and opts.align or "right" local tupdate= opts and opts.update or 600 config.widget = nil -- TODO: triggers previous widget's destruction? config.widget = widget({ type = "textbox", name = "orgmode", align = align }) local b = { } if opts and opts.launch then table.insert(b, button({ }, 1, function () awful.util.spawn(opts.launch) end)) end if opts and opts.force then table.insert(b, button({ }, 2, function () os.execute(opts.force) close() update() open() end)) end table.insert(b, button({ }, 3, function() update() close() open() end)) config.widget:buttons(b) config.widget.mouse_enter = open config.widget.mouse_leave = close awful.hooks.timer.register(tupdate, update) config.note = nil config.count = { } -- locations config.agenda = opts and opts.agenda or os.getenv("HOME").."/.emacs.d/org-agenda.txt" -- appearance config.title = opts and opts.title or "Agenda for this week:" config.format = opts and opts.format or "$past/$today/$soon/$future" config.soon = opts and opts.soon or 3 config.todo = opts and opts.todo or true -- TODO: maybe we could reuse some colors from 'beautify'... config.color = { } config.color.past = opts and opts.color_past or "#FF0000" config.color.today = opts and opts.color_today or "#DED200" config.color.soon = opts and opts.color_soon or "#00D225" config.color.future = opts and opts.color_future or "#00921A" -- naughty config.timeout = opts and opts.timeout or 0 config.hover_timeout = opts and opts.hover_timeout or 0 config.width = opts and opts.width or 600 config.position = opts and opts.position or "top_right" config.title = config.title .. " " .. colorize("past", config.color.past) .. " " .. colorize("today", config.color.today) .. " " .. colorize("soon", config.color.soon) .. " " .. colorize("future", config.color.future) update() return config.widget end
