What would you like to read?

Brighton Ruby Users GroupWith the new year, this is your chance to shape the future of this space:

What do you think this blog’s focus should be?

 
Your comments will be all be read and everybody will get a reply, so feel free to share!

If you enjoyed this post, make sure you subscribe to my RSS feed!

Six Resources To Study And Master Git Source Control

Logo by Henrik Nyh (http://henrik.nyh.se/2007/06/alternative-git-logo-and-favicon)It’s no secret that Git, as a source code control tool, has become quite popular in 2008, in part boosted by the success of the socially oriented github.com Here is a list of six resources that will help you get more comfy with Git, whatever your current knowledge of the tool. Let me know if you think that, after reading these six documents, you can still point to a few stones left unturned.

3 Reasons To Switch To Git From Subversion

A to-the-point document, created by Mark McBride, that covers several scenarios and for each scenario, shows how Git could make your life easier if you are not using it yet.

3reasons

My Git Cheatsheet

A concise guide for the absolute beginner who wants to hit the ground running. Go through the exercises and you will end up with a pretty good picture of what Git can do.

mygitcheatsheet

Everyday GIT With 20 Commands Or So

A quick cheat sheet: start with the section corresponding to your role (individual developer, contributor, integrator…) You will not learn a lot about Git’s philosophy, but you will certainly get the job done.

everydaygitwith20

Git Magic

Ben Lynn wrote a whole book covering not just cloning and branching but also some precious recipes: What to do when something goes wrong? What if my commit is too big? Remote access magic, history digging…Even Git’s shortcomings and their workarounds are covered.

gitmagic

Git from the bottom up

John Wiegley makes a convincing case that approaching Git from a 10,000 ft level is not the best way to understand the tool’s philosophy. Rather, building your knowledge of the tool based precisely on the very concepts that it uses make it much easier to get an overall grasp of Git’s world.

gitfrombottomup

Using Git to Maintain Your Website

Using source code control has always been an effective tool to maintain a web site, especially avoiding these “Uh-oh I clobbered something I shouldn’t have” moments. But Git is particularly well suited to this task, due to its self-sufficient nature. Daniel Miessler shows us how to do just that using Git hooks.

gittomaintain

If you enjoyed this post, make sure you subscribe to my RSS feed!

A very geeky Holidays break

Kill BillWas your break as geeky as mine? Come on, admit it: you’ve done at least one incredibly unsexy thing in the last couple weeks. I know I have. Well, in fact, I had to take a four weeks-long break and it shows in the number of silly things I’ve played with.

In no particular order:

If you enjoyed this post, make sure you subscribe to my RSS feed!

Flex: A hack to give instant focus to a form field

Day 79 - f o c u sI was working on a “quick add” tool for Toodledo — which I am liking more and more — and I assumed that my biggest challenge would be wiring a hotkey to my application — a can of worms in its own right. My mini-application’s main requirement is to be fast and not get in the user’s way. Part of this requirement is that when the “Add” window is displayed, the “Task description” field should be automatically selected, an inviting cursor happily blinking. Easier said than done!

Flex will let me display the native window and select the description field using setFocus() but no cursor for me. I googled the issue and found that when a Flex application runs in a browser, the solution is to give the application itself focus using Javascript.
But I’m not running in a browser!

And now, my silly workaround: since displaying an other panel container — such as an alert message — and dismissing it will return proper focus to my original field, I will simply “display” an invisible container and immediately get rid of it.
There is no guarantee that, on the odd instance, a race condition will not occur.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.voilaweb.addtdtask
{
    import flash.events.TimerEvent;
 
    public class Main
    {
        import mx.core.Application;
        import mx.containers.TitleWindow;
        import flash.display.DisplayObject;
        import flash.utils.Timer;
        import flash.events.TimerEvent;
        import mx.managers.PopUpManager;
 
        private var _tw:TitleWindow;
 
        public function Main()
        {
            Application.application.task_description.setFocus();
            Application.application.task_description.drawFocus(true);
            _tw = new TitleWindow();
            _tw.width = _tw.height = 0;
            var t:Timer = new Timer(100, 1);
            t.addEventListener(TimerEvent.TIMER, showCursor);
            t.start();
            mx.managers.PopUpManager.addPopUp(_tw, Application.application as DisplayObject, true);
        }
 
        public function showCursor(event:TimerEvent):void
        {
            mx.managers.PopUpManager.removePopUp(_tw);
        }
    }
}

If you enjoyed this post, make sure you subscribe to my RSS feed!

More Blaqua

moreblaqua

A couple years ago, some lad going by the pseudonym of @binderskagnaes, at DeviantArt, released a set of icons on a dark background lovingly named “Blaqua.”

Then, he ventured to a great forest and got devoured. Or something.
Whatever the reason, he never created more icons, which frankly is a pity.
I am still using his icon set in my Dock, unfortunately the set was created before Twitter got popular, uTorrent or Evernote were released on OS X, etc.
So, I took a few hours to re-create an original dark PSD and put together a pack of 24 new icons.

I will create more packs if my beloved readers suggest more applications.

In the meantime, go get it!

If you enjoyed this post, make sure you subscribe to my RSS feed!

GMail is the new Mutt! Shortcuts galore.

I know, it’s a bold assertion. But, please, bear with me: as a longtime Unix-head, I need a tool that allows me to zoom through my emails rather than click-glance-click-glance-click-yawn-right-click-delete, etc.

For years I’ve been happy with Mutt because nothing compares with using the arrow keys to navigate through my emails, ALT-O to open a folder, SHIFT-O-R to do a reverse-sort, M for a new message, etc.
That, and using Visor, give me the comfort of a HUD-based email management tool whose speed is quite unbeatable.

Unfortunately, with today’s evolution of mail, everything is more or less HTML-based, which really doesn’t work well with Mutt — even using V to open in a text-based browser isn’t that good. If I ask Mutt to open a full-fledged browser instead, there goes the speed advantage…

So, I have reluctantly moved to a pure Google Mail solution and my experience has been positive so far: I run GMail as a standalone program using Fluid — on another platform I would use Prism — and I can keep using keyboard shortcuts for all my tasks!

If you wish to give it a try, start with only this subset of GMail’s keyboard shortcuts: JKEX#[ENTER]U are all you need to replicate 99% of your Mutt experience…

K/J: cursor up/down
X: select message
E: archive messages
#: delete messages
ENTER: read message
U: back to messages list

If you enjoyed this post, make sure you subscribe to my RSS feed!

Adobe Alchemy: Passing a ByteArray from Flex to C++

fxlogoI started playing with Alchemy a couple days ago, with the intent of finally writing OpensIFRr3 — you know, the one working with sIFR3. Since the previous release was in Java, I was planning on creating this one in Flex.
I am not quite there yet, due to the nightmare that porting libxml would be. But I’ve learnt that reading Alchemy’s currently meager documentation could have saved me a few headaches. For instance, do not assume that you will find here some of the magic that other “gateways” offer. More specifically, do not assume that a ByteArray will automatically be passed from ActionScript to C++ as a char *.
Nope, it’s passed as a ByteArray structure, with all sorts of fun overhead that will drive you crazy if you assume a “StringType” object.

If this is gibberish to you, keep reading:
Yes, Alchemy is verbose.
No, you should not fear its complexity.

Here is how I read a compressed flash file in a ByteArray, in Flex, then pass it to C++ for parsing. Obviously it is the start of OpensIFRr3 (jump to the end of the listing if you are only curious about seeing an Alchemy call in action):

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package
{
	import flash.display.Sprite;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.utils.ByteArray;
	import flash.utils.CompressionAlgorithm;
	import cmodule.swfmill.CLibInit; // My C code
 
	public class EchoTest extends Sprite
	{
		private var length:uint;
		private var compressed:Boolean;
		private var version:uint
		private var sig:String;
		private var data:ByteArray;
 
		private function main_fread_uint(fs:FileStream):uint
		{
			return fs.readUnsignedByte();	
		}
 
		private function main_fread_char(fs:FileStream):String
		{
			return String.fromCharCode(fs.readUnsignedByte());	
		}
 
		private function main_fread_str(fs:FileStream, offset:uint, length:uint):String
		{
			var ba:ByteArray = new ByteArray();
			fs.readBytes(ba, offset, length);
			return ba.toString();
		}
 
		private function main_load(name:String):Boolean
		{
			try
			{
				var file:File = new File("/Users/Chris/Projects/sIFRr3/rockwell.swf");
				var fs:FileStream = new FileStream();
				if(!file.exists)
				{
					trace("File does not exist");
					return false;
				}
				fs.open(file, FileMode.READ);
				sig = main_fread_str(fs, 0, 3);
				version = main_fread_uint(fs);
				if(sig != "CWS" && sig != "FWS")
				{
					trace("ERROR: input is no SWF");
					return false;
				}
				length = main_fread_uint(fs);
				length += main_fread_uint(fs) << 8;
				length += main_fread_uint(fs) << 16;
				length += main_fread_uint(fs) << 24;
				length -= 8;
				compressed = sig.charAt(0) == 'C';
				if(length != file.size - 8)
				{
					if( length > file.size - 8 && !compressed)
					{
						trace("WARNING: size specified in SWF (" + length + ") != file.size (" + file.size + "), using filesize-8.");
						length = file.size - 8;
					}
				}
				data = new ByteArray();
				fs.readBytes(data);
				if(compressed)
				{
					data.uncompress(CompressionAlgorithm.ZLIB);					
				}
				fs.close();
			}
			catch(e:Error)
			{
				trace("Error: " + e.message);
				return false;
			}				
			return true;
		}
 
		public function SWFTest()
		{
			var loader:CLibInit = new CLibInit;
			var lib:Object = loader.init();
 
			if(main_load("/Users/Chris/Projects/sIFRr3/rockwell.swf"))
			{
				trace("ASLength = " + data.length);
				lib.swfmill_swf2xml(version, data.length, data); // Exported method
			}
		}
	}
}

The magic happens here: lib.swfmill_swf2xml(…)

Let’s have a look a this little guy in his natural habitat — in swmill.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
	//define the methods exposed to ActionScript
	//typed as an ActionScript Function instance
	AS3_Val swfmill_swf2xml_method = AS3_Function( NULL, swfmill_swf2xml);
 
	// construct an object that holds references to the functions
	AS3_Val result = AS3_Object( "swfmill_swf2xml: AS3ValType", swfmill_swf2xml_method );
 
	// Release
	AS3_Release( swfmill_swf2xml_method );
 
	// notify that we initialized -- THIS DOES NOT RETURN!
	AS3_LibInit( result );
 
	// should never get here!
	return 0;
}

