Pike project – module stub creator
I recently began learning how to create Pike modules in C. The Pike module C API seems great and once you’ve sorted things out the modules are easy to build and install. Non the less, when creating a C module from scratch there’s a couple of files you need and some configurations of those before everything is set for go. And here comes “pike-project” into play.
Pike-project is a simple GTK program (works as command line tool also) written in Pike it self. The program will create the basics for a running Pike C module, or a plain installable Pike module. Then it’s just starting programming.
The program is available at my Github repository.
BTW! At the moment it only works on Linux I suppose.
GTK hacking in Pike
I’ve found out that it’s great fun programming desktop applications and of course it gets more fun the more you learn. Now I’m doing a Twitter client in Pike – my favorite programming language – mostly because I wanted to try out GTK programming in Pike. I use the good Twitter client Pino – written in Vala – and I have borrowed the concept and layout from it. I call it Tweepi.
The only major difference between Tweepi and Pino – besides they are written in different programming languages – is that Pino uses WebKit to draw the status messages where I am using good old GTK widgets – and I guess there are no bindings to WebKit in Pike for that matter
One thing I noticed is that the Gtk.Label widget sucks at displaying longer texts that line wraps. Since the label widget handles some HTML formatting I thought that it would be suitable for displaying the status messages, but the text looked like shit, line wrapping where ever it felt like. And the Gtk.TextView widget doesn’t handle formatting per default so I Googled some and found that you can format text in Gtk.TextViews by inserting Gtk.TextTags at desired positions. And since Pike has the most awesome HTML parser It was just a matter of sending the text through the parser and create some Gtk.TextTags and inserting them at the same position in the text buffer. (Well, actually it wasn’t that easy but with some help from a Python class I found on the web it was doable).
So now I have a start at something that is a Gtk.HtmlTextView – actually it inherits Gtk.TextView but has an additional method insert_html_text(string text) – and albeit quite simple at the moment it’s worth continuing on. The code for the HtmlTextView is available at my Github repository.
In general I find the GTK implementation in Pike to be pretty OK, but there exist some verbose, and tedious, stuff like getting the text from a Gtk.TextView:
- Gtk.TextBuffer b = my_textview->get_buffer();
- string text = b->get_text(b->get_start_iter(), b->get_end_iter(), 0);
which in Vala and C# would be done like:
- // Vala
- string text = my_textview.get_buffer().text;
- // C#
- string text = myTextView.Buffer.Text;
Anyway! Tweepi isn’t done yet but I think I have solved the most tedious stuff and it’s starting to become useful. It’ll probably be done in a couple of weeks and I will of course release the sources then.
Extracting text from PDFs

Unwanted line breaks in text copied from PDF
Anybody working with information sooner or later have to copy and paste text from PDF-files. And anybody who has done that knows what a pain in the a** that is! You get actual line breaks from the visual line breaks in the PDF. The other day I began a job where I have to copy and paste text from a whole bunch of PDF files and it didn’t take long before I almost exploded with anger
So I thought: Why not make a simple application that extracts the text from the PDF and – to the most possible degree – normalizes the unwanted line breaks.
And then there was Textifyer
So I fired up Visual C# Express and started hacking. I soon found the PDFbox component – using IKVM.NET – and it didn’t take long before I had some code that actually extracted the text from a PDF file. (a PDF extraction in C# howto)
I figured out how to detect unwanted line breaks: Each line with an unwanted line break ends with a space character. Lines with a wanted line break doesn’t (in 99% of the cases). So it is just a matter of of looping over the lines and if it ends with a space skip adding a line break and just append it to the previous text buffer.

Unwanted line breaks removed
So now I just have to clean up the interface and bug test the program – which will happen automatically since I’m copy and paste from a whole bunch of PDFs at the moment. When I feel it’s working alright I will release the program. It’s really nothing hardcore about it anyway

Of course there’s drag-n-drop support!
Bitlyfier – A Bit.ly client for GNOME
For those of us tweeting – or sharing web addresses in general – these long addresses with extensive query strings you wan’t to share isn’t too user friendly. So we have Bit.ly, among others, that lets you shorten a URL – or give it an alias if you like – and also gives you statistics on how many clicks it has and if it’s shared on Twitter and what not.
Since I’m on the quest of learning the programming language Vala I though why not making a Bit.ly desktop client for GNOME. So I did!
The desktop client
There’s really nothing extraordinary about it, in fact it’s quite simple. Put a long URL in the input field and hit “OK”. You’ll get the shortened URL back in the same input field.
NOTE! The screenshots is showing the Swedish translation but the interface is orginally in English.
Shortening a long URL

The shortened URL

