Thursday, September 09, 2010

Some Freemind Scripting

I go back and forth, trying to find my ultimate tool for knowledge and task management. I have been switching between TiddlyWiki, email, Freemind, and other wikis and online/local tools. The pendulum has swung back to freemind for the moment, and I'm finally getting around to scripting what I need in it. As some background, Freemind is my preferred mind-mapping application, whether online or on my desktop. I also keep coming back to it as my knowledge management tool.

I downloaded the source code of freemind, since documentation is non-existent. What is documented is that there is a groovy scripting environment. The main classes used are MindMapController and MindMapNode. The controller is used to make and changes to your mindmap, and the node is used for reading and traversing. The environment provides you c as the current MindMapController and node  as the current node. Just so you know, I am by no means writing idiomatic groovy. I am using Freemind version 0.9 RC7

With this bit of background I wrote the following short script:


import freemind.modes.MindMapNode;
import freemind.modes.mindmapmode.MindMapController;
import freemind.modes.attributes.Attribute;
import java.text.SimpleDateFormat;

def now = new java.util.Date();
def fmt = "yyyy-MM-dd HH:mm";
def formatter = new SimpleDateFormat(fmt);
def nowString = formatter.format(now);
def status = node.getAttribute("task");
if(status == null){
    def attr = new Attribute("task","todo");
    c.addAttribute(node,attr);
}
else{
    c.editAttribute(node,"task","todo");
}
if((pTS=node.getAttribute("task-changed"))==null){
    def timestamp = new Attribute("task-changed",nowString);
    c.addAttribute(node,timestamp);
}
else{
    c.editAttribute(node,"task-changed",nowString);
}


What it does is to add a pair of attributes to a node.

At first, what I attempted to do was to associate it with a pattern. In other words, from the context menu for a node, I went to Physical Styles -> Manage Patterns -> Needs Actionand at the bottom of that page opened the script editor, inserting the above script. I ran it from the script editor, and it acted as expected, to my pleasant surprise. Then I saved and exited, assuming that every time I hit F4 on a node, the script would be run on that node. Alas, that was not the case. In fact, to my chagrin, when I opened up that attached script again, I found pieces had been cut off, and all my formatting was gone. With a little probing, I found that the script was saved in my personal patterns.xml file, and probably the saving and parsing isn't quite working right.


Next step. I just saved the script to a node. That is, with a node selected, I went to Tools -> Script Editor, pasted in the script, and then hit ALT-F8 to evaluate it. That worked.


The approach I am going with now is to associate the script with the root node. As a first step, I look for any node that starts with the string "todo::". If that is present, I create attributes indicating this node is a task, and the time at which it was set as a task, and remove one of the colons from that prefix string, so that the node doesn't get reprocessed. Then I can use a filter to find just the task management nodes. Granted, I could do this with filters, but this allows me to add some tags on when a task was created and when it was completed.


Here is the final script


import freemind.modes.MindMapNode;
import freemind.modes.mindmapmode.MindMapController;
import freemind.modes.attributes.Attribute;
import java.text.SimpleDateFormat;

def setTags(MindMapNode pnode, MindMapController pc, String pstatus){
    def now = new java.util.Date();
    def fmt = "yyyy-MM-dd HH:mm";
    def formatter = new SimpleDateFormat(fmt);
    def nowString = formatter.format(now);
    def status = pnode.getAttribute("task");
    if(status == null){
        def attr = new Attribute("task", pstatus);
        pc.addAttribute(pnode,attr);
    }
    else{
        pc.editAttribute(pnode,"task", pstatus);
    }
    def pTS=pnode.getAttribute("time-" + pstatus);
    if(pTS==null){
        def timestamp = new Attribute("time-" + pstatus , nowString);
        pc.addAttribute(pnode,timestamp);
    }
    else{
        pc.editAttribute(pnode,"time-" + pstatus, nowString);
    }
}

def processTasks(MindMapNode pnode, MindMapController pc){
    // check if text is tagged
    def nodeText=pnode.getText();
    def matchTodo = (nodeText =~ /todo::/);
    if(matchTodo){
        setTags(pnode, pc, "todo");
        nodeText = matchTodo.replaceFirst("todo:");
        pc.setNodeText(pnode,nodeText);
    }
    if(pnode.hasChildren()){
        pnode.childrenUnfolded().each() { aChildNode ->
            processTasks(aChildNode, pc); /* recursive invocation */
            def placeHolder = 1;
        };
    };
}

processTasks(node, c);



Monday, July 12, 2010

WSJ on men's razors