So, main() will be invoked when the program instance comes up and Flex will be informed that there is a method of interest (swfmill_swf2xml).

Digression:
I know, this is a bit hard to read, but so far most of Alchemy is. After all, the whole bridge relies on the C++ code being compiled to bytecode that is linked indirectly against Flash libraries, the result being turned into ActionScript that will then be compiled to asm-asc. If you look at the work files, you will see ActionScript mixed directly with what looks like assembly code. To quote Adobe, the end-result is “basically one huge finite state machine.”
This means that your C++ code will run “somewhat” in parallel with ActionScript. Beware!

How does this swfmill_swf2xml method manage with our ByteArray? After all, C++ doesn’t know anything about that type of structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static AS3_Val swfmill_swf2xml( void *self, AS3_Val args )
{
	bool success = false;
	unsigned int e_version;
	unsigned int e_length;
	AS3_Val		 e_data = AS3_Undefined();
 
	AS3_ArrayValue( args, "IntType, IntType, AS3ValType", &e_version, &e_length, &e_data );
	fprintf(stderr, "Clength: %u", e_length);
	unsigned char * data = (unsigned char *)malloc(sizeof(unsigned char) * (e_length + 1));
	for(int runner=0; runner < e_length; runner++)
	{
		*(data + runner) = AS3_IntValue(AS3_Get(e_data, AS3_Int(runner))) & 0xFF;
	}
 
	...
 
	return AS3_Int(success ? 0 : -1);
}

