Showing posts with label tips. Show all posts
Showing posts with label tips. Show all posts

2014-01-05

Remote notifications

This post explains how to get notifications (libnotify) from a remote system. Typically this is useful with an IRC client accessible through SSH.

Prerequisites:
  • A notification daemon! (dunst, xfce4-notifyd, etc.)
  • socat
  • notify-send
apt-get install socat libnotify-bin

On the client, modify the SSH configuration to introduce two elements:
  • forward a TCP port,
  • execute a local command.

Example entry for ~/.ssh/config:
Host remote-host
    Hostname remote-host.gandi.net
    RemoteForward 12000 localhost:12000
    PermitLocalCommand yes
    LocalCommand socat -u tcp4-listen:12000,reuseaddr,fork,bind=127.0.0.1 exec:$HOME/.local/bin/notify-remote.sh 2>/dev/null &
The fowarded TCP port will be used to netcat notification messages to the local system.

socat is used to bind a port on the local system, it will take the notifcation messages, and write them to the executed shell script notify-remote.sh.

The shell script will then simply call notify-send to display a notification with the default notification daemon.

notify-remote.sh:
#!/bin/sh
delay="5000"

read line
summary="$line"
read line
msg="$line"
read line

if [ "$line" = "" ] && [ "$summary" != "" ]; then
  [ -x "$(which notify-send)" ] && notify-send -u critical -t "$delay" -- "$summary" "$msg"
fi

Now it is possible to connect to the remote host and "write" notifications:
local$ ssh remote-host
remote-host$ echo -e 'Summary\nBody\n\n' | nc 127.0.0.1 12000

Integrate into irssi


Copy the irssi script available bellow to get notifications from hilights, and private messages.

Once the script is copied, execute /script load rnotify.pl inside irssi.

~/.irssi/scripts/autorun/rnotify.pl:
# shamelessly copied from http://git.esaurito.net/?p=godog/bin.git;a=blob;f=rnotify.pl
use strict;
use Irssi;
use HTML::Entities;
use vars qw($VERSION %IRSSI);

$VERSION = "0.01";

%IRSSI = (
    authors     => 'Luke Macken, Paul W. Frields',
    contact     => 'lewk@csh.rit.edu, stickster@gmail.com',
    name        => 'rnotify',
    description => 'Use libnotify to alert user to hilighted messages',
    license     => 'GNU General Public License',
    url         => 'http://lewk.org/log/code/irssi-notify',
);

Irssi::settings_add_str('misc', $IRSSI{'name'} . '_port', '12000');
Irssi::settings_add_bool('misc', $IRSSI{'name'} . '_if_away', 0);

sub is_port_owner {
    my ($port, $uid) = @_;
    my $wanted = sprintf("0100007F:%04X", $port);

    # XXX linux-specific
    open HANDLE, "< /proc/net/tcp" || return 0;
    while(<HANDLE>){
        #   sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
        my @splitted = split /\s+/;
        my $local = $splitted[2];
        my $remote = $splitted[3];
        my $uid = $splitted[8];

        return 1 if $local eq $wanted and $uid == $<;
    }
    close HANDLE;
    return 0;
}

sub notify {
    my ($server, $summary, $message) = @_;

    $message = HTML::Entities::encode($message);
    $summary = HTML::Entities::encode($summary);

    # echo \ escaping
    $message =~ s/\\/\\\\/g;
    $summary =~ s/\\/\\\\/g;

    my $port = Irssi::settings_get_str($IRSSI{'name'} . '_port');

    return if ! is_port_owner($port, $<);

    # check for being away in every server?
    return if $server->{usermode_away} &&
              (Irssi::settings_get_bool($IRSSI{'name'} . '_if_away') == 0);

    # XXX test for other means of doing TCP
    #print("echo '$summary\n$message\n\n' | /bin/nc 127.0.0.1 $port");
    system("echo '$summary\n$message\n\n' | /bin/nc 127.0.0.1 $port &");

    #my $pid = open(FH, "|-");
    #if( $pid ){
    #    print FH "$summary\n$message\n\n";
    #    close(FH) || warn "exited $?";
    #}else{
    #    exec("/bin/nc 127.0.0.1 $port") || warn "can't exec $!";
    #}
}