Razor Burn. -- The Wall Street Journal has a piece on men feeling the pinch of the artificially expensive market for the latest razors. If you've been reading this blog, you've heard my own opinions on this matter, so it seems it's time for an update. I've been using my Gillette super speed for the most part for over two years now. I also picked up a Merkur classic with the comb edge when it seemed my Gillette had disappeared in a move. The Merkur is a bit aggressive for me, I tend to cut myself more often with it, especially on my head. I picked up a pack of 100 Derby razors on ebay for about US$25. After two years, I still have about 15-20 left. I typically generally shave every other day, but I have a very tough beard that grows fast, and I shave my head as well. It takes a bit more care than using cartridge razors, but I'm at the point that I can pretty reliably shave almost as fast, and without cutting myself.

When I was shaving with a five-blade solution, I was paying about $3.50 per cartridge. I see I can get them for about $3 online. If we assume one cartridge per week, I was paying $156/year just for blades, and now I am paying about $10/year.

Tuesday, June 22, 2010

Fast food versus Healthy Food

Came across a discussion of food perception on wise bread. I take issue with fast food restaurant versus healthy restaurant, where french and italian food is included in healthy. Replace 'healthy' with 'fancy' in the article, and it is all more sensible. Anyone who goes to a restaurant that doesn't publish nutritional information can't assume that the food meets or doesn't meet any dietary guidelines. What's in the salad dressing? Are they using whole milk cheese or skim milk cheese. Just how much oil or butter was used to pan fry that dish? For example, american's tend to think of asian food as healthy. Having cooked chinese food for the last eight years, knowing what my recipes call for, and assuming short cuts on the part of restaurants, I'm no better off than eating typical american fare. If it's creamy soup, it being Thai doesn't mean the cream will have fewer calories.

Monday, June 21, 2010

The logic of paleo diets

I am sympathetic to the idea that we return to hunter-gatherer diets, but I find myself thinking about what that actually means. How did we happen to start farming? How did we decide as gatherers what was edible? Was it starvation that drove us to try new foods? I like the idea of climate change driving early agriculture. "Gee, these grass seeds are hard to eat, but I'm hungry. Gee, look at that, I survived the winter eating grass seeds and roots." I'm afraid the logic that some paleo-philes present as to the transition from hunter-gatherer to farmer feels very weak to me. I think that without that transition, perhaps humans would have come close to extinction, if we didn't disappear altogether.

Tuesday, June 01, 2010

Security Vulnerability = Sexy Bug

Watching Billy Hoffman's JSConf talk, "Javascript, the Evil Parts". A favorite point he makes: security flaws in software are unintended software behavior, that is, they are bugs, albeit sexy because they relate to security. When a developer says security is not their problem, they are declaring that they are not responsible for bugs that happen to affect security. Fail.

Thursday, May 20, 2010

Self-Disciplined Children do better in school

Came across an interesting study, whose results show that self-discipline has a higher correlation with academic achievement than intelligence. No surprise really, as any hyper-intelligent slacker can tell you. The real question is how much of self-discipline is nature and how much is nurture.

Tuesday, March 02, 2010

Thunderbird on Ubuntu

I have been having just a wretched time with Thunderbird on Ubuntu Linux 9.10 the last few months. Thunderbird would regularly peg an 100% of one of my CPUs. Today, to address this, I tried using swiftdove, which supposedly has better performance. I had exactly the same problem, if not worse.
Don't know why I didn't think of this before, but I started to look at the plugins I am using. I have been using Lightning, Tag Toolbar, and MailTweaks. I turned them all off, no more 100%. I turned them on one by one, and found the culprit in Lightning. For reference, I was using lightning 1.0b1. We'll see if sunbird behaves better on its own.
Further investigation shows my big problem is with Remember The Milk. I ended up with the same problems when I ran Sunbird, and subscribed to my RTM tasks. Once I unsubscribed, both in Sunbird and in Thunderbird Lightning, the excessive CPU utilization cleared up.
It would appear that someone isn't testing on Linux, because I don't have these issues on Windows XP.

Friday, February 26, 2010

linux telephony

It has been a sore point for me for a while that I haven't been able to get decent telephony on my linux desktop. I'm running Ubuntu 9.10 on an old HP two Xeon processor workstation. I'm working remotely, cell phone coverage it near non-existent at my house, my T-Mobile Blackberry doesn't seem to do a good job of staying connected to my wifi router, and I want to keep my home phone free (I spend about six hours a day on the phone for work).

From work, I have a windows laptop running XP SP3, I use a Cisco VPN to connect into the office, and have the choice of two Cisco softphones to use. Problem is, my laptop has a knack for hanging and bluescreening just before meetings. Like right now.

I have Google Voice. Ability to forward calls to Gizmo5 means I can do free SIP to PSTN. But I need to be able to do DTMF, for the various teleconferences I need to join. Skype doesn't do it. Gizmo5 doesn't seem to work with my audio setup. Ekiga screeches at me. Finally, when I log Twinkle into Gizmo5, I have happiness.