To use the application you will of course need a Bit.ly account. The first time Bitlyfier is launched it will ask for your Bit.ly account settings. Just fill in your username and API key (it’s found on your account page at http://bit.ly/account).
Bitlyfier account settings

The command line interface
For the hacker you, Bitlyfier can also be used as a command line tool. These are the options:
- Usage:
- bitlyfier [OPTION...] - Bitlyfier, URL shortener/expander
- Help Options:
- -h, --help Show help options
- Application Options:
- -e, --expand Expands the given URL
- -s, --shorten Shortens the given URL
- -n, --no-gui Sets the application in command line mode
- -g, --gconf Invokes setting username and apikey
NOTE! You should quote the value of the ‘-s’ flag. If the URL to be shortened
contains a querystring with ampersands the URL will be truncated if it’s not
quoted.
So to shorten a long URL do like:
user@machine:~$ bitlyfier -n -s "http://domain.com/long/url/to/shorten"
The Vala Bitly API classes
The Bitly API class I’ve written can of course be used standalone (it’s located in src/bitly.vala in the sources package downloadable below). Here’s an example of usage:
- // main.vala
- // Compile: valac --pkg gee-1.0 --pkg json-glib-1.0 --pkg libsoup-2.4 -o main
- int main(string[] argv)
- {
- Bitly.Api api = new Bitly.Api("username", "R_the_api_key");
- Bitly.Response response = api.shorten("http://domain.com/the/long/url");
- stdout.printf("Short URL: %s\n", response.get_string("shortUrl"));
- response = api.stats("A2ma2z");
- stdout.printf("Clicks: %d\n", response.get_integer("clicks"));
- return 0;
- }
More about the Bit.ly API and what the API methods do can be read about at http://bit.ly/6HIqjS.
The sources
The development sources of this application is available at Bitlyfier at Github. The current stable release can be found at the Download page.
JavaScript URI class
The other day I needed an URI class for JavaScript. I was doing some stuff where I needed to alter certain parts of an URI. I bet there’s a couple of URI classes for JavaScript out there but I can be a bit nit-picky about code and how it’s written
Anyway, I had a URI parser regexp lying which I wrote for a Vala class (before I found the Soup.URI class) and I thought that since that’s reusable I could hack up a JavaScript URI class myself. So I did!
Here’s some examples of usage:
- var uri = new URI("http://poppa.se/blog/javascript-uri-class/");
- console.log(uri.scheme); //-> http
- console.log(uri.host); //-> poppa.se
- console.log(uri.path); //-> /blog/javascript-uri-class/
- console.log(uri.port); //-> 80
Now, if we want to alter the host so that it contains www we do:
- uri.host = "www.poppa.se";
- console.log(uri.toString()); //-> http://www.poppa.se/blog/javascript-uri-class/
It’s also easy to alter query string variables:
- var uri = new URI("http://host.com/?name=poppa&lang=se");
- uri.variables["name"] = 'Günther';
- uri.variables["lang"] = 'de';
- console.log(uri.toString()); //-> http://host.com/?name=Günther&lang=de
And I think that’s pretty smooth
New Roxen Application Launcher for Linux written in Vala
A couple of weeks ago I stumbled upon a fairly new programming language named Vala. I thought it looked promising and since Vala is developed by the GNOME project – with the purpose of making software development for, primarily, GNOME easier – and I’m an avid GNOME user I wanted to look deeper into the world of Vala.
I, and most programmers I believe, work in that way that I need a real and useful project when learning a new programming language. So I thought why not re-writing the Roxen Application Launcher I wrote in C#/Mono a couple of years ago in Vala – which by the way is syntactically very, very similar to C# and Java. I’d gotten tired of always having to fiddle with the C# code with every new version of Mono since something always broke when Mono was updated so a re-write wasn’t going to be totally pointless. The good thing about Vala is that the Vala compiler generates C code and that’s what you compile the program from. Fast code and hopefully more mature and stable libraries that won’t break backwards compatibility with every new release.
What about Vala
So, on I went about it and I think that Vala is a really promising language. It’s still a very young language so some library bindings isn’t behaving exactly as expected and the documentation isn’t directly redundant – although the Vala reference documentation site isn’t half bad. But since Vala pretty much is a wrapper for, or binding to, the underlying C libraries you can find answers to your questions that way. All in all I think Vala has a promising future: Way more simple than C and almost as fast and light on memory (remember the Vala compiler generates C code) and way faster than C#/Mono and free from any Microsoft associations
.
What about the Roxen Application Launcher
In this new version I utilize GConf for storing application settings. I also made use of – for the first time – the GNU Build Tools for compilation which also makes it easier to distribute and for others to compile from the sources. This also means that the distributed version compiles from the C sources and not the Vala sources so there’s no need for the Vala compiler to build the program.
Other than that there’s nothing fancy about it. The Vala sources is available at my Github repository.
Roxen Appliction Launcher 0.4.2 19:38, Sun 20 December 2009 :: 374 kB
Screenshots
The screenshots is showing the Swedish translation.
Vala – the new programming language for Gnome
This Friday when I read the last issue (in Sweden) of Linux Format there was an article on a new programming language named Vala. The goal for Vala is to provide a modern programming language for, primarily, developing Gnome applications. There is of course Mono, but Vala doesn’t run in a virtual machine but is complied to machine code. But Vala resembles C# syntactically and has borrowed a lot of concepts from C#.
From what I understand Vala code is first translated into plain old C code, and then compiled with the ordinary GCC compiler. The benefit is that you don’t have to get head aches about memory management and so forth.
Vala seems pretty interesting and I downloaded it and compiled it without any difficulties. There are precompiled packages for most Linux distros – it’s available in the Ubuntu repository – but since Vala is new and still under development the distro packages is far behind in version.
There’s also a Vala IDE and plugins for GEdit, Anjuta and Eclipse.
Anyway, just to try Vala out I made a little program – using Val(a)ide – that changes the desktop wallpaper on a per interval basis. Send the program a path to a directory with images and the background will change among those images every *nth minutes.
This program needs libgee which at the moment needs to be added manually.
Compile: valac --pkg gconf-2.0 --pkg gee-1.0 --pkg gio-2.0 main.vala -o wallpaper-iterator
- /* main.vala
- *
- * Copyright (C) 2009 Pontus Östlund <spam@poppa.se>
- *
- * No license what so ever. Do what ever you like...
- *
- * Author:
- * Pontus Östlund <spam@poppa.se>
- */
- // GLib isn't really neccessary since it's imported automatically
- using GLib, Gee, GConf;
- /**
- * User defined exception types
- */
- errordomain IOError {
- FILE_NOT_FOUND,
- NOT_A_DIRECTORY
- }
- /**
- * Main class
- */
- public class Main
- {
- /**
- * Used as reference in option parser
- */
- static int arg_delay;
- /**
- * Application command line options
- */
- const OptionEntry[] options = {
- { "delay", 'd', 0, OptionArg.INT, ref arg_delay,
- "Number of minutes to wait before swapping background", null },
- { null }
- };
- /**
- * Main method
- *
- * @param args
- * Command line arguments
- */
- public static int main (string[] args)
- {
- try {
- var opt = new OptionContext("\"/path/to/wallpapers\"");
- opt.set_help_enabled(true);
- opt.add_main_entries(options, null);
- opt.parse(ref args);
- }
- catch (GLib.Error e) {
- stderr.printf("Error: %s\n", e.message);
- stderr.printf("Run '%s --help' to see a full list of available "+
- "options\n", args[0]);
- return 1;
- }
- if (args.length < 2) {
- stderr.printf("Missing argument!\n");
- stderr.printf("Run '%s --help' for usage\n", args[0]);
- return 1;
- }
- // Default time before changing background is 30 minutes
- int delay = arg_delay > 0 ? arg_delay*60 : 60*30;
- try {
- WallpaperIterator bg = new WallpaperIterator(args[1], delay);
- bg.run();
- bg.stop();
- }
- catch (IOError e) {
- stderr.printf("Error: %s\n", e.message);
- return 1;
- }
- finally {
- stderr.printf("Finally block reached!\n");
- }
- return 0;
- }
- }
- /**
- * Class that handles changeing of desktop wallpapers on a per interval way
- */
- public class WallpaperIterator : GLib.Object
- {
- /**
- * Number of seconds to wait before changeing wallpaper
- */
- private int delay = 0;
- /**
- * Current index in the images list
- */
- private int index = 0;
- /**
- * List of images to change between
- */
- private ArrayList<string> files = new ArrayList<string>();
- /**
- * List of allowed content types
- */
- private ArrayList<string> allow = new ArrayList<string>();
- /**
- * GConf client object
- */
- private GConf.Client gclient = null;
- /**
- * GConf registry where the background image is set
- */
- private string gconf_key = "/desktop/gnome/background/picture_filename";
- /**
- * Background being used when the application is started
- */
- private string default_bg = null;
- /**
- * Constructor
- *
- * @param dir
- * The directory to collect wallpapers in
- * @param delay
- * Time to wait - in seconds - before swapping wallpaper
- */
- public WallpaperIterator(string dir, int delay)
- throws IOError
- {
- assert(delay > 0);
- allow.add("image/jpeg");
- allow.add("image/png");
- var f = File.new_for_path(dir);
- if (!f.query_exists(null))
- throw new IOError.FILE_NOT_FOUND(" \"%s\" doesn't exits!".printf(dir));
- if (f.query_file_type(0, null) != FileType.DIRECTORY) {
- throw new IOError.NOT_A_DIRECTORY(" \"%s\" is not a directory!"
- .printf(dir));
- }
- collect(f.get_path());
- if (files.size < 2) {
- warning("Not enough images found for this application to be useful!\n");
- return;
- }
- this.delay = delay;
- }
- /**
- * Run the application. Starts a MainLoop
- */
- public void run()
- {
- gclient = GConf.Client.get_default();
- default_bg = gclient.get_string(gconf_key);
- MainLoop loop = new MainLoop(null, false);
- var time = new TimeoutSource(delay*1000);
- time.set_callback(() => { swap(); });
- time.attach(loop.get_context());
- loop.run();
- }
- /**
- * Stop the application. Tries to reset the background
- */
- public void stop()
- {
- try {
- if (default_bg != null)
- gclient.set_string(gconf_key, default_bg);
- }
- catch (GLib.Error e) {
- warning("Failed to restore background!\n");
- }
- }
- /**
- * Does the actual background swapping
- */
- private void swap()
- {
- if (index >= files.size) {
- debug("Restart...\n");
- index = 0;
- }
- debug("Callback...%-2d (%s)\n", index, files[index]);
- try {
- gclient.set_string(gconf_key, files[index]);
- }
- catch (GLib.Error e) {
- warning("Failed to set background: %s\n", e.message);
- }
- index++;
- }
- /**
- * Collect images
- *
- * @param path
- */
- private void collect(string path)
- {
- try {
- var dir = File.new_for_path(path).enumerate_children(
- "standard::name,standard::type,standard::content-type",
- 0, null
- );
- FileInfo fi;
- string fp;
- while ((fi = dir.next_file(null)) != null) {
- fp = path + "/" + fi.get_name();
- if (fi.get_file_type() == FileType.DIRECTORY)
- collect(fp);
- else {
- if (fi.get_content_type() in allow)
- files.add(fp);
- else
- warning("Skipping \"%s\" due to unallowed content type\n", fp);
- }
- }
- }
- catch (GLib.Error e) {
- warning("Error: %s\n", e.message);
- }
- }
- }
I think Vala looks promising and I will try it out trying to write a more complex application when I find the time.
Merging associative arrays in PHP
It’s nice when serendipity is your friend! I was porting my Bitly class from Pike to PHP – I know there’s probably a hundred PHP classes already out there, but mine is better coded
– and noted by accident that I had used some Pike syntax in my PHP class but it was working anyway. So what was I doing? In Pike there’s separate data type for associative arrays called mapping. In Pike, in general, when merging two objects you just join them with a + sign. Thus merging two mappings you do like
- mapping m1 = ([ "key1" : "Value 1", "key2" : "Value 2" ]);
- mapping m2 = ([ "key3" : "Value 3" ]);
- write("My mapping: %O\n", m1 + m2);
- //> My mapping: ([ /* 3 elements */
- //> "key1": "Value 1",
- //> "key2": "Value 2",
- //> "key3": "Value 3"
- //> ])
And I noted that I had done the same thing in PHP and the result was perfectly valid:
- $a1 = array("key1" => "Value 1", "key2" => "Value 2");
- $a2 = array("key3" => "Value 3");
- echo "My mapping: ";
- print_r($a1 + $a2);
- //> My mapping: Array
- //> (
- //> [key1] => Value 1
- //> [key2] => Value 2
- //> [key3] => Value 3
- //> )
This method doesn’t work on flat array though so there you’ll still have to use array_merge(), but pretty nice anyway.
And oh, the PHP Bitly class will be part of the new PLib release once done!
UTF-8 encoding/decoding in C
I was working on a simple database to Excel XML exporter the other day and decided to write it in C. Now, the problem was that since the Swedish language contains non-ascii characters the output needs to be UTF-8 encoded. C doesn’t have a built-in function for this – it seems I should add since I’m a C rookie – and no matter how I searched at Google I couldn’t find anything useful. So I thought…
Look at PHP
…why not look at the source code of PHP and see how the PHP functions utf8_encode and utf8_decode are being done. So I downloaded the source of PHP and with a little find . -name *.c -print | xargs grep "utf8_encode" I found the functions in xml.c. Thankfully they weren’t too complicated – when dug out from the rest of the XML functions – so I didn’t take too long before I had them as standalone functions.
This is how they are used:
- #include "utf8.h"
- int main(int argc, char **argv)
- {
- char *iso_str = "Pontus Östlund";
- char *utf8_str;
- utf8_str = utf8_encode(iso_str);
- iso_str = utf8_decode(utf8_str);
- return 0;
- }
And it seems to be working quite OK!
utf8.c 17:31, Sat 17 October 2009 :: 5.3 kB
utf8.h 17:31, Sat 17 October 2009 :: 1 kB
Roxen Application Launcher 0.3
I just created an updated version of Roxen Launcher. I got an error report from one who tried to build the application:
./ApplCon.cs(232,24): error CS0122:
‘System.Net.Sockets.TcpListener.Server’ is inaccessible due
to its protection level
An explanation of the error can be found at MSDN. The reason seems to be due to TcpListener.Server being a protected property but I tried to access it as public. The strange thing is that I didn’t get an error about it nor on my machine at home or at work. Now I created a derived class of TcpListener.Server so that I can access the protected property.
We’ll see if it works!
Roxen Application Launcher 17:31, Sat 17 October 2009 :: 97.3 kB
Gnome Font Manager
One thing I miss on Linux Gnome is font manager. Not just a font viewer but a proper manager like the old Adobe Type Manager. So I thought: Well, lets create one then! It might be that it already exist some font managers for Linux/Gnome but as always; this will be a good project for learning new stuff so I really don’t care if there are 1000 font managers out there
Font parsing
The first thing to do, and that I have done, is porting my font parser from PLib to C#. That was no major head ache. There are at least to different font classes available in C# Mono (`System.Drawing.Font` and `Pango.Font`) but they don’t give all information about the font that I want.
Worth mentioning is that I heavily used the Mono DataConverter class to unpack the binary strings in the fonts. The unpack() function in PHP is just tremendous and there doesn’t seem to be a native alike in C#. But thanks to Miguel de Icasa’s DataConverter it went quite alright.
Font preview
The next thing to do was figuring out how to create the font previews. And I figured it out
First I though of using the console program gnome-thumbnail-font to create the previews but I had to throw that one into the bin since it doesn’t seem to handle multi line text. Since I’ve never used the graphics functions in C# before I came to the conclusion that I had to create the previews all by my self. It was quite easy finding good examples on the net of how to create text images with C#. A couple of hours later that problem was also solved (as you can see in the screen shot below). And man the graphics stuff in C# is fast. The preview images are generated instantly!
Next step
I have a lot left to do before this is a useful program but we’re heading there. One feature I’m planning on implementing is the ability to create your own font sets that you can activate/deactivate.
And I will probably come up with some more stuff to add, but that will be a later head ache!
Roxen Application Launcher for Linux
I thought I should broaden my C# knowledge a bit and you know how it is: To learn new stuff you need a real project to work on or else you will lose the fire sooner than later. So I came up with a good project that is actually useful to me: Porting Roxen’s “Application Launcher” to C#. There’s nothing wrong with the original one, written in Pike, except that it uses GTK 1 which is quite hideous (in an aesthetic meaning) compared to the newer GTK 2. And I also though it would be cool to create a panel applet (in the notification area of Gnome so you could put the Application Launcher in the background).
BTW: For those of you not knowing what the heck Roxen’s Application Launcher (AL here after) is here’s a brief explanation: Files in Roxen CMS is stored in a CVS file system which means that you don’t deal with files the way you normally do. To manage files you use a web browser interface (which is a darn good one I might add) but sometimes you actually want to edit files in your standard desktop application. And it is here the AL comes to play. You can download a file through the browser interface so that the file is opened in the AL. AL will then open the file in the desktop application you have associated with the file’s content-type. When you make your changes and saves them the AL will directly upload the changes to the server. So in short I could have said: The Application Launcher is a means to edit files on a remote Roxen server with a preferred desktop application.
The obstacles
I must say I’ve learned a lot from this project!
First off: If you download a file for editing and the AL is already started you don’t want to start a new instance of AL (this is something I have never ever thought about before – in general terms, not just concerning AL) but when you do think about it you find that it’s not a piece of cake to solve. I solved it the way it is solved in the original AL. The first instance of AL that is started also starts a “socket server” that listens for incoming traffic on a given port on the local IP. When a new instance is started it first checks if it can connect to said port and if it can it sends the arguments through the socket to the first instance which then handles the request. The second instance is simply terminated when it has send the data though the socket.
So there I had to do some socket programming. Great fun
Secondly: Stuff happens in the background of AL – data send through the socket remember – which means that nothing happens when you try to update the Graphical User Interface. (NOTE! This is the first more advanced desktop application I’ve done.) After “Google-ing” around a bit I came to know that this was a real newbie problem
The thing is that the GUI can only be updated through the same thread that started it so when using background threads – implicitly that’s what I’m doing although handled by the asynchronous callback infrastructure of C# – you need to make sure the GUI is updated through the main thread. This is the most simple way so solve it:
- Gtk.Application.Invoke(delegate{
- CallFunctionToUpdateGUI();
- });
That’s not too difficult when you know it
Thirdly: The AL is sending data back and forth through the HTTP protocol which means we have to use some sort of HTTP client. C# has a couple of ways to do this but unfortunately they came up short, or I couldn’t use them anyway. I didn’t manage to figure out exactly why I always caught an exception saying something like: A protocol violation occurred!. I’m far from the only one who have fought with this and it has something to do with the headers sent from the remote server. You can invoke “unsafe header parsing” but that was to much of a hassle so I created my own little HTTP client.
One big annoying thing with C# is that is seems almost impossible to turn data from streams into strings without having to use any one of the System.Text.Encoding.* classes/objects which in my case meant that images and files in binary form got seriously fucked up. I manged to solve this my never turning the data into a string but keeping it as a System.Text.Encoding.* all the way from request to response to saving to disk. It was rather irritating but at the same time nice when solved (and I learned a whole bunch about System.Text.Encoding.*, System.Text.Encoding.*, System.Text.Encoding.* and System.Text.Encoding.*.)
Finally: Of course I learned a great deal more about C# but this blog post is starting to get pretty excessive so I will round it off by saying that MonoDevelop is starting to become pretty darn good! I just upgraded to the latest version of Ubuntu and that also meant that I got the latest MonoDevelop and I must say it’s more stable than ever (although it occasionally crashes) and a whole bunch of new features are in place. One I havn’t used before – although it might have existed before – is the “Deployment” stuff. It creates a package with configure and make files for optimal compilation. Really smooth!
Source and screens
I will finish off by adding the source files and a few screen shots:
Roxen Application Launcher 17:31, Sat 17 October 2009 :: 96.7 kB
Screen shot 1: Just a standard view

Screen shot 2: The panel applet in action

PLib, the Poppa PHP Library
Other than working my ass off at work I just lately took a real approach on my secretly sleeping project PLib. PLib is my own PHP framework with functions and classes to ease my everyday PHP programming.
To give you an idea of what PLib is all about let me give you an example:
- <?php
- require_once '/path/to/PLib.php';
- //! Lets create thumbnails of all JPEG images in a directory
- PLib::Import('Graphics.Image');
- //! The Dir class is included in Image so I don't explicitly need to
- //! include it
- $dir = new Dir('/path/to/jpegs/');
- $mw = 150; // Max width of thumb
- $mh = 90; // Max height of thumb
- while ($file = $dir->Emit('*.jpg')) {
- $img = new Image($file->path);
- $img = $img->Copy($file->path.'/thumb-'.$file->name)->Scale($mw, $mh);
- wbr($img->Path()); // The full path to the thumbnail
- }
- ?>
Rather easy I think!
AutoDoc
Another cool feature (if I may say so) is the auto documentation. If you quickly want a list of all available classes and functions just type PLib::Info() and you will get the list. Each class and function is then clickable and will lead you to the documentation for which ever class or function you clicked.
If you want the documentation for a specific class just type PLib::Info() and there you have the documentation.
The third way to use the autodoc is to pass an instance of a class as argument like PLib::Info().
And if you wan’t a full documentation site just type PLib::Info() and you will get the same documentation as available at the PLib site.
The site
Anyway, PLib has its site of it’s own where anyone curious can download the latest version of PLib and find out more about the project.
Script for adding all new files in a SVN repository
When working with revision controlled stuff you sometimes add loads of new files to an already existing repository. Then when you are about to check in the next revision you have forgotten where all the new files are and you probably don’t feel like writing svn add thefile too many times. This is of course no problem if you’r using a decent SVN client – like Tortoise SVN on Windows – but I prefer the command line so the solution was writing a script that adds all new files in a directory structure to the SVN repository.
There are “one liners” for this but I wanted a bit more flexibility and ease of use so I wrote the a script that also lets you define regexp patterns for files you don’t want to add even if they exist in the directory structure.
This is how to use it:
- # Add all new files
- svnadd path/to/repository/
- # Add all new files except those matching the regexp
- svnadd -s ".*.txt|tmp/.*" path/to/repository/
- # Add all new files except those matching the regexp in
- # the file defined by the "-f" flag
- svnadd -f regexp.txt path/to/repository/
Quite easy! If you don’t feel like remembering the pattern for files to skip, put the regexp in a file and use the svn add thefile flag.
- #!/bin/bash
- ##########################################################################
- #
- # Script for adding all new files in a directory structure to an SVN
- # repository.
- #
- # copyright © 2007 Pontus Östlund <spam@poppa.se>
- #
- # The svnadd script is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or (at your
- # option) any later version.
- #
- # The svnadd script is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- # Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software Foundation,
- # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #
- ##########################################################################
- while getopts "s:f:h" opts
- do
- case $opts in
- s) skip="$OPTARG";;
- f) if [ -f "$OPTARG" ]; then
- skip=$(head -n 1 $OPTARG)
- else
- echo "$OPTARG doesn't exist!"
- fi
- ;;
- h) help=1;;
- esac
- done
- shift $(($OPTIND - 1))
- if [ -z $1 ] || [ "$help" ]; then
- echo "About: svnadd enables you to add all new files in [dir] to a "
- "subversion repository"
- echo "Usage: svnadd [flags] [dir]"
- echo
- echo " -s <pattern> Regexp pattern for files to skip"
- echo " -f <path> Path to file containing regexp for files to skip"
- echo " The regexp should be placed in line one!"
- echo " [dir] The path to the repository"
- echo
- echo "Example: svnadd svnsrc/"
- echo "Example: svnadd -s 'tmp/.*.xml' svnsrc/"
- echo "Example: svnadd -f regexp.txt svnsrc/"
- echo
- exit 0
- fi
- dir=$1
- if [ ! -d "$dir" ]; then
- echo "$dir is not a directory"
- exit 1
- fi
- while read status file; do
- if [ "$status" = "?" ]; then
- res=$( echo "$file" | egrep -o "$skip" )
- if [ -z "$res" ]; then
- svn add "$file"
- fi
- fi
- done<<EOF
- $( svn st "$dir" )
- EOF
- exit 0
Download
PHP documentation browser
Even though I have my vacation right now I need to hack some ![]()
What I have done is a PHP documentation browser, I simply call it PHPDoc Browser, for GNU/Linux to read the PHP documentation locally on the computer (it’s a little bit like CHM for Windows). This little app isn’t that necessary but I thought it was a great thing for learning new stuff: The application is written in Mono/C# and uses SQLite for storing the search index.
Difference from CHM
Although there’s a CHM equivalent, XCHM, for Unix like systems I decided that my application serves a purpose: What I like about the PHP manual is that you can hit www.php.net/the_function in you browser and you will get the documentation for “the_function”. Of course I implemented the same functionality in PHPDoc Browser. You can also do a wild card search like “array_*” and you will get a list of all “array_*” functions.
I also implemented a free text search but that’s not “a real” FTS at the moment. FTS in SQLite in a little bit harder than in MySQL so while awaiting the next SQLite version the FTS is a bit of a hack. But you can quote the search to narrow it down
What’s learned?
Most of the unnecessary stuff I do I do to learn and the PHPDoc Browser is no exception. I learned how to use SQLite in Mono/C# and I also wrote a self contained installer in Bash, and Bash I havn’t really touch although I’ve been using GNU/Linux for 6-7 years! I found it quite fun writing the installer
Howto
If you would like to try it out:
- Download the install script
- Un-tar it (`tar zxvf phpdocbrowser-installer.tgz`)
- Make sure the script is executable (`chmod +x phpdocbrowser-installer`)
- Open a console and run the installer:
./phpdocbrowser-installer - Answer the questions and you’r ready to go.
The script will create a directory, ./phpdocbrowser-installer, in your home directory in wich you will find ./phpdocbrowser-installer, ./phpdocbrowser-installer and a directory, ./phpdocbrowser-installer, with the PHP documentation. A “run script” will also be installed either in ./phpdocbrowser-installer or in your home directory depending on how you answered the questions and if you agreed to create a desktop shortcut one will hopefully appear on your desktop (havn’t tested this on KDE but it should work fine in Gnome).
To run the application hit the desktop shortcut, if one was created, or invoke ./phpdocbrowser-installer from a console.
If you wish to remove the PHPDoc Browser run the following from a console:
./phpdocbrowser-installer.
And that’s that!
Download
PHPDoc Browser 17:31, Sat 17 October 2009 :: 8.9 MB
Screen shots
Updated Roxen trim tag
Jonas Walldén, CTO at Roxen, has improved my RXML tag contribution <trim></trim>. The code is now really beautiful and you can tell the difference from the code written by a lamer, as myself, and a real programmer, as Jonas. Jonas told me that the <trim></trim> tag will be part of the next Roxen release
Download
Roxen trim tag 17:31, Sat 17 October 2009 :: 4.8 kB
Pike trim module 17:31, Sat 17 October 2009 :: 4 kB
Bug fix for Syntaxer.pmod
It didn’t take too long to notice that I had f–ked up the HTMLParser class a little bit. It was how entities was handled that didn’t really worked as expected – entities in tag attributes was duplicated and inserted in the tag content – but the good side of it is that I learned about the HTMLParser method of the HTMLParser Pike class. I only want to match entities in the data section – i.e. tag content – and not in attributes and the HTMLParser method tells you, as the name implies, in what context the entity is found. So my entity callback function now looks like:
- //! Entity callback
- protected void ecb(Parser.HTML p, string _data)
- {
- if (p->context() == "data")
- line += colorize(entify(_data), "entity");
- }
which hopefully will be completely bug free now. So one down 854 to go
Codify RXML tag and Syntaxer.pmod 17:31, Sat 17 October 2009 :: 183.9 kB
A Pike syntax highlighting module
So I thought I should try to port my syntax highlighting script, Syntaxer, written in PHP to Pike. Mostly for the fun of it but also to improve my knowledge of string handling in Pike. The greatest concern here is that PHP is a dynamic language and Pike is not (in the same sense) and the PHP version of Syntaxer heavily depends on dynamic loading of PHP files. The reason for this is that I generate the “syntax maps” dynamically from syntax files of Edit+. That means that if you want support for a new language just drop a .stx file in the right location and there you go. My script will convert that into a static PHP file, so that the conversion only needs to be done once, and load that file on the fly when that particular language is requested.
I thought that this method would be hard to implement in Pike – although it might be possible – so I had to come up with a slightly different approach. Frankly; it’s not that often you alter the .stx files or implement support for new languages so my solution is to manually create definitions for what ever language. But I still use the .stx files from Edit+ although one needs to copy and paste bit.
In the Pike solution each language is its own class that inherits the master class .stx. The only thing you pretty much need to put in the derived class is some .stx, .stx and .stx that specify what is what in the language. For example, the C++ definition looks like this:
- inherit .Hilite;
- public string title = "C++";
- //| Override the keywords mapping
- private mapping(string:multiset(string)) keywords = ([
- "keywords" : (<
- "auto","bool","break","case","catch","char","cerr","cin",
- "class","const","continue","cout","default","delete","do",
- "double","else","enum","explicit","extern","float","for",
- "friend","goto","if","inline","int","long","namespace","new",
- "operator","private","protected","public","register","return",
- "short","signed","sizeof","static","struct","switch","template",
- "this","throw","try","typedef","union","unsigned","virtual",
- "void","volatile","while","__asm","__fastcall","__based",
- "__cdecl","__pascal","__inline","__multiple_inheritance",
- "__single_inheritance" >),
- "compiler" : (<
- "define","error","include","elif","if","line","else","ifdef","pragma" >)
- ]);
- //| Override the default since # is no line comment in C++
- protected array(string) linecomments = ({ "//" });
- void create()
- {
- ::create();
- colors += ([ "compiler" : "#060" ]);
- styles += ([ "compiler" : ({ "<b>", "</b>" }) ]);
- }
And you really don’t need to make it more fancy than that. For most C-based languages the definitions in the master class .stx is enough. Just add the keywords to the .stx mapping and it looks better than nothing
HTML parser
One thing that differs from the PHP version of Syntaxer is that SGML-based, or tag based, languages will be run through a HTML-parser. The downside of the PHP version is that tag content will be highlighted as well, which of course isn’t what we want, but since Pike has a decent HTML parser that behaves like a SAX parser so I wrote a class, .stx, that uses that for highlighting tag based stuff. The .stx class also inherits .stx so the methods and members are the same.
I wonder why there’s no, built-in, HTML parser for PHP?
A Roxen tag module
Of course I had to write a Roxen tag module so that we can highlight source code in Roxen web pages. This was the reason for writing the Pike module at all. The tag is named .stx which might not be the most innovative name but what the heck! The beauty of it is that I made it possible, in the module settings tab, to create a surrounding HTML template for the output. When you run some code through the parser you get the highlighted source code as well as the name of the language and how many lines of code was highlighted and it might be nice to present that as well (just like the code blocks on this site). It’s tedious writing that surrounding HTML every time so now it’s just to put that in the settings and the code blocks will always look the same.
Finally
There’s some stuff left to do but the code works well enough to be usable. And I must say that the speed of the Pike version is like a thousand times faster than the PHP version!
Oh, and I have implemented support for the following language:
- ActionScript
- C
- C++
- C#
- CSS
- Java
- JavaScript
- HTML
- Perl
- PHP
- Pike
- Python
- Ruby
- RXML
- XSL
And that’s that for now.
Codify RXML tag and Syntaxer.pmod 17:31, Sat 17 October 2009 :: 183.9 kB
A Pike module and a Roxen tag
When you’r used to one programming language and start learning a new one you sometimes miss some features from the former. That happened to me a couple of years ago when we started using Roxen at work. What I missed was the trim functions from PHP. Sure, Pike and RXML can trim strings from whitespace but the beauty of trim, trim and trim in PHP is that you can trim characters as well as whitespace. And to my knowledge there’s no equivalent to trim and trim – that is only trim the left and right side respectively of the string.
So I wrote a Pike module that did that and also created an RXML tag of it. Just yesterday I rewrote that code since I do think I’ve become a better programmer and have come to learn Pike a lot better since my first try.
And I also wrote a method to shorten a string from the center and out, i.e. trim.
So here are some examples of usage:
- import .trim;
- string path = "/this/is/a/path/";
- write("%s\\n", rtrim(path, "/"));
- // Will output: /this/is/a/path
- write("%s\\n", trim(path, "/"));
- // Will output: this/is/a/path
- string long_str = "This is some string that's too long for us";
- write("%s\\n", ctrim(long_str, 20));
- // Will output: This is...for us
And here’s the RXML implementation:
- <trim right="" char="/">/this/is/a/path/</trim>
- <!-- /this/is/a/path -->
- <trim center="" length="20">This is some string that's too long for us</trim>
- <!-- This is...for us -->
And that’s that.
Trim Pike module 17:31, Sat 17 October 2009 :: 4 kB
Trim Roxen tag module 17:31, Sat 17 October 2009 :: 4.8 kB