sub print_text_notify {
    my ($dest, $text, $stripped) = @_;
    my $server = $dest->{server};

    return if (!$server || !($dest->{level} & MSGLEVEL_HILIGHT));
    my $sender = $stripped;
    $sender =~ s/^\<.([^\>]+)\>.+/\1/ ;
    $stripped =~ s/^\<.[^\>]+\>.// ;
    my $summary = "Message on $dest->{target}";
    notify($server, $summary, $stripped);
}

sub message_private_notify {
    my ($server, $msg, $nick, $address) = @_;

    return if (!$server);
    notify($server, "Private message from ".$nick, $msg);
}

sub dcc_request_notify {
    my ($dcc, $sendaddr) = @_;
    my $server = $dcc->{server};

    return if (!$dcc);
    notify($server, "DCC ".$dcc->{type}." request", $dcc->{nick});
}

Irssi::signal_add('print text', 'print_text_notify');
Irssi::signal_add('message private', 'message_private_notify');
Irssi::signal_add('dcc request', 'dcc_request_notify');

# vim: et

2013-08-15

rndc retransfer failed: not found

I came accross the dummy error rndc: 'retranfer' failed: not found, with many unhelpful articles. If you run a rndc retranfer command, and get this error, make sure there is an entry for the zone on the slave, it may be helpful…

2013-07-02

Reorder network devices set by udev

In order to reorder network devices (e.g. swap eth1 with eth2), the persistent-net rules from udev can be edited. Usually there is a file at the following location:
/etc/udev/rules.d/70-persistent-net.rules
The file contains several rules, for example:
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="3c:ab:cd:00:ab:cd", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="3c:ab:cd:00:ab:ce", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"
By editing this file it is possible to change the NAME of each rule. After that, to reload the rules, simply issue this command:
udevadm control --reload-rules
Edit: you need to unload the modules first (modprobe -r e1000e for example), ensure the udev rules are reloaded, and load the modules back in. If the network drivers are built into the kernel, you need to reboot.

2013-05-18

Making use of custom actions with Xfce Appfinder

One addition in the latest versions of Appfinder was the custom actions. I never used it until after I started typing several times twitter which didn't work (a habit from the web browser url bar).

The custom actions can be useful for anything, and it's really quick to run it.

Examples of custom actions:
  • twitter: xdg-open https://twitter.com/
  • us: setxkbmap us
It can be very handy, check the online documention for a quick setup. There are also online examples, don't mind to leave a comment or to fill the bugtracker if you have clever ideas, I can add them, I just did with the setxkbmap us example ;-)

2012-12-23

Apache restart with Vim autocmd

In order to execute a command right after saving a file in Vim, you can use the :autocmd command. Here is a quick example how it can be useful with Apache files.

NB: on my system, Debian in this case, an Apache file is automatically recognized as filetype=apache.

