Archive for the 'REALBasic' Category

07/13 clic clac

Via Bill de Hóra, unicode converter.

Clic clac!

Why go to the web for that? This thing stays out of the way when not needed:

Automatic copy/paste: when you enter the plain text box, it pastes whatever text the clipboard has, and selects it. In the Unicode box, it pastes the content of the clipboard if it matches the \uXXXX format. After conversion, the result is copied back to the clipboard. What say?

Download  Tested on a TiBook 17″ running 10.3.9. Prolly won’t work on MacIntels. Not me faults, Guv’.

06/11 Erlang/gs Event loop

I have now a cool-ish event loop in place that declares a buttonpress/click for each known GUI element. An event loop is created with all elements referenced, and basic messages are implemented [clicks/buttonpresses]. If a pushbutton as “quit” as caption, app termination is provided for. Ditto when closing the window. [Mouse] Button presses provide the number of the mouse button, and the position. What else do ya need? ;-)

Erlang

06/11 Erlang/gs progress

I solved most of my problems with listboxes and grids. I should probably add a couple of other elements, like the editor [aka EditField]. But now is the time to turn to linking the existing elements to events inside an event loop, which looks like this:

loop() ->
    receive
        {gs,_Win,destroy,_Data,_Args} -> bye;
        {gs,_Gridline,click,_Data,[Col,Row,Text|_]} ->
            io:format("Click at col:~p row:~p text:~p~n",[Col,Row,Text]),
            loop();
        Msg ->
            io:format("Got ~p~n",[Msg]),
            loop()
    end.

You set up a receiver and match messages following this pattern: {gs, IdOrName, EventType, Data, Args}

The original in RB’s IDE

The end result in X11

Erlang

06/10 Messing with Erlang/gs

Building GUI apps in Erlang is pretty primitive. And it’s text-only work. As in, you have to hard code GUI elements into a text editor.

W_Window1 = gs:create(window, gs:start(), [{width,789}, {height,544}, {x,100}, {y,100}, {title,"First Try"}]),
CV_Canvas1 = gs:create(canvas, W_Window1, [{y,14}, {x,20}, {width,483}, {height,483}]),
CVP_Canvas1 = gs:create(image, CV_Canvas1, [{'load_gif', "tiger.gif"}]),

Blech…

So I am working on a GUI editor for Erlang, but with a twist I had used before for Python: I am using RB’s own GUI editor to build a nice window, and then I make a call in the window’s Open() event to a library I wrote that outputs Erlang/gs code for said window. The app runs, produces the code, and quits. It’s far from complete, and I am having difficulties with gs grids, aka multiple-column listboxes. But it is already enough to easily produce some skeletton code, and I hope I can then move on to linking GUI elements to code managing events. Like when a pushbutton is clicked, provide basic code to handle this.

More later… But see this already:

The original in RB

The end result in gs/X11

Erlang

03/23 Tokens, Attributes, and pseudo XML parsing in Erlang

I have a very specific need, and I have this wild idea I can solve it with Erlang. Grosso modo, the need is that I have to parse a huge XML file, but I mean something fiercely huge. I haven’t seen it yet – my client has it – but even my very very specific, can break if you move a comma, I am reading this file as plain text parser, which I wrote for this client and this file format, takes forever to parse the file. Attempts to read that file, or similar, albeit a tad smaller ones, with expat et altri was entertaining but fruitless.

So I broke out the big guns. I have three computers at home – well four, but my wife’s old TiBook 15″ is sick – and will prolly have one or two more soon, thanks to recent/current contract work. And one at least will be dual core, or better* so it should be interesting.
* I haven’t decided yet whether to buy a double core or better G5 – since most of my commercial apps are PPC, and OSS stuff can be recompiled and sped up with -mcpu=g5 – or to buy an Intel. We’ll see.