Did you see it? Did you see the awesomely hackish way we have to retrieve our arguments using AS3_ArrayValue?
Use of AS3ValType means “You, C++, will store this object as a blob because you do not know better. However, if you use the correct AS3 calls, you will be able to ask ActionScript to manipulate this object on your behalf.”
Therefore, to convert that object, which, I happen to know, is a ByteArray, I will ask ActionScript to read its content and I will store it in an array of chars. Note that I am masking the returned value with 0xFF, because there is no function to read a byte, therefore I need to get rid of the irrelevant bits after reading an integer. And, yes, AS3_IntValue() is a function that maps AS3 integers to C integers. More info here.

If you read the page I just provided a link to, you may wonder why I am passing AS3_Int(runner) to AS3_Get(…)
After all, the second parameter is supposed to be a method name. And this is the case - in a way. By passing an integer, I am asking ActionScript to use the ‘[]‘ form to access our ByteArray.
Note that I had no joy trying to use readUnsignedByte() instead. That’s to be expected; after all, Alchemy is far from stable — or complete.

But it’s certainly promising.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Flex: Render your tree nodes with a line through

So…how hard can it be, right? After all, Flex offers to change your text style — using setStyle — to bold, italics, underlined…oh, but no strikethrough.

But I really needed that for my tree nodes, so here is how I did it.