augroup apache
    autocmd BufWritePost */sites-enabled/* !/etc/init.d/apache2 restart
augroup END

2012-07-30

Vim and Vala

I once wrote a quick note about Vala and Vim (or Vim and Vala) and the use of the Tag List plugin. Here is a clean post about these two beasts.

Vim — probably the best editor out there, at least always after trying out different editors I end up with Vim — has great plugins. However there is a lack of support for the Vala language. So here are two basic add-ins to include in the Vim editor.

Vala syntax

First there is no syntax color for this language. A quick fix is to use the C# syntax with the command :set filetype=cs. That works but is not ideal, ideal is to install a vala.syntax file, and there is one available on this GNOME Live! page.

First download the file from this page and save it under ~/.vim/syntax/. Next add the following lines to your ~/.vimrc file:
" Filetypes
augroup filetypedetect
        au! BufRead,BufNewFile *.vala,*.vapi setfiletype vala
augroup END

augroup vala
        autocmd BufRead *.vala,*.vapi set tw=100 efm=%f:%1.%c-%[%^:]%#:\ %t%[%^:]%#:\ %m
augroup END

Tag List

Tag List is a powerful plugin that lets you explore classes or functions from a source file, also called a source code browser. The installation steps are simple, they are also available bellow, and again to get it working with Vala there is a small hack to include inside the ~/.vimrc file.

First download the latest version of taglist from this page. Then uncompress the archive with, for example, the command line:
unzip -x taglist_45.zip -d $HOME/.vim/
Then go inside ~/.vim/doc, run Vim and inside Vim execute the command :helptags .:
cd ~/.vim/doc
vim
:helptags .
Finally add the following lines inside ~/.vimrc:
" Work-around Tag List for Vala
let tlist_vala_settings='c#;d:macro;t:typedef;n:namespace;c:class;'.
  \ 'E:event;g:enum;s:struct;i:interface;'.
  \ 'p:properties;m:method'

Now Vim is ready for Vala, and it's possible to browse source code by typing the command :TlistToggle.

Screenshot of Vim Vala Tag List
Vim Vala Tag List

2012-01-22

.screenrc

So I pimped up my .screenrc, and since it's been a long time I didn't care about my hardstatus I keep the content here just in case I need it again in a few years...

defscrollback 2048
startup_message off
caption always "%{= Wk}%-w%{= KW}%f%n %t%{-}%+w"
hardstatus off
hardstatus alwayslastline
hardstatus string "%{= ky}[ %H %l ]%=%{= kg}%{+b}[ %n %t ]%-=%{= ky}[ %D %d.%m.%Y %0c ]"

screen -t irssi 0
screen -t mutt 1
screen -t bubbie 2

2011-08-21

Xfce 4.8 with Conky

I have been following a short discussion on the IRC channel #xfce regarding an issue with the use of Conky and transparency. I didn't use Conky for a very long time, but since I knew it was possible to have Conky perfectly running, I gave it a shot again and since I did a fresh reinitialization of Xfce on my workstation, I tweaked the configuration file to my need. Now I have it running in the background and I'll most probably keep it.

The configuration I was able to get for a good working Conky window with transparency is bellow. Of course I could tell you which combination doesn't work, with the why, but since there are so many of them I simply put a working one.
own_window yes # create a separate XWindow over the one from Xfdesktop
own_window_type desktop # the window cannot be moved or resized
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager # make it behave like it belongs to the desktop
own_window_argb_visual yes # true transparency, a compositor has to be active
own_window_argb_value 100 # make the background semi-transparent
double_buffer yes # avoid flickering

Here is a screenshot of the desktop with Conky in the bottom right corner, I made sure there is some I/O activity going on :-)

Xfce with Conky
Now if you want you can steal my .conkyrc file.

2011-05-27

Changing PolicyKit settings per user

I have been hit twice by a required authentication on my workstation after the Wifi connection got lost and it is clearly irritating, especially when you are not around. The authentication requests are handled by PolicyKit (polkit for short) and can be tweaked.

The message by which I was hit was the following: "System policy prevents modification of network settings for all users."

Before you get started, the system wide configuration files that contain the default values reside inside the /usr/share/polkit-1/actions/ directory. In this directory resides the file org.freedesktop.NetworkManager.policy which contains all the default actions. It does also contain the message about the network settings for which the action id is "org.freedesktop.NetworkManager.settings.modify.system." At this point I was still clueless of what I was supposed to do.

After having search the web for information about PolicyKit I have found one interesting article that helped me getting done with my issue and learning more about this authorization framework. This action being very seldom to perform, I'm summing up everything here.

There are two useful commands to perform tests with PolicyKit, pkcheck and pkaction.

The first interesting command to use is pkcheck. It will trigger an authorization request and prompt you to type in a password, simply return true if no authorization is required otherwise false. For example:
pkcheck --action-id org.freedesktop.NetworkManager.settings.modify.system \
    --process `pidof gnome-session` -u `id -u`
You have to adapt the process and user parameters of course.



Next the command pkaction can be used to print the default system values, for example:
pkaction --action-id org.freedesktop.NetworkManager.settings.modify.system \
    --verbose
Now to have a custom setting for your user, what has to be done is to create a PolicyKit Local Authority file inside the directory /var/lib/polkit-1/localauthority/. Here is an example:
[Let user mike modify system settings for network]
Identity=unix-user:mike
Action=org.freedesktop.NetworkManager.settings.modify.system
ResultAny=no
ResultInactive=no
ResultActive=yes
I have saved this file under /var/lib/polkit-1/localauthority/50-local.d/10-network-manager.pkla.

There are three main values you can pass to ResultActive that are no, auth_admin or yes. Respectively it will deny the authorization, ask for a password, and give access. For further information about the possible values check the polkit manpage, also don't miss the pklocalauthority manpage to read more about the localauthority tree structure.

2011-01-23

Update the GeoIP database

GeoIP is a proprietary technology provided by MaxMind that allows the geolocalization of IPs. It provides databases as both free and paid solutions with IP records matching the country and the city. The GeoLite Country database can be downloaded for free and is updated about once a month.

The database can be used with the command line tool geoiplookup . By calling it, it will check for the default database, but you can specify another one through a command line option.

First download and install the latest database and license under your home directory, for example ~/.local/share/GeoIP/. Make sure to decompress the database with gunzip. The directory has to contain these files:
GeoIP.dat
LICENSE.txt
Next create an alias for the command geoiplookup, for example through your ~/.bashrc script put the following line:
alias geoiplookup='geoiplookup -d $HOME/.local/share/GeoIP/'

And done! But why all the hassle? Because your system may not provide the updates on a regular basis. Of course you can set up a scheduled task to download the database right into your home directory.

2010-10-23

XTerm as root-tail

The idea behind this title is to use XTerm as a log viewer over the desktop, just like root-tail works. The tool root-tail paints text on the root window by default or any other XWindow when used with the -id parameter.

Using XTerm comes with little advantage, it is possible to scroll into the “backlog” and make text selections. On a downside, it won't let you click through into the desktop, therefore it is rather useful for people without desktop icons for example.

We will proceed with a first simple example, by writing a Shell script that will use the combo DevilsPie and XTerm. The terminals will all be kept in the background below other windows and never take the focus thanks to DevilsPie. DevilsPie is a tool watching the creation of new windows and applies special rules over them.

Obviously, you need to install the command line tool devilspie. It's a command to run in the background as a daemon. Configuration files with a .ds extensions contain matches for windows and rules that are put within the ~/.devilspie directory.

First example

The first example shows how to match only one specific XTerm window.

The DevilsPie configuration:
DesktopLog.ds
(if
 (is (window_class) "DesktopLog")
 (begin
  (wintype "dock")
  (geometry "+20+45")
  (below)
  (undecorate)
  (skip_pager)
  (opacity 80)
 )
)
The Shell script making sure devilspie is running, and spawning a single xterm process:
desktop-log.sh
#!/bin/sh
test `pidof devilspie` || devilspie &
xterm -geometry 164x73 -uc -class DesktopLog -T daemon.log -e sudo tail -f /var/log/daemon.log &
NB: You can notice the size of the XTerm window is set through the Shell script while the position is set through the DevilsPie rules file, and there is a simple reason for this. By default XTerm has a size of 80 columns and 24 lines and text with too long lines will be wrapped on the next line. If afterwards you resize the window the wrapped text won't move up and the result will be ugly. Therefore it's better to set the initial size of the terminal correctly.

To try the example, save the DevilsPie snippet inside the directory ~/.devilspie, and download and execute the Shell script. Make sure to quit any previous DevilsPie process whenever you modify or install a new .ds file.


Second example

The second example is a little more complete, it starts three terminals of which one is coloured in black.
DesktopLog.ds
(if
 (matches (window_class) "DesktopLog[0-9]+")
 (begin
  (wintype "dock")
  (below)
  (undecorate)
  (skip_pager)
  (opacity 80)
 )
)
 
(if
 (is (window_class) "DesktopLog1")
 (geometry "+480+20")
)
 
(if
 (is (window_class) "DesktopLog2")
 (geometry "+20+20")
)
 
(if
 (is (window_class) "DesktopLog3")
 (geometry "+20+330")
)
desktop-log.sh
#!/bin/sh
test `pidof devilspie` || devilspie &
xterm -geometry 88x40 -uc -class DesktopLog1 -T daemon.log -e sudo -s tail -f /var/log/daemon.log &
xterm -geometry 70x20 -uc -class DesktopLog2 -T auth.log -e sudo -s tail -f /var/log/auth.log &
xterm -fg grey -bg black -geometry 70x16 -uc -class DesktopLog3 -T pacman.log -e sudo -s tail -f /var/log/pacman.log &


NB: You will probably notice that setting the geometry is awkward, specially since position and size are in two different files, getting it right needs several tweakings.

This blog post was cross-posted to the Xfce Wiki.

2010-09-19

CLI tool to review PO files

If there is something annoying about reviewing PO files is that it is impossible. When there are two hundred messages in a PO file, how are you going to know which messages changed? Well, that's the way it works currently for Transifex but there are very good news, first a review board is already available which is a good step forward but second it is going to get some good kick to make it awesome. But until this happens, I have written two scripts to make such a review.

A shell script msgdiff.sh

Pros: tools available on every system
Cons: ugly output, needs template file

#!/bin/sh
PO_ORIG=$1
PO_REVIEW=$2
PO_TEMPL=$3

MSGMERGE=msgmerge
DIFF=diff
PAGER=more
RM=/bin/rm
MKTEMP=mktemp

# Usage
if test "$1" = "" -o "$2" = "" -o "$3" = ""; then
    echo Usage: $0 orig.po review.po template.pot
    exit 1
fi

# Merge
TMP_ORIG=`$MKTEMP po-orig.XXX`
TMP_REVIEW=`$MKTEMP po-review.XXX`
$MSGMERGE $PO_ORIG $PO_TEMPL > $TMP_ORIG 2> /dev/null
$MSGMERGE $PO_REVIEW $PO_TEMPL > $TMP_REVIEW 2> /dev/null

# Diff
$DIFF -u $TMP_ORIG $TMP_REVIEW | $PAGER

# Clean up files
$RM $TMP_ORIG $TMP_REVIEW

Example:
$ ./msgdiff.sh fr.po fr.review.po thunar.pot
[...]
 #: ../thunar-vcs-plugin/tvp-git-action.c:265
-#, fuzzy
 msgid "Menu|Bisect"
-msgstr "Différences détaillées"
+msgstr "Menu|Couper en deux"
 
 #: ../thunar-vcs-plugin/tvp-git-action.c:265
 msgid "Bisect"
-msgstr ""
+msgstr "Couper en deux"
[...]

A Python script podiff.py

Pros: programmable output
Cons: external dependency

The script depends on polib that can be installed with the setuptools scripts. Make sure setuptools is installed and than run the command sudo easy_install polib.

#!/usr/bin/env python
import polib

def podiff(path_po_orig, path_po_review):
    po_orig = polib.pofile(path_po_orig)
    po_review = polib.pofile(path_po_review)
    po_diff = polib.POFile()
    po_diff.header = "PO Diff Header"
    for entry in po_review:
        orig_entry = po_orig.find(entry.msgid)
        if not entry.obsolete and (orig_entry.msgstr != entry.msgstr \
        or ("fuzzy" in orig_entry.flags) != ("fuzzy" in entry.flags)):
            po_diff.append(entry)
    return po_diff


if __name__ == "__main__":
    import sys
    import os.path

    # Usage
    if len(sys.argv) != 3 \
      or not os.path.isfile(sys.argv[1]) \
      or not os.path.isfile(sys.argv[2]):
        print "Usage: %s orig.po review.po" % sys.argv[0]
        sys.exit(1)

    # Retrieve diff
    path_po_orig = sys.argv[1]
    path_po_review = sys.argv[2]
    po_diff = podiff(path_po_orig, path_po_review)

    # Print out orig v. review messages
    po = polib.pofile(path_po_orig)
    for entry in po_diff:
        orig_entry = po.find(entry.msgid)
        orig_fuzzy = review_fuzzy = "fuzzy"
        if "fuzzy" not in orig_entry.flags:
            orig_fuzzy = "not fuzzy"
        if "fuzzy" not in entry.flags:
            review_fuzzy = "not fuzzy"
        print "'%s' was %s is %s\n\tOriginal => '%s'\n\tReviewed => '%s'\n" % (entry.msgid, orig_fuzzy, review_fuzzy, orig_entry.msgstr, entry.msgstr)

Example:
$ ./podiff.py fr.po fr.review.po
'Menu|Bisect' was fuzzy is not fuzzy
 Original => 'Différences détaillées'
 Reviewed => 'Menu|Couper en deux'

'Bisect' was not fuzzy is not fuzzy
 Original => ''
 Reviewed => 'Couper en deux'
[...]

2010-07-15

Don't produce Gzipped tarballs

A quick note so I can delete it from my desktop. In order to produce only a Bzip2 tarball with the Autotools, specially when running make distcheck, set the automake init call with these parameters:

AM_INIT_AUTOMAKE([no-dist-gzip dist-bzip2])

By the way I wonder if it's worth dumping bzip2 against xz.

2010-04-04

VLC with GTK+ look-n-feel

To get Qt applications to look like GTK+ applications run qtconfig and in Select GUI Style choose GTK+. Next click in the menu bar File > Save.

Something is still puzzling me, why does GNOME run VLC automatically with native GTK+ look-n-feel and not Xfce?

Update: Thanks to the power of tig and grep, I figured the Qt library (qt_init function) defines the desktop environment as GNOME for Xfce (this results in GTK+ theming, GNOME like Open dialogues, etc) by retrieving an X11 atom on the root window and compares it to “xfce4” but it seems that this doesn't work nowadays (at least it didn't work within an Xfce 4.7 desktop session). I'm looking forward for sending patches.

Update2: The latest version Qt 4.6.2 doesn't include the code for checking the X11 atom (it's in git), which explains why it doesn't work.

2010-03-08

Include custom GTK+ RC style

I've been using a custom GTK+ RC style for the notes plugin since the version 1.4.0, right now it is at version 1.7.2. I have been playing with GTK+ theming again these last two hours, and I've get custom scrollbars, a gradient for the custom-made “title bar”, and better colours for the notebook to get the current tab stand out from the crowd.

While experimenting on a test-case code I found out a better way to parse a gtkrc file in the program. The first time I was fighting with the existing gtk_rc related functions, I gave up on a solution I partially dislike that is to include a line to the custom gtkrc file within ~/.gtkrc-2.0.

Today I understood how gtk_rc_parse(filename) behaves. You have to call this function at the beginning of the program before building any widgets, it will work even if the file doesn't exist yet. Next, while the program is running, you can modify the file, create it, delete it, truncate it, whatever, and call gtk_rc_reparse_all() to get the style refreshed in the GUI. It's hard to believe that such easy things are sometimes a PITA :-)

Be prepared for a 1.7.3 notes plugin with nicer colours.

2010-03-01

Show/hide functionality from notification area

When using a status icon within the notification area it is common to use the left-click action to show/hide the main window. Obviously this is often done in different ways. So here is my tip on how to do it right :-)

What I believe to me the most sense-full way is to:
  1. Check if the application is invisible and show it,
  2. Otherwise check if the window is inactive and present it,
  3. Otherwise hide it.
In C language it looks like this:
/* Show the window */
if (!(GTK_WIDGET_VISIBLE(window))) {
    gtk_widget_show(window);
}
/* Present the window */
else if (!gtk_window_is_active(GTK_WINDOW(window))) {
    gtk_window_present(GTK_WINDOW(window));
}
/* Hide the window */
else {
    int winx, winy;
    gtk_window_get_position(GTK_WINDOW(window), &winx, &winy);
    gtk_widget_hide(window);
    gtk_window_move(GTK_WINDOW(window), winx, winy);
}
I have been doing this for quite a long time inside the Xfce Notes plugin, except a little different with multiple windows.

