Omnioutliner to BBCode conversion - my php script

Thom Brooks omni_groupie at unithom.com
Thu Jul 13 01:06:18 PDT 2006


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 1
 		Item 1a
 		Item 1b
 	Item 2
 	Item 3
 		Item 3a
 		Item 3b
 	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
<?php

// Take first command line argument as the filename
$fa = file($_SERVER["argv"][1]);

$prevtabs = 0;

$ent_table = array("-" => "&#8722;", " " => " ", "+" => "&#8730;");

// test it out first -- first ten lines only!
// 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 "&#8711; " . $prev_line;
 			}
 			print str_repeat("[list]", $thediff);
 		}
 		else if ($thediff < 0)
 		{
 			if ($i > 0) // not on the very first line
 			{
 				print "&#8226; " . $prev_line;
 			}
 			print str_repeat("[/list]", $thediff * -1);
 		}
 		else // same, no change
 		{
 			if ($i > 0) // not on the very first line
 			{
 				print "&#8226; " . $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 "&#8226; " . $prev_line;
 		}
 		$prev_line = $fa[$i];
 	}
}
// last line has no children, by definition, so:
print "&#8226; " . $prev_line;

// close out any indents
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]&#8711; [ ] Intro[/b]
[list][b]&#8711; [ ] Who are we[/b]
[list][b]&#8226; [ ] and what are our goals while we're here?[/b]
[/list]&#8711; [ ] Thom
[list]&#8226; [ ] Tech Team Director
&#8226; [ ] How can tech team help?
[/list]
[/list]
etc.

* * *

Some notes about the code and formatting -

I chose to use the &bull; entity, whose code is &#8226; for all of the 'leaf' 
items, and I decided to use the &nabla; (&#8711;) 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 (&#8722;) or a "&radic;" (which 
is &#8730;), 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.


Thom Brooks
Chicago, IL


More information about the OmniOutliner-Users mailing list