First, my tree, as defined in a MXML file — well, a simplified version:

?View Code ACTIONSCRIPT
1
2
3
4
<mx:Tree id="outlinerTree" 
    height="100%" width="100%"
    itemRenderer="com.voilaweb.tfd.OutlinerRenderer"
    creationComplete="main_initOutliner();"/>

As you can see, I explicitely reference my renderer. Let’s have a look at OutlinerRenderer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.voilaweb.tfd
{
	import mx.collections.*;
	import mx.controls.treeClasses.*;
 
	public class OutlinerRenderer extends TreeItemRenderer
	{
		override public function set data(value:Object):void
		{
			super.data = value;
		}
 
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			var startx:Number = data ? TreeListData(listData).indent : 0;
			if(disclosureIcon)
				startx += disclosureIcon.measuredWidth;
			if(icon)
				startx += icon.measuredWidth;
			graphics.clear();
			graphics.lineStyle(1, getStyle("color"));
			var y:Number = label.y + label.measuredHeight / 2;
			graphics.moveTo(startx, y);
			graphics.lineTo(startx + label.measuredWidth, y);
		}
	}
}

In a nuthsell, I let the parent paint the label, then add my own line to my graphic context. I use the label’s measurements to size my line.

For those of you new to ActionScript but familiar with Java: yes, it’s just like overriding the paint() method. In fact, ActionScript offers so many similarities with Java — renderers, editors, listeners, annotations… — that if you’ve ever written front-end code, you should give AS3 a try.

If you enjoyed this post, make sure you subscribe to my RSS feed!

A driver for your Darwin-based keyboard woes

I built this driver in 2007, to support Leopard Darwin on my wife’s laptop (hmmm where’s the “wink wink nudge nudge” smiley when you need it?)

I am offering a full driver for download, but it’s only so that you could use my keyboard fix if you do not currently have an ApplePS2Controller.kext that support plug-ins.

The point of this driver really is to provide keyboard support for laptops that see their built-in keyboard as PS2 — ie the vast majority. Therefore the piece that is really interesting to you is ApplePS2Keyboard.kext (in ApplePS2Controller.kext/Contents/PlugIns/)

There are other drivers that do just that, out there, but unfortunately many of them fail to properly detect the keyboard.

So, here goes. If you have a laptop running Leopard Darwin but your built-in keyboard is not working, give this driver a try.

Download Laptop Input Controller Version 1.0

ps: Come to think of it, you may find this kext useful if you are using a desktop with a recalcitrant PS2 keyboard as well.

pps: Miracle! After a year of having misplaced the source code, I found it on a USB stick. It’s now available at Github.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Twitterified 1.2 is out: multi-accounts, mouse gestures, visual ignore…

Based on the very helpful feedback I received from the Twitterified client users, here is version 1.2’s log:

- Multiple accounts support:
– Multiple accounts using the same server
– Accounts using multiple servers (Twitter, Identi.ca…)
– Underlying architecture to eventually support any third-party server as long as they are compatible
- Better error reporting
- Better error recovery
- Mouse Gestures support
- Tweets can now be marked “read
- Obviously new tweets are now easily identifiable
- The application window height is now a setting
- It is now possible to “ignore” someone using the collapsable boxes

Due to the client’s support for multiple accounts, if you are upgrading, you will have to re-enter your credentials. It’s a one-time thing.

Note, too, that starting with v1.1, the client offers to update automatically when a new version is out.

Twitterified Accounts
Showing two accounts…
-

Twitterified Ignore

Sorry, Jeremiah, ignoring you for the purpose of this demo…
-

Twitterified Mouse Gesture
Use Mouse Gesture to mark all Tweets “read”

If you are not using Twitterified yet, go get it!

If you enjoyed this post, make sure you subscribe to my RSS feed!