Some remarks, the PendingSealings proposes gtk_widget_get_visible instead of its analogous MACRO. And as you may also notice when the window is hidden it gets moved just after, this is important as otherwise the window would be repositioned by its initial value once shown again (e.g. centre of screen or dynamically by the window manager).

2010-02-06

Backward compatibility for Ruby 1.8

As I'm currently writing some Ruby code and that I started with version 1.9 I felt onto cases where some methods don't exist for Ruby 1.8. This is very annoying and I started by switching the code to 1.8 method calls. I disliked this when it came to Process.spawn which is a one line call to execute a separate process. Rewriting it takes around 5 lines instead.

So I had the idea to reuse something I already saw once. I write a new file named compat18.rb and include it within the sources that need it. Ruby makes it very easy to add new methods to existing classes/modules anyway, even if they exist already, so I just did it and it works like a charm.

Here is a small snippet:
class Array
        def find_index(idx)
                index(idx)
        end
end

class Dir
        def exists?(path)
                File.directory?(path)
        end
end

Update: It can happen that a fallback method from Ruby 1.8 has been totally dropped and replaced against a new method in 1.9, and in this case the older method has to be checked if it exists, and otherwise make a call to the parent.
class Array
        def count
                if defined? nitems
                        return nitems
                else
                        return super
                end
        end
