Hobby-hacking Eric


So tired... skipped work today because i was so so close. But here I am. Checkpoint reached. Got a working prototype of wxdarcs submitted to the list.

Had a long post detailing all the issues I went through, but somehow got lost. That's the trouble with these web tools. You lose stuff so easily.

Tests seem to run slow in gui mode. Can't figure out why.

Bed... at last, I may go to bed.

And go to work tomorrow. Looking forward to doing anything other than my hobby...


another dateparser error

Tommy Pettersson observed today that the dateparser.sh test was failing on "4 score, 7 years ago". Nothing wrong with the date parser itself. Apparantly, his computer doesn't like dates from 87 years back. Mine doesn't like them from 105 years back. But parsing score of years, as well as expressions like "tea time", "bed time" and "proper bed time" is completely silly and pointless, so I submitted some patches to remove this functionality. Functionality I put in on a whim. Geez. I think half of my patches to darcs are corrections to the other half of my patches.

no start twice

Yippee! I found it! And this tiny moment of joy has made the whole miserable sniffly headachy weekend (got a cold) worth it.

I ferreted out the problem by making a small wxhaskell demonstrator and trying to figure out what Control.Exception.bracket is all about. As far as I can tell, it doesn't look like more than just a >>= c >>= b, so we can forget about it. The problem is more to do with the start function. Here's what my tester boiled down to:
main = createGui ""

createGui txt =
do putStrLnAndFlush $ "opening " ++ txt
start $ gui txt
putStrLnAndFlush $ "closing " ++ txt