Those two of you who read my posts on Erlang and survived know that I have been playing with concurrency, distributed computing [ridiculously easy to set up in Erlang, but I suspect there are pitfalls lurking right across the corner to bite me…], looping through lists and tuples [of distributed nodes, wink wink], and complaining about string manipulations [for all I know Erlang has a superb set of string manips, but people on #erlang agreed that it’s so so…]. Now, I *need* decent string manips if I am to fake-parse XML. So far, I can start nodes on remote machines, read lines from a file and send these lines to the nodes in a round-robin way, to be processed. Meaning, to obtain the content of the XML – in this case the attributes – and store them somewhere. The “store somewhere” part, I’ll leave for later, we can’t win all battles in one day. Just the word mnesia makes me shiver… For the time being, the parsed output will go to the node’s dictionary. Good enough.

Now, I started working on this with another XML file that has a similar format: the opml file produced by Technorati. It looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!– OPML generated by Technorati Blog Finder –>
<opml version="1.0">
<head>
<ownerName>Technorati</ownerName>
<title>5 blogs tagged Erlang sorted by authority</title>
</head>
<body>
<outline text="3pBlog Mickaël Rémond Performance, Process, P… " description="Mickael Remond’s thoughts on cluster, robust, scalable and distributed computing" htmlUrl="http://www.3pblog.net" xmlUrl="http://www.3pblog.net/rss.php" type="rss"/>
<outline text="Life’s too short to brag about microcosm a… " htmlUrl="http://sungnyemun.org/wordpress" xmlUrl="http://sungnyemun.org/wordpress/wp-rss2.php" type="rss"/>
[…]
</body>
</opml>

The idea is to extract the 5 attributes – not all five may be present, so it’s actually a good idea to preset the dictionary with the five keys and empty values – and return a tuple, list, dictionary, whatever. Read the file until you hit <body> and then start reading lines until </body>. Ok, can do. Then, for each line, I read the “header” [<outline ], and then hope for the best and pray that the tag/attribute pairs are properly formatted – no reason to doubt, they’re machine-produced, right? So I need a function to retrieve the tag [which I called token], and then the attribute. This until I hit “/>”, the end of the line, as far as the “parser” is concerned. I know, many things could break, but if the format is consistent… we should be safe!

Here goes:

-module(extract).
-compile(export_all).

doit(S) -> % that’s the function we’ll call
% reset the dictionary
put(text,""),
put(type,""),
put(htmlUrl,""),
put(description,""),
put(xmlUrl,""),
proceed(S).

proceed("/>") -> % This is the closing tag, we’re done.
{{text, get(text)}, {type, get(type)}, {htmlUrl, get(htmlUrl)}, {description, get(description)}, {xmlUrl, get(xmlUrl)}};
proceed([$< |T]) -> % opening tag, read the header
{S1,Head}=extract_header(T),
proceed(S1);
proceed([32|T]) ->
proceed(T);
proceed(S1) -> % any other possibility
{S2,Tk}=extract_token(S1),
{S3,Attr}=extract_attribute(S2),
Atom=list_to_atom(Tk),
put(Atom,Attr),
proceed(S3).

extract_header(L) ->
extract_header(L,[],0).
% the last argument, 0 and then 1 is just a state marker
extract_header([H|T],Acc,0) ->
case H of
32 -> extract_header(T,Acc,1);
Other -> extract_header(T,[H,Acc],0)
end;
extract_header([H|T],Acc,1) ->
case lists:member(H, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890 -_") of
true -> {[H|T],lists:reverse(lists:flatten(Acc))};
% Return header + remainder
Other -> extract_header(T,Acc,1)
end.

extract_token(L) ->
extract_token(L,[]).
extract_token([H|T],Acc) ->
case lists:member(H, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890 -_") of
true ->
case Acc of
[] -> extract_token(T,H);
Other -> extract_token(T,[H,Acc])
end;
false -> {[H|T],lists:reverse(lists:flatten(Acc))}
end;
extract_token([],Acc) ->
{">",lists:reverse(lists:flatten(Acc))}.

extract_attribute(L) ->
extract_attribute(L,[],0).
extract_attribute([H|T],Acc,0) ->
case H of
34 -> extract_attribute(T,Acc,1); % Open "
Other -> extract_attribute(T,Acc,0)
end;
extract_attribute([H|T],Acc,1) ->
% " open
case H of
34 -> {T,lists:reverse(lists:flatten(Acc))}; % Close ". Return Acc
Other -> extract_attribute(T,[H,Acc],1)
end.

70> S2="<outline text=\"3pBlog Micka\303\253l R\303\251mond Performance, Process, P… \" description=\"Mickael Remond’s thoughts on cluster, robust, scalable and distributed computing\" htmlUrl=\"http://www.3pblog.net\" xmlUrl=\"http://www.3pblog.net/rss.php\" type=\"rss\"/>".
71> extract:doit(S2).
{{text,"3pBlog Micka\303\253l R\303\251mond Performance, Process, P… "},
{type,"rss"},
{htmlUrl,"http://www.3pblog.net"},
{description,"Mickael Remond’s thoughts on cluster, robust, scalable and distributed computing"},
{xmlUrl,"http://www.3pblog.net/rss.php"}}

Sweet, no? :-)

I am sure this is clumsy. But.It.Works. Now on to bring all the pieces together… And learn about mnesia and stuff.

Erlang