end

2009-10-22

Console keyboard layout and beep

Two quite annoying bits to remember so lets blog 'hem. Under a tty the keyboard may have a bad layout, I know perfectly changing it under X with setxkbmap but I usually Google for the console. The answer is loadkeys. Running loadkeys -d will print the current map file that gives an idea where to find the maps. Switching the map works like loadkeys /lib/kbd/keymaps/.../fr-latin1.map.gz, in other words just pass the map file. Now to come to the other annoying command to remember is the ability to cut off the beep. It works with setterm -blength 0.

Update: passing the locale directly to loadkeys works (thanks Boris), neither the help output nor the man page mentions this.

2009-10-13

Fast Python debugging with Vim

So I just needed to test some lines of Gtk+ code and preferably with Python. I love the interpreter (just as well as irb) but debugging even small Gtk+ pieces is not very attractive in the end. Therefore I jumped into Vim, typed my small script, and then executed the command ":%!python -". Only problem is that after the command exits it replaces the content of the Vim buffer with the console output that contains Python debugging messages as well, a quick press on "u" reverts this but maybe there is a cleaner way.

2009-09-03

Build a project with Vala

This post is about using Vala in a project but in the end provide the C code for the releases. I think that this is very essential and that releasing source code to be build from Vala is wrong. Vala will always rewrite the code to GObjects in C, but has already proven that compiling the same code from two different versions of Vala will fail. So when you are doing releases with Vala you will break your releases sooner or later. Another good point is when the Vala code is compiled on top of patched vapi files, doing only C compilation with the releases will drop the requirement to apply them.