gui txt =
do f <- frame [text := "Howdy " ++ txt ]
closeBt <- button f [ text := "Close"
, on command := close f ]
spawnBt <- button f [ text := "Spawn"
, on command := createGui $ txt ++ "."
set f [ layout := margin 5 $ column 2 [ widget closeBt
, widget spawnBt ] ]
putStrLnAndFlush $ "gui created " ++ txt

putStrLnAndFlush x = putStrLn x >> hFlush stdout

This demonstrator allows us to replicate the issue I was having with wxDarcs. That is, you click on the spawn button to create a second window, and if you close the second window, it does not seem to come back. Exactly like yesterday, if you close the first window, you get a bus error. All you need to do to fix this is to realise that start indeed performs some kind of voodoo, and this voodoo is something you may only perform once. It was one of my theories, but I had written some code into Record.lhs to not call start, but it didn't seem to work. Maybe I had just confused myself or something. So, the simple fix is just to change the code so it looks more like this:
main = start $ createGui ""

createGui txt =
do putStrLnAndFlush $ "opening " ++ txt
gui txt
putStrLnAndFlush $ "closing " ++ txt

This way, when you call that createGui function from within the gui, you're not calling that start function a second time. Woohoo! Then maybe we're not so far from getting wxDarcs out the door so that other people can hack on it and so that I can start working on other stuff.

radical departure for wxDarcs

This morning before getting up, I had the sudden thought that I was aiming for something truly pointless in the previous incarnations of wxDarcs. The story goes that wxDarcs was supposed to provide you a change-oriented view your repository instead of a task-oriented one. That is, instead of deciding "I want to do darcs send" and then choosing your patches, you first select your patches and then tell the gui "I want to send these guys".

I realised that there a few headaches that I did not really want to deal with, and the task of building a darcs gui was getting more and more complicated as the days went on. All sorts of stuff I hadn't thought of, like for instance, when you do a darcs send, the only patches the console interface shows you are the ones that don't already exist in the remote repository. You don't get that with the change-oriented view. And also, the business of splitting the commands up so that they are only available in the right contexts would be really annoying to deal with: for example, at first, I only had the Revert in the 'Changes tab, and the Record option in the Whatsnew tab. But that's annoying, because you have to think to go to the Changes tab in order to get a Revert button. What if your brain is hardwired in task-oriented mode? What if you're saying to yourself, ok, I want to send in my changes? You shouldn't have to think, "oh, I need to go look at the changes tab first".

So the original goal was to resurrect the wxhaskell code, and I'm now going to aim more towards that direction. Well... in fact, that's already been long done and that patches are waiting acceptance. My new direction is to make more use of the original wxhaskell code. For instance, when you click on the Record button, all my gui code does is execute the record command, which launches its very own GUI. None of this select-your-patch-and-then-your-operation nonsense.

Here is what it looks like now. It's the same story: you first start out with an empty repository viewer:

When you click open, you get the stardard directory-choosing dialogue from your operating system. You choose darcs repo, what you get is this interface. Notice that I now use the tree widget I had for Whatsnew:

I think this is a clear improvement. Simpler code, simpler user interface, much more down to earth and direct. No more silly tabs. And now, if you click on the Record button, you get the original David Roundy (I assume) gui for Record, this being a result of me giving up on the change-oriented approach to darcs. Oh, and another thing I managed to implement is this business of the --gui flag. Now, there is no distinct wxDarcs main module. If you call darcs with just the --gui flag, or if you call the program as wxDarcs (i stuck a cp darcs wxDarcs in the Makefile), you get the wxDarcs standalone interface.

But here's a major piece of bad news. A huge blocker, and clear evidence that I don't actually know crap about haskell or programming or computers. When I tried to link my buttons to commands is that the commands refuse to relinquish their locks when you close the guis which are associated to them. This means, for example, that you can't Record some stuff, and then Send it, because darcs is always stuck with a lock from Record. It doesn't matter whether you close the window by cancelling or recording, it simply does not come back. Plus, when you close all the windows of wxDarcs, you get a bus error. Yipee.

Totally stumped here. It's as if we never make it out of the function for the inner gui, even when we close the window. The whole record command is wrapped with a withRepoLock, and for some reason, you never get to the closing end of that bracket. Yet you do when you're calling the record gui from the command line. So confused.


three tabs

Merged a good chunk of code together tonight, and combined two of the user interfaces. This is what wxDarcs looks like now. When you first open it, you get a single tab with a bunch of disabled buttons:

Hopefully, it should obvious enough that you need to open a repository. When you do, the interface gets a little fancier:

The two tabs, "Whatsnew" and "Patches" are the same as yesterday.

All of the buttons now do something, though not something very useful. They display the following dialogue box:

I'm hoping that some of these commands won't be too difficult to implement. It should consist mostly of de-anonymising the business end of the darcs commands. For example, the Record command calls with_selected_changes_to_files with a bunch of arguments and a huge lambda term starting with \ (skipped,chs) ->. The idea is that the anonymous function is supposed to be run on the whatever patches the user selects via the SelectChanges.lhs code. It seems like we could assign a name to this lambda term, say, something like "record_job" and invoke that from the standalone GUI.


wxDarcs widget progress

More gui code coming together. It's really weird. I actually very much dislike working on graphical interfaces (maybe), but I spend so much time working on them and writing about them that you'd think i did it for fun or something. Maybe just a desire for things to be correct, but this kind of stuff is so outside of my zone of competence.

Anyway, so here's what I have so far. When you first launch wxDarcs, you get two buttons:

When you click on "Open repository", you get a standard directory selection dialogue:

If you select a folder, it opens up the repository viewer, which has two tabs, an unrecorded patches tab, and a recorded patches tab. Here are the unrecorded patches (what's new) :

And the recorded patches (Patches) -- this is implemnted wrong, but I don't care; my job here is to get the prototype running, remember?

That's all. Remember that the buttons don't actually do anything.

Also, the 'pull' command does not enter this model... maybe you select pull from a menubar or a toolbar, and it adds a new tab. Maybe it opens a new window, or something.

Now, I had some worries last night about keeping the patch display up to date. To keep things simple and prevent things from going horribly wrong, I make the following two recommendations:
  1. all commands should cause the repository gui to reload complete, thus displaying the new set of what's new and recorded patches
  2. only one repository may be open at a time

This will be pitifully unsophisticated, very far from what I first proposed in my mail. I'm really hoping that this getting the ball rolling will lead us to a nice powerful GUI for darcs, one day.


standalone gui

Had some trouble in the beginning with the standalone gui - it seemed to be calculating every single patch in the repository or something, not just the unrecorded changes. Don't really understand how everything works underneath, but using withRepoLock fixed the issue.

Here is a view of the standalone gui so far:

Doesn't look like much different, but notice the buttons on the bottom. The idea here is that the standalone gui is something you launch without a repository in mind. Either you choose a repository, or it selects the previous one you loaded (we can talk about this some more). It presents you with a list of unrecorded modifications, as well as a list of patches in the repo. These will likely be in two seperate tabs, each with its own set of buttons. Only the first tab is implemented, and even that is not complete. For instance, the buttons are not yet active.

I think i'm starting to get bored with this project and might think about looking for a new hobby. I dunno. All this gui coding stuff is tedious, makes it feel more like work than play. We'll see. Maybe some random burst of inspiration will strike. But I'll at least aim to get a minimal version of this standalone gui running, and send it as a patch. Maybe once it's out the door, the joyfulness of hobby hacking will come back on its own. Or maybe going to FOSDEM will help.



wxDarcs - that's my unimaginative name for the standalone "native" darcs GUI. Got some hacking to the makefile and a wxDarcs.lhs file. Doesn't do much. Lets you select a repository. Whoopeedo. Kinda worried about concurrency type stuff, like, I don't know, you select a patch, and by the time you decide you want to record it, somebody else has already obliterated it or something. Making GUIs is tough work. Not something I'm cut out for. I dunno. Figure it's not really my job. I'm just here to get the infrastructure up, make a useful prototype, get the ball rolling.


Just noticed something I like about the present gui code: it's actually pretty well factored. For some reason, I was walking around thinking there was some kind of redundancy between SelectChanges.lhs and Record.lhs when in fact the Record.lhs gui code just calls a function in SelectChanges. Great! So the only real redundancy is with Whatsnew, which has a slightly different task. So now the two big problems I have are
  1. how to have a nicer patch view for SelectChanges - i'm trying to think of ways i can do this without the luxury of resizable widgets
  2. the standalone gui front end

One insight on the dynamically sized widgets thing - one thing I could do upon resizing one of the child widgets, maybe is to reset the layout of the parent window. Kind of a ugly hack, but this would allow the parent window to take the new widget sizes into account.

Not much otherwise. Made a small change to SelectChanges.lhs to reformat tabs as spaces, same old issue with any character after a tab being completely dropped.


Layout bugs in Record.lhs fixed!

Aha! Found out what was causing the layout to go all funky. It turns out that for some reason (maybe a bug, maybe a feature) scrolled windows have to go into their own panels, otherwise they interact badly with their neighbouring widgets. So got Record.lhs fixed. Turns out that SelectChanges.lhs was also suffering from the same layout bug. Noted that whoever wrote the original gui code (i'm too lazy to trawl the repo to find out) did a pretty good job. Some nice, clean elegant ideas that integrate well with the rest of the darcs code. For example, implementing SelectChanges as an optional GUI was cool because then you can use the same code for lots of commands without lifting a finger, Pull, Apply, Send, etc. Now that this bug is done for, I guess I shall turn my attention to building a simple standalone interface.

The standalone interface won't do very much. It'll just let you select a repodir and then some operations. Maybe it'll provide the patch view and changes view in tabbed windows or something. I don't aim for fancy or even complete. Just operational and standalone. Enough to get people to understand that this code may actually be worth maintaining and that they should dive right in!

Oh, Juliusz suggests that I put up some screenshots and link them from the wiki. Whatsnew, I already showed last week. So here are Record and Pull. If you like what you see, please remember that this is *NOT* my doing. Somebody else (David?) wrote this code, and the only thing I did was tweak it so that it worked as s/he intended:

Also, a special shout-out to Johnathan Mah and Tom Counsell. In the event that you folks ever stumble upon this blog, I hope that you'll be inspired to go learn HOC and port your work to Haskell so that you get better integration with Darcs AND all the cool OS X features. This wxWidgets interface is like Mozilla Firefox, whereas your Patchworks are more like Camino. The former is cool because it runs everywhere and lets us have a common platform. The latter is also cool because of its integration with OS X, something we probably won't achieve with universal code.

There was some interest in the GUI by a user on #darcs today. I estimated that it would take me till next weekend to get something functional out the door. Maybe that's a little optimistic.

Don't know what I'm doing. Trying to produce a universal patch viewing control that could be shared by Record and Whatsnew. What would be nice is to be able to select a patch (Record) as well as to collapse its view (Whatsnew) and do other cool stuff like select all the patches for a given file. What I have in mind is some kind of fancy tree-checkbox widget where each tree item is associated with a checkbox. If that's not possible, i'd like to be able to select multiple items in the tree, but setting wxTR_EXTENDED does not seem to help.


Made some discoveries in how wxWidgets works. Namely,
  • treeCtrl comes with its own scrolled window. I wonder if there's an easy way to get a non-scrolled treeCtrl, because then maybe I could simulate my tree-of-checkboxes idea
  • I had been stupid about how I used treeCtrlAppendItem. I was zipping around trying to append to a given node number. Just assumed that one of the Int arguments was a node position, but in fact, it has nothing to do with that. It's just a position in the image list. Each tree node can be associated with an image, and when you append the item, you can specify what its image is. Perhaps I could use this image functionality to represent selected and unselected item. After all, the append functions take arguments for the image when it's selected and when it's not.

I need to remember not to fixate on treeCtrl. The original source code had a nice simple idea where clicking on a patch would toggle it between summary and full size. But it's just that there's this issue with wxhaskell where resized widgets do not retain their new size... so that's a blocker.

Also having some trouble with the Record gui. Some resize bug somewhere. The button bar is hidden when you resize the window, and reappears sometimes. Weird. Will have to compare with code from my projects at work to see why my stuff behaves better.


Droundy believes that we should still consider the issue from yesterday as a regression, so I sent in a couple of small patches. Sort of a bad habit of mine, the whole forest from the trees thing. Sometimes i obsess with being precise about things when there's a fundamental issue at hand such as "uh, my stuff doesn't work anymore". Anyway, that was an easy fix.

Also, regarding that Record.lhs business: darcs diff --last=2000 shows that at some point in time, those slurpies were being ignored by the gui code, so I too will do the same. There seems to be some layout bug where the buttons (Record and Quit) are hidden by the other widgets. I'll need to look into that later, but for now, the goal was just to make the code compile.

Was pleased to discover that it is not the entirety of wxhaskell's macosx-app script which is neccesary. A simple /Developer/Rez does the trick. That's good news. Means we can install darcs in /usr/local/bin, run /Developer/Rez on it and it will give us a functioning GUI. So I updated the Makefile accordingly. So this brings us three patches closer to a functioning gui, all sent to darcs-unstable:
  1. freshen the code so it compiles
  2. reimplementation of Whatsnew widget
  3. MacOS X stuff for the makefile.

Guess the next thing to look at is writing the code for a standalone gui that builds off this preexisting code and tries very hard to co-exist with it.


Record.lhs (gui)

Spent the evening stripping down my GUI code trying to get things down to the non-invasive ideal mentioned in yesterday's post. The good news is that all the original gui code now compiles and that I've managed to get my Whatsnew tree view of patches integrated into the original Whatsnew.lhs. Bad news is that I still have no idea what the SelectChanges.lhs stuff is supposed to do and even worse, I had to comment out a big chunk of code in Record.lhs because the function it calls has evolved since the last time somebody touched the GUI code. Here's the relevant bit of the code I commented out:

do_actual_record opts (s1,s2)
n date my_a my_log []
(map tp_patch $ get_first_choice rpc)
(map tp_patch $ get_middle_choice rpc++
get_last_choice rpc)

The new version of do_actual_record does not use the (s1,s2) slurpies. I wonder what I'm supposed to replace them with, then? I don't suppose anybody's reading this and feel qualified to comment?

Oh and besides from the that, the darcs record gui seems to be pretty nice. You use checkboxes to select the patches you want. Maybe a few extra buttons like 'select all' or maybe ability the select all the patches for a while, but overall the layout seems useful.

In other news, Zooko found a possible bug in the date parsing code. I don't think it's a bug, but one of these strange creatures that looks like a bug, but is in fact an unpleasant truth revealed by a bugfix. It's one of those cases where instead of pretending to work, the software gives an error message and as a result the user thinks a bug was introduced in the new version, when in fact the new version had simply stopped lieing to the user.


So yesterday it occured to me that I should shelve some of my GUI implementation ideas, namely, putting all the gui stuff into their own seperate files, completely apart from core darcs and letting it all have its own namespace.

The darcs code has this interesting idea that certain commands should have a -gui flag, and that when you pass this flag to a command, like darcs whatsnew -gui then it pops up a little graphical window. I guess this would be a useful thing to have. I'll have to work out how all this resource fork stuff on the Mac works out, whether it'd be possible to have the darcs binary do the graphical stuff outside of this whole appbundle thingy, but meh, just a technical detail right?

At some point I will have to create a seperate Main module just for a graphical darcs. This would be for the double-clickable version of darcs on a Mac or a Windows box. When you call this version of darcs, the first thing it should present you is either the control centre for your most recent repository or a file selection dialogue asking you to select a repository. But this alternate main module need to involve moving a bunch of code around like I first imagined.

The main idea then is that I want to respect the old code and the old ideas. Try to make my patches minimal and non-invasive. So what I'm working on now is the following
  1. get the gui code to compile - not to work, just get it so that when you do ./configure --with-wx and run make, ghc doesn't yell at you for all the dust the code's been collecting
  2. import my tree-control stuff into whatsnew so that at least that piece of the gui works
  3. figure out how this should work out patch-wise; do i want to submit a patch which comments out the stuff I'm not ready to work on yet just so it compiles? Should i wait till I get everything somewhat working again?
  4. edit the makefile, make sure macosx-apps is called on the darcs binary
  5. figure out if there is any way to make the graphical stuff work on a standalone darcs executable without a surrounding bundle


What the heck is going on here?

I find that I really like keeping logs of things as they progress. And for some reason, I like it even better when they're public. I made this discovery when I started logging my daily progress at work, and figured that maybe now that I seem to be always involved in some kind of computer hobby activity or another, I might enjoy keeping a public log of that as well. Kinda ashamed of the public thing. Always needing to be showing something to somebody. Worse than a five year old.

Anyway, so the hobby of the week is working on Darcs. Not doing anything fantastically useful, right now trying to dust off the graphical interface code and get it working again.

Oh yeah, and anything before this post was added after the fact and back-dated.

Whatsnew display seems to work now! I'm doing something horribly abusive with the tree widget (each line in the patch is a tree node), and stayed up till 3h to get it working. I must be stupid or something.


Well, since I can't really use dynamically sized widgets, i'm thinking of a two-column patch browser arrangement for whatsnew. If I can get whatsnew, changes, and a repository selector working, I think we can release this as a rough draft. Current problem is I can't figure out to make widgets accept not being at maximal size (especially when they have a scroll window


Shoot - can't figure out layout issue. Minimal example of why Whatsnew's flexible guipatch widget doesn't work. WF response from wxhaskell mailing list
module Main where 
import Graphics.UI.WX

main = start $
do f <- frame [text := "Layout testing"]
st <- staticText f [ text := "no" ]
set st [ on click := \_ -> set st [ text := "yes\nyes" ] ]
set f [ layout := widget st ]


Got Darcs.Gui stuff in Makefile. Main just calls the Whatsnew Gui. Would like to hack on this some more, get it so that you choose a directory on opening, make the whatsnew gui actually do something useful, add general interface so that people get the idea to add their own commands.

Blog Archive