The following is adapted from an email I sent to the OmniOutliner-users mailing list. I should also add that after fighting with this stupid WP editor, I’m having a very hard time convincing it that I really want to display ‘raw’ html instead of it helpfully converting it right back to entities for me. I also understand that the code is probably very hard to read, so if you’re interested in checking it out, I would recommend that you download the attached file, convert; hopefully that will make much more sense.
In my email, I asked:
Is there an SDK for developing OmniOutliner export plugins? If so, or if not, would there be sufficient interest in creating a BBCode export option from OmniOutliner? Just throwing it out there.
I ask, because I was asked to post some notes I took in OmniOutliner Pro… on a web discussion forum where they use BBCode instead of regular HTML to format stuff.
Embedded lists in BBCode look like this:
[list]Item 1
[list]Item 1a
Item 1b[/list]
Item 2
Item 3
[list]Item 3a
Item 3b[/list]
Item 4
The above would produce this output:
Item 2
Item 3
Item 4
Fairly simple and straightforward, but I was kind of racking my brain as to how to get my OmniOutliner document into this format. So I wrote this PHP script, called ‘convert.’ In my example below, I copied this script into my Documents -> planning folder, where I’m keeping the rest of my files.
---------------------------------convert----------------------
#!/usr/bin/php
// Take first command line argument as the filename
$fa = file($_SERVER["argv"][1]);
$prevtabs = 0;
$ent_table = array("-" => "−", " " => " ", "+" => "√");
// test it out first
//for ($i=0; $i < 10; $i++)
for ($i=0; $i< count($fa); $i++)
{
$match_array = array();
$itworked = preg_match("#^([\t]{0,})(- \[[+\- ]\] )(.*)$#", $fa[$i], $match_array);
if ($itworked)
{
$curtabs = strlen($match_array[1]);
$thediff = $curtabs - $prevtabs;
if ($thediff > 0) // means we indented inwards.
{
if ($i > 0) // not on the very first line
{
print "∇ " . $prev_line;
}
print str_repeat("[list]", $thediff);
}
else if ($thediff < 0)
{
if ($i > 0) // not on the very first line
{
print "• " . $prev_line;
}
print str_repeat("[/list]", $thediff * -1);
}
else // same, no change
{
if ($i > 0) // not on the very first line
{
print "• " . $prev_line;
}
}
// set this as the previous line amount now
$prevtabs = $curtabs;
$prev_line = "[" . $ent_table[$match_array[2][3]]. "] " . $match_array[3] . "\n";
}
else
{
// The match failed, so err on the side of caution and print the previous line with a bullet,
// then set the new previous line to be the whole line we couldn't match
if ($i > 0) // not on the very first line
{
print "• " . $prev_line;
}
$prev_line = $fa[$i];
// $prevtabs // not gonna change it, hope it stays the same. ack.
}
}
// last line has no children, by definition, so:
print "• " . $prev_line;
if ($prevtabs > 0)
{
print str_repeat("[/list]", $prevtabs);
}
?>
-------------------------------------------------------------------
Usage:
Export your OmniOutliner document as tab-separated values (a .tsv file. Except OmniOutliner’s export insists on making it end in .txt. Ugh. Can we please get a ‘Hide file extension’ checkbox to uncheck, and then override the default?)
In the Terminal, change directories to the folder containing this script, and your TSV file.
unixprompt> cd ~/Documents/planning
I called my exported file, planning_notes.txt
And I want my output file called, ‘output.txt’:
unixprompt> ./convert planning_notes.txt > output.txt
If it doesn’t work – remember to make the script executable first:
unixprompt> chmod 755 convert
If you don’t redirect the output into a file, it will just print right in the terminal
window, which may be preferred:
unixprompt> ./convert planning_notes.txt
[b]∇ [ ] Intro[/b]
[list][b]∇ [ ] Who are we[/b]
[list][b]• [ ] and what are our goals while we’re here?[/b]
[/list]∇ [ ] Thom
[list]• [ ] Tech Team Director
• [ ] How can tech team help?
[/list]
[/list]
etc.
* * *
Some notes about the code and formatting -
I chose to use the • entity, whose code is • for all of the ‘leaf’ items, and I decided to use the ∇ (∇) entity, the downward pointing triangle, to represent ‘branches’ (rows with children).
I did this by not printing each line immediately; instead I saved it until the next time through the loop, where I could see whether the next line indented further. Based on this, I knew whether to make it a bullet or an open ‘disclosure triangle.’
After either the triangle or bullet, I kept the square brackets containing either a space (unchecked), a ‘minus’ entity (−) or a “√” (which is √), for a ‘checked off’ item. The conversion table is near the top, in the $ent_table array.
Note that I commented out a ‘first ten lines only’ version of my for-loop — I’d used that earlier so I could test and see if it would work, before turning it loose on my whole document!
One frustrating thing was, choosing to start from the tab separated values format didn’t give me any style information. So I still ended up going through my document once it had been exported and converted, and [b]re-bolding[/b] certain lines after the fact. This is obviously not the most ideal solution, but it’s a solution. (I made a custom BBEdit Glossary folder called ‘BBCode’ with a ‘bold’ file in it, simply containing [b]#select#[/b] and I assigned that to a key. Then I selected each line I wanted to bold and hit my hotkey.)
I started out with a much simpler version of this script, but then I fell victim to ‘feature creep’ and I kept making it better… and now I’m really happy with the results.
Anyway, hope this script is of use to someone out there.