I'll take as example the Autotools, if you are using a different tool-chain you can surely adapt it. The idea is simple, the Vala sources are only compiled in maintainer mode. When you compile the application from the development branch you will usually have a script called autogen.sh to build the configure script that will automatically be executed with the parameter --enable-maintainer-mode. When providing the distribution tarball that is created with make distcheck, the configure script will not be run with that parameter (except if specified by hand) and the source files to build from will be filled in with the C filenames.

The example below is very generic and can be copy/pasted but should be adapted.

Autoconf script

1. The initialization of Automake and the maintainer mode in the autoconf script. The Automake version is checked for 1.11 which is the first version that comes with Vala support. The extra dist-bzip2 argument is there to provide an extra bzipped distribution tarball as you guessed it.
AM_INIT_AUTOMAKE([1.11 dist-bzip2])
AM_MAINTAINER_MODE()
2. The check for Vala only on maintainer mode. The AM_PROG_VALAC defines the variable VALAC that can be reused inside the Makefile.am files and accepts an optional version check.
if test "x$USE_MAINTAINER_MODE" = "xyes" ; then
AM_PROG_VALAC([0.7.4])
if test "x$VALAC" = "x" ; then
AC_MSG_ERROR([Cannot find the "valac" compiler in your PATH])
fi
fi
3. It is possible to sum up the build configuration at the end of the autoconf script.
echo
echo "Build Configuration:"
echo
echo "* Maintainer Mode: $USE_MAINTAINER_MODE"
if test "x$USE_MAINTAINER_MODE" = "xyes" ; then
echo
echo " * Vala: $VALAC"
echo
fi

