Saturday, November 15, 2008

Perl Gtk2::StatusIcon example

I had the need to add a status icon in the systray, enhancing the functionality of a web application. My needs are a little more complex than displaying a simple menu, but the problem was that you can't find many examples for scripting languages, like Perl, especially with StatusIcon.

The beautiful thing is that Gtk+ bindings try not to diverge too much from the main API, although some of them add useful extensions.

So I found this PyGtk example, converting it to Perl:
http://marcin.af.gliwice.pl/if-then-else-20070121143245.

#!/usr/bin/env perl
use strict;
use warnings;

use Gtk2 -init;

sub quit_cb {
my ($widget, $status_icon) = @_;

$status_icon->set_visible(0) if $status_icon;
Gtk2->main_quit();
}

sub popup_menu_cb {
my ($widget, $button, $time, $menu) = @_;

if ($button == 3) {
my ($x, $y, $push_in)
= Gtk2::StatusIcon::position_menu($menu, $widget);

$menu->show_all();
$menu->popup( undef, undef,
sub{return ($x,$y,0)} ,
undef, 0, $time );
}
}

sub activate_icon_cb {
my $msgBox = Gtk2::MessageDialog->new(undef,
'GTK_DIALOG_MODAL',
'GTK_MESSAGE_INFO',
'GTK_BUTTONS_OK',
"Status Icon example!");
$msgBox->run();
$msgBox->destroy();
}

my $status_icon = Gtk2::StatusIcon->new_from_stock('gtk-home');

my $menu = Gtk2::Menu->new();
my $menuItem = Gtk2::ImageMenuItem->new_from_stock("gtk-about");
$menuItem->signal_connect('activate', \&activate_icon_cb);
$menu->append($menuItem);

$menuItem = Gtk2::ImageMenuItem->new_from_stock('gtk-quit');
$menuItem->signal_connect('activate', \&quit_cb, $status_icon);
$menu->append($menuItem);

$status_icon->set_tooltip("StatusIcon test");
$status_icon->signal_connect('activate', \&activate_icon_cb);
$status_icon->signal_connect('popup-menu', \&popup_menu_cb, $menu);
$status_icon->set_visible(1);

Gtk2->main();

~

Sunday, November 9, 2008

Django - url tags for persistent GET parameters

I've been working on a project based on Django recently. The project was already established, and it's using Django version 0.96.

In the project's reporting interface I needed lots of filters to be passed around from the reports to the logs viewer. I also needed pagination on queries made by hand (i.e. not using django's models) ... just to give a little background. I'm not really proficient with Django, and there might be a better way to do this, but I wrote 2 tags that helped me dealing with persistence of GET parameters.

The code is posted here: http://www.djangosnippets.org/snippets/1175/

To install, you just drop the file in a "templatetags" directory, add the application to INSTALLED_APPS in settings, and in the template you have to include the templatetags file like so ...
{% load links %}
Usage is simple:
{% link_persist viewname arg1,arg2,kwarg1=value1,kwarg2=value2 %}
This tag has the same behavior as the normal url tag, with a couple of notable differences:
  • GET parameters are included in the resulting url
  • (key,value) arguments become GET arguments in the current url, overriding the value in the current request
  • if you specify a value to a key as an empty string, or as a None, that key will be excluded from the resulting url ... useful for not persisting a set of parameters that only make sens for the current url

The other tag:
{% link_add kwarg1=value1,kwarg2=value2... %}

This tag adds to the url in the address bar the values specified in the list of named arguments. It has the same behavior as above, so for example, instead of adding to the current url, or replacing an existing value (useful for pagination) you can also remove parameters from the current URL.

~

Saturday, November 8, 2008

Emacs - TextMate like snippets

I love Emacs, and while I'm no guru, I know my way around it.

At Adobe I had the option of using a MacBook Pro, so naturally, being a dynamic languages freak I've had the opportunity of experimenting with Textmate, as all the cool kinds use it in screencasts.

The coolest feature of Textmate is its intuitive and powerful snippets mechanism. The syntax is easy to understand and use and with it you can automate boring boilerplate code. If you don't know what I mean, take a look at the screencasts from rubyonrails.org. So yeah, I felt jelousy that my favorite text editor, Emacs, doesn't have it.

But then I found this wonderful Emacs plugin: Yasnippet. You can also watch a YouTube introductory screencast to whet your appetite. It uses the same Textmate syntax, with a notable difference: for text filters you can use elisp syntax.

Installing it is easy ... just download the latest version, extract the files to your "site-lisp" directory, which usually is "~/.emacs.d/site-lisp" on Linux. If you cannot find your "site-lisp" directory, just create one in "emacs.d/site-lisp" (or whatever) and add this line to your ".emacs" configuration file:
(setq load-path (cons "~/emacs.d/site-lisp" load-path))
Then you need to add to the same ".emacs" configuration file this line:
(require 'yasnippet)
(yas/initialize)
(yas/load-directory "~/emacs.d/site-lisp/snippets")
Be careful to change the specified directory ("~/emacs.d/site-lisp/snippets") to match your own setup.

Defining snippets is easy. It implies creating for every snippet a file containing specific syntax. Snippets are context-dependent ... you can define snippets that only work in html-mode, or only in java-mode (as in Textmate). Editing modes in Emacs have an inheritance model, as in ... java-mode inherits cc-mode, which in turn inherits text-mode. The "snippets" directory has a similar structure, so if you want to define a snippet for java-mode, you can define it in "cc-mode" and it will be inherited by all derived modes, like c++-mode and java-mode, or you can define it for java-mode.

To take an example, to define a snippet named "bean" for java-mode, you need to edit the file "snippets/text-mode/cc-mode/java-mode/bean". And when you'll type "bean" with a TAB following, it will expand. Such a snippet could have the following syntax:
private ${2:String} ${1:varname};

public void set${1:$(upcase-initials text)}(${2:String} new${1:$(upcase-initials text)}) {
${1:fieldName} = new${1:$(upcase-initials text)};
}

public ${2:String} get${1:$(upcase-initials text)}() {
return ${1:fieldName};
}

${N} is a hole in the snippet where you can type text. It can have a default, and you can also have filters for the typed text, by using elisp functions, as in the above example where the typed text for the variable name has the initial upper-cased (according to Java conventions).

Now for my next problem: I'm experimenting with Catalyst web-framework, which uses by default the Template Toolkit. I don't mind using html-mode for editing TT files, but it's a problem for snippets because I used and will use lots of other template managers with html-mode, so snippets names may clash, and I don't want to prefix the names I use for snippet-expansion.

But emacs is wonderful right? So why not define our own editing mode, inherited from html-mode?

To create an inherited mode from html-mode, I created a file named "site-lisp/template-toolkit-mode.el" with the following code:
;; specifies that this script provides an emacs module
(provide 'template-toolkit-mode)

;; defines a derived editing mode, inheriting from html-mode
(define-derived-mode template-toolkit-mode html-mode "Template Toolkit2" nil)
And in our ".emacs" configuration file we can initialize this mode automatically for files ending with ".tt" (the file extension):
(autoload 'template-toolkit-mode "template-toolkit-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.tt$" . template-toolkit-mode))
That's it. Now we can define snippets only for template-toolkit file types. For example this is a snippet creating a foreach loop:
[% FOREACH ${1:item} IN ${2:items} %]
$0
[% END -%]
Btw, if your interested in my emacs configuration (nothing special about it, but may give you some hints), you can find it here: http://code.google.com/p/my-emacs-d/

Enjoy ~