Org-mode Conky Colorizer Sunday, June 5th 2011
Just whipped up a little script to colorize my org-mode todo lists for display via Conky. It's bound to be of use to someone so I thought I'd better share :)

Here's a screenshot of it in action, sitting in the corner of my desktop.
http://i.imgur.com/mqYUGs.jpg

Source is below, to use, place ${execp /path/to/org-conky-parser.scm 30} in to your conkyrc. Requires Chicken Scheme, and remember to chmod +x the script first.

#!/usr/bin/csi -script
;; org-conky-parser.scm
;; Run an org-mode file through some regexes and output colors
;; Suitable for Conky.

; File to read, could be easily grabbed from argv
(define *file* "~/org/day.org")
(define *font* "Liberation Sans")

;; Code below

(use regex-literals)
(set-read-syntax! #\/ read-regex-literal)

(define ++ string-append)

(define (color c)
  (++ "${color " c "}\\1${color}"))

(define (font f)
  (++ "${font " f "}\\1${font}"))

(define *replace-list*
  (list
   (list /^(\*+)/      (color "#555555"))
   (list /(TODO)/      (color "#ffaa88"))
   (list /(DONE)/      (color "#aaff88"))
   (list /(TODO|DONE)/ (font (++ *font* ":style=bold:pixelsize=12")))
   (list /(<.*>)/      (color "#aaaaff"))
   (list /(<.*>)/      (font (++ *font* ":style=bold:pixelsize=14")))
   (list /(.*list.*)/  (font (++ *font* ":style=bold:pixelsize=16")))))

; Grab file contents into a list
(define *contents*
  (with-input-from-file *file* read-lines))

; Colorize a line using above regexes
(define (colorize-line line)
  (for-each ; Foreach regex/replacement
   (lambda (pair)
     (set! line (string-substitute (car pair) (cadr pair) line)))
   *replace-list*)
  line)

(define print-colorized-line (compose print colorize-line))

; Print colorized lines
(for-each print-colorized-line *contents*)
Comment on this Post
Adding FreeType to our Demo Sunday, June 5th 2011
Continuing on from my Chicken Scheme, and OpenGL tutorial, I'm going to show you how to extend it to render pretty FreeType text using the FTGL library. Follow the code below for details as always; it's really easy! :)

Users of ArchLinux can get FTGL with a simple sudo pacman -S ftgl. Debian should be something like sudo apt-get install libftgl-dev.

Alright lets start by loading up the code from last time ...

... and scrolling down to the "(inline .." call:

(inline #<<EOF
#ifndef CHICKEN
...
#endif

// Here we're going to add the new stuff for FTGL!

// Define a constant we're going to use later
const int FTGL_RENDER_ALL = 0xffff;

// And typedef FTGLfont as void so we can use it and pass it around
typedef void FTGLfont;

// Notice however that I didn't include the ftgl header, because I
// want to define just the functions we're going to use to make
// things even easier

FTGLfont* ftglCreatePixmapFont(const char*);

void ftglSetFontFaceSize(FTGLfont*, int, int);
void ftglRenderFont(FTGLfont*, const char*, int);
void ftglDestroyFont(FTGLfont*);

// The above are the only ones we will be using for now, but these
// ones below may also be useful, along with the SimpleLayout class

// Also possible to use ftglCreateTextureFont and
// render as a plain texture too! Using the same render call
//FTGLfont* ftglCreatePixmapFont(const char*);

//float ftglGetFontLineHeight(FTGLfont*);
//void ftglGetFontBBox(FTGLfont*, const char*, int, float*);

// Done!


... Now skip down to the EOF part:

EOF
"-lSOIL -lftgl" ; Notice here we have added -lftgl to be linked
)


... Now skip down to our old draw-text function, where we're going to replace the GLUT code with our new FTGL render code:

(define (draw-text text x y #!key (color '(1 1 1 1)))
  (apply gl:Color4f color)
  (gl:PushAttrib gl:ENABLE_BIT)
  (gl:Disable gl:TEXTURE_2D)
  (gl:RasterPos2f x y)
  ; This line has been replaced with a new one for FTGL
  ; FTGL even takes care of rendering for us!
  (ftglRenderFont font text FTGL_RENDER_ALL)
  (gl:PopAttrib))


... and down a bit further to where we loaded the texture last time:

(define texture (LoadGLTexture "circle_gradient.tga"))

; And add a new line for loading the font up
(define font (ftglCreatePixmapFont "pathtoyourfont.ttf"))
; with minimal error checking
(unless font
  (error "Couldn't load font!")
  (exit 1))

; now set the font size
(ftglSetFontFaceSize font 36 36)


... Nearly done! down to the last line now:

(glut:MainLoop)

; Add a call to destroy the font after we're done
(ftglDestroyFont font)


And that's it! Ah the joys of libraries and high level languages!
If all went well you should have sweet anti-aliased variable-pitch text in place of the standard GLUT stuff before :D Comment on this Post
More Practical Chicken Thursday, May 12th 2011
As I love sharing code on my blog, and I love Chicken Scheme, I'm going to share a couple of handy and practical features that I've made use of recently.

Anyone that has used C++ for longer than a few minutes has probably noticed that literal constants (numbers and such) often have a suffix attached to them. The most common place that you'll see this is when writing floating-point decimals, ie. 1.0f.

They might seem a little pointless at first, but they have their uses; I swear that I once read of a way to add your own types into the language too.

But anyway, I searched for a way to do this in Chicken too, and it turns out it's really easy (of course!). Chicken provides a function called set-parameterized-read-syntax! that can emulate this functionality quite nicely.

Here's a real world case that I used recently, I wanted to be able to convert from inches into pixels, based on a known DPI (in this case 180). The code to set this up looks like this:

; This lets you type #12i anywhere in your code and have it replaced with 2160
(set-parameterized-read-syntax #\i (lambda (port n) (* n 180)))


Yeah that's really it, isn't Scheme wonderful :P

The other really useful feature is the regex-literals egg (download it with sudo chicken-install regex-literals), which gives Chicken Scheme the ability to use Ruby/Perl/Javascript style literal regexes; well almost, it allows you to type #/myregexhere/i (notice the leading #) and it will be converted into a regexp object. Luckily we can even take this a step further and remove the hash at the front. Code time!

; Import the egg first of all
(use regex-literals)

; Lucky for us, regex-literals provides us the function we need to read
; a full regex literal from a Scheme port, so all we have to do is just
; hook it up to the "/" character and it will work as expected!
(set-read-syntax! #\/ read-regex-literal)

; Now we can write inline regex with a familiar syntax <b>:D</b>
(pp (string-match /.*match[A-Za-z]+me.*/i "hello match world me <b>:D</b>"))


I know this a measly amount of code to be posting an entry for, but I hope that both of these features (among others) demonstrate just how practical Chicken Scheme can be in many situations, and shows that you don't always have to write a large amount of code to get cool things done! Mint! Comment on this Post
Org-agenda-sms.el Thursday, May 12th 2011
So my warmup for today was to rewrite my old org-mode agenda notification code to use Emacs lisp instead of Python.
The aim of this code is to check your org-mode agenda for any headings with DEADLINEs and create a vcalendar for each, and then send them to your phone via Clickatell.

To use it, save the code into your Emacs lib path, and then in your .emacs you'll want something like:

(require 'org-agenda-sms)

(setq org-agenda-sms-username "")
(setq org-agenda-sms-password "hunter2")
(setq org-agenda-sms-api-key "")
(setq org-agenda-sms-phone "")

(run-at-time "7am" nil 'org-agenda-sms)


The contents of org-agenda-sms.el is below:

;;
;; Org-agenda-sms.el
;; Allows Emacs to SMS you a vcalendar of appointments each day
;; Written by Zane Ashby (http://www.demonastery.org)
;;
;; Usage: (run-at-time "07am" nil 'org-agenda-sms)
;;

(defvar org-agenda-sms-username nil "Clickatell username for SMS")
(defvar org-agenda-sms-password nil "Clickatell password for SMS")
(defvar org-agenda-sms-api-key nil "Clickatell API key for SMS")
(defvar org-agenda-sms-phone nil "Phone number for SMS")

;;;###autoload
(defun org-agenda-sms-build-vcal (header timestamp)
  "Builds a vcalendar from a header and timestamp"
  (let ((vcal-template "BEGIN:VCALENDAR
VERSION:1.0
BEGIN:VEVENT
CATEGORIES:APPOINTMENT
DTSTART:%s
DTEND:%s
SUMMARY:%s
DESCRIPTION:%s
END:VEVENT
END:VCALENDAR"
)
        (time (format-time-string "%Y-%m-%d %H%M"
               (apply 'encode-time (org-parse-time-string timestamp)))))
    (format vcal-template time time header header)))

;;;###autoload
(defun org-agenda-sms-send (text &optional type)
  "Send an SMS vcalendar provided by \"text\""
  (let* ((text (url-hexify-string text))
         (url-format "https://api.clickatell.com/http/sendmsg?user=%s&password=%s&api_id=%s&to=%s&msg_type=%s&text=%s")
         (url (format url-format org-agenda-sms-username org-agenda-sms-password org-agenda-sms-api-key org-agenda-sms-phone (if type type "SMS_NOKIA_VCAL") text)))
    (message "Retrieving api.clickatell.com/http/sendmsg..")
    (url-retrieve-synchronously url)))

;;;###autoload
(defun org-agenda-sms ()
  "Check for appointments in org-agenda and SMS as vcalendar to phone"
  (org-map-entries
   (lambda ()
     (let ((heading (clean-org-heading (nth 4 (org-heading-components))))
           (props (org-entry-properties)))
       (cond
        ((assoc "DEADLINE" props)
         (org-agenda-sms-send (org-agenda-sms-build-vcal heading (cdr (assoc "DEADLINE" props)))))
        ((assoc "SCHEDULED" props)
         (org-agenda-sms-send (org-agenda-sms-build-vcal heading (cdr (assoc "SCHEDULED" props)))))
        ((assoc "TIMESTAMP" props)
         (org-agenda-sms-send (org-agenda-sms-build-vcal heading (cdr (assoc "TIMESTAMP" props))))))))
   "TIMESTAMP<=\"<+1d>\"|DEADLINE<=\"<+1d>\"|SCHEDULED<=\"<+1d>\""
   'agenda))

(provide 'org-agenda-sms)


Seems to work for me, but as always your mileage may vary ;)
Comment on this Post
FileTools C++ Class Sunday, May 8th 2011
Here is the source for the FileTools C++ Class promised a few posts back, which uses inotify to monitor files for changes.

Again we start off with the class header:

// FileTools.cpp

#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>

typedef class FileTools {
public:
    static int addWatch(char *, ...);
    static void removeWatch(int);
    static bool hasChanged(int);

private:
    static int fd;
} *pFileTools;

// Parse variable arguments into 'buffer' character array
// This is just a macro I use often in my functions
#define parsevargs(buff, buffer)                    \
        char buffer[128];                               \
        memset(buffer, 0, sizeof(buffer));              \
        va_list ap;                                     \
        va_start(ap, buff);                             \
        vsnprintf(buffer, sizeof(buffer), buff, ap);    \
        va_end(ap);


And on to the implementation:

int FileTools::fd = 0;

int FileTools::addWatch(char *path, ...)
{
    // Parse variable arguments into "buffer"
    parsevargs(path, buffer);

    // Initialize inotify if need be
    if (!FileTools::fd) FileTools::fd = inotify_init();

    printf("Adding Watch for %s..\n", buffer);

    // Return a new watch handle
    return inotify_add_watch(FileTools::fd, buffer, IN_CLOSE_WRITE);
}

void FileTools::removeWatch(int wd)
{
    printf("Removing Watch id = %i..\n", wd);
    inotify_rm_watch(FileTools::fd, wd);
}

#define EVENT_SIZE (sizeof(struct inotify_event))
#define BUF_LEN    (1024 * (EVENT_SIZE + 16))
bool FileTools::hasChanged(int wd)
{
    bool ret = false;
   
    // Return from select immediately if none available
    struct timeval time;
    time.tv_sec = 0;
    time.tv_usec = 0;
    fd_set rfds;

    FD_ZERO(&rfds);

    // Set up our fd_set with our inotify fd
    FD_SET(FileTools::fd, &rfds);

    // Do the select
    select(FileTools::fd + 1, &rfds, NULL, NULL, &time);

    if (FD_ISSET(FileTools::fd, &rfds)) {
        int length = 0;
        int i = 0;
        char buffer[BUF_LEN];

        length = read(FileTools::fd, buffer, BUF_LEN);

        while (i < length) {
            // Got a match
            struct inotify_event *event = (struct inotify_event*)&buffer[i];

            if (event->wd == wd &&
                event->mask & IN_CLOSE_WRITE) {
                // It was a file we were monitoring!
                printf("Watched file %i has changed\n", wd);
                ret = true;
            }

            i += EVENT_SIZE + event->len;
        }
    }

    return ret;
}


And that's it! Use to your hearts content, this code and the CodeTools code before it are free to use for whatever purpose you want.

Sorry for the short post, but I want to post more Scheme (and maybe PHP) instead of cluttering up my blog with C++ ;) Comment on this Post
CodeTools C++ Class Saturday, May 7th 2011
As promised a couple of posts back, I will present a C++ class to compile some arbitrary code using GCC and load it into memory.

The code is pretty simple, we start off with the class header:

// CodeTools.hpp

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

typedef class CodeTools {
public:
    static bool compileString(char*, bool (*callback)(void*));
    static bool compileFile(char*, bool (*callback)(void*));

private:
} *pCodeTools;


And then on to the compileString method. This method actually just wraps compileFile to avoid code duplication, so it's really just taking in a string and writing it to a temporary file before calling compileFile.

Here we go:

// CodeTools.cpp

bool CodeTools::compileString(char* code, bool (*callback)(void*))
{
    // Generate a temporary file name
    // (There are better ways to do this!)
    char temp[256];
    sprintf(temp, "codetools_XXXXXX");
    char* tmppath = mktemp(temp);

    // Open temporary file
    FILE* fp = fopen(tmppath, "wb");

    if (!fp) {
        fprintf(stderr, "Could not open temporary path %s\n", tmppath);
        return false;
    }

    // Write out string
    fwrite(code, strlen(code), sizeof(char), fp);
    fclose(fp);

    // Call out to compileFile method
    bool ret = compileFile(tmppath, callback);

    // Remove temporary file
    unlink(tmppath);

    return ret;
}


So again, just a small wrapper, which can be reimplemented to your liking.

Now for the part that does the actual work, this can be cleaned up plenty but seems pretty stable for me:

bool CodeTools::compileFile(char* path, bool (*callback)(void*))
{
    // Increments each time this function is called.
    // This is used for the .so path. If the .so path
    // doesn't change then our new functions won't
    // override the old ones.
    static int count = 0;

    // A buffer to hold our command line
    char buffer[256];
    memset(buffer, 0, sizeof(buffer));

    // The last path used
    char sopathLast[256];
    memset(sopathLast, 0 , sizeof(sopathLast));

    // The current path to use
    char sopath[256];
    memset(sopath, 0 , sizeof(sopath));

    sprintf(sopathLast, "./%s.%i.so", path, count - 1);
    sprintf(sopath, "./%s.%i.so", path, count++);

    // Please change modify these to your liking! These are what I use
    // for my livecoding playground
    sprintf(buffer, "g++ -shared -o %s -fPIC -fno-use-cxa-atexit -xc++ -include src/Global.hpp %s -Isrc -I/usr/include/freetype2", sopath, path);

    // Call it!
    int ret = system(buffer);

    if (ret != 0) {
        fprintf(stderr, "Error in compilation: g++ returned %i\n", ret);
        return false;
    }

    // Cool, compile was successful!

    // Now, try to get a handle to the last opened .so so we can close it
    void* handle = dlopen(sopathLast, RTLD_LAZY | RTLD_NOLOAD);
    if (handle) {
        fprintf(stderr, "Found current handle %s, closing first\n", sopathLast);
        dlclose(handle);
    }

    // Open the new .so, LAZY load symbols for speed
    handle = dlopen(sopath, RTLD_LAZY);

    if (!handle) {
        fprintf(stderr, "Could not load compiled file into memory: %s\n", dlerror());
        unlink(sopath);
        return false;
    }

    printf("Loaded %s\n", sopath);

    // Remove temporary .so
    unlink(sopath);

    // Call the user supplied callback passing the .so handle to it
    // From there it can load individual functions.
    return callback(handle);
}


And done. This should be all the code needed to use the CodeTools sample from the C++ Eval? Hell yes. post. Have fun! I will be posting the FileTools class shortly too. Comment on this Post