Automake script

1. The declaration of the Vala sources and their respective compiled C sources.
product_VALASOURCES = \
obj1.vala \
obj2.vala \
main.vala

product_VALABUILTSOURCES = $(product_VALASOURCES:.vala=.c) product.h
2. Use the special BUILT_SOURCES variable to build given targets before running a dist with e.g. make distcheck. This usually done in maintainer mode, as in this case to be sure the releases won't have anything to do with Vala.
if MAINTAINER_MODE
PACKAGES = --pkg=gtk+-2.0
BUILT_SOURCES = vala.stamp
vala.stamp: $(product_VALASOURCES)
$(VALAC) --vapidir=$(srcdir) $(PACKAGES) $^ -C -H product.h
touch $@
endif
3. The final sources for the product are filled in with the generated Vala sources. The Vala sources are not passed to any SOURCES which is why they are passed to the special EXTRA_DIST variable.
product_SOURCES = \
random-source.c \
random-header.h \
$(product_VALABUILTSOURCES)

EXTRA_DIST = $(product_VALASOURCES)
if MAINTAINER_MODE
CLEANFILES = \
$(BUILT_SOURCES) \
$(product_VALABUILTSOURCES)
endif

That's it

There are many existent Vala projects nowadays from where you can pick up new ideas, and this post is just an example amongst many others. The full example is available in the xfce4-vala bindings.

Update: I corrected some mistakes seen in green in the script portions. If VALAC is unset the configure script must quit otherwise the resulting Makefiles will have empty commands instead of /usr/bin/valac. Also the generated header file must be passed to product_VALABUILTSOURCES otherwise it would have been left out from distributions as it wans't passed to any product_SOURCES nor EXTRA_DIST variables.