outliner:// URL Scheme

The Problem

Over the Thanksgiving break, I was listening to Gabe Weatherhead’s Generational podcast Episode 009 “Research Materials and Tools with Walton Jones”. Walton blogs at Drosophiliac and has some very geeky processes and tools to capture his research data. I was particularly intrigued by his custom skimmer:// URL Scheme. My mind immediately jumped to how I can combine the iOS URL schemes that are available in the apps that I use, and how they can be used on the Mac, allowing me to have a single URL that I can drop into either VoodoPad or Omnifocus.

Thinking about what applications I use on the iPhone / iPad are:

On the desktop I use:

Each of these has a URL Scheme:

  • nebulous://
  • nebulous://
  • nebulous://new
  • nebulous://new?contents=some%20string
  • nebulous://path/to%20file.txt
  • nebulous://path/to%20file.txt?append=some%20string
  • nebulous://path/to%20file.txt?prepend=some%20string
  • outliner://
  • outliner://name/p
  • ithoughts://
  • ithoughts://Maps/

After looking at Walton Jones’ code, it didn’t appear too difficult, so I broke out the AppleScript Editor and got to work.

The Solutions

For each application, I created a “listener” application and a PHP script to generate the URLs.

Following the directions on Mac OS X Automation, each “listener” application needs the info.plist edited to indicate that that the Applescript application can listen for URLs. I am not going to show the info.plist modifications, they are exactly the same as the demo linked.

To get these things working, I had to use RCDefault to check things out and make sure they are pointed to the right place. There was some weirdness with Versions and the applications.

Generator

Outliner
iThoughts
Nebulous
Due
Maps
Quotebook
Day One
if (count($_POST) > 0) {
$fileName = $_POST['fileName'];
$type = $_POST['type'];
$url = "";
$filetype = "";
switch ($type) {
case "Outliner":
$url .= "outliner://name/";
$filetype .= "";
break;
case "iThoughts":
$url .= "ithoughts://Maps/";
$filetype .= "";
break;
case "Nebulous":
$url .= "nebulous://_blog/drafts/";
$filetype .= ".markdown";
break;
case "Due":
$url .= "due:///add?title=";
break;
case "Maps":
$url .= "maps://?q=";
break;
case "DayOne":
$url .= "dayone://add?entry=";
break;
case "Quotebook":
$url .= "quotebook://add?quote=";
break;
}
$fullURL = $url . rawurlencode($fileName) . $filetype;
echo '
' . $fullURL . '
';
}
?>
I can access this from my phone and from my desktop, so it works great.

Nebulous Notes

I like Nebulous Notes on the iPhone and iPad because of the macros keyboard that is offered. Sure, Byword gives me most of that functionality, but Nebulous feels like a tool, Byword feels like silk sheets.

Listener

The listener will open the markdown file in what ever the default markdown editor is.
on open location outlinerURL
set oldDelims to AppleScript's text item delimiters
set newDelims to {"nebulous://_blog/draft/"}
set AppleScript's text item delimiters to newDelims
set outlineName to item 2 of the text items of outlinerURL
set outlineName to outlineName & ".markdown"
set outlineName to urldecode(outlineName)
set OutlineLocation to "/Users/00469508/Dropbox/_blog/draft/"
set theFullPath to OutlineLocation & outlineName
set AppleScript's text item delimiters to oldDelims
-- PROCESS ACTIONS
-- This loop will execute scripts located within the Resources folder
-- of this applet depending on the key and value passed in the URL
do shell script ("open "" & theFullPath & """)
end open location
on run_scriptfile(this_scriptfile)
try
set the script_file to path to resource this_scriptfile
return (run script script_file)
on error
return false
end try
end run_scriptfile
on load_run(this_scriptfile, this_property_value)
try
set the script_file to path to resource this_scriptfile
set this_script to load script script_file
set main_property of this_script to this_property_value
return (run script this_script)
on error
return false
end try
end load_run
-- http://harvey.nu/applescript_url_decode_routine.html
on urldecode(theText)
set sDst to ""
set sHex to "0123456789ABCDEF"
set i to 1
repeat while i ? length of theText
set c to character i of theText
if c = "+" then
set sDst to sDst & " "
else if c = "%" then
if i > ((length of theText) - 2) then
display dialog ("Invalid URL Encoded string - missing hex char") buttons {"Crap..."} with icon stop
return ""
end if
set iCVal1 to (offset of (character (i + 1) of theText) in sHex) - 1
set iCVal2 to (offset of (character (i + 2) of theText) in sHex) - 1
if iCVal1 = -1 or iCVal2 = -1 then
display dialog ("Invalid URL Encoded string - not 2 hex chars after % sign") buttons {"Crap..."} with icon stop
return ""
end if
set sDst to sDst & (ASCII character (iCVal1 * 16 + iCVal2))
set i to i + 2
else
set sDst to sDst & c
end if
set i to i + 1
end repeat
return sDst
end urldecode
CarbonFin Outliner
CarbonFin Outliner is a great outliner and now that it supports Dropbox syncing, I can bring it back into the fold. Welcome back, old friend.

Listener

on open location this_URL
set OutlineLocation to "/Users/00469508/Dropbox/Outliner/"
set URLScheme to "outliner://name/"
set FileExtension to ".opml"
set EditorOfChoice to "OmniOutliner"
set PosixOutlineLocation to POSIX path of OutlineLocation
set PosixOutlineLocation to POSIX file PosixOutlineLocation
set oldDelims to AppleScript's text item delimiters
set newDelims to {URLScheme}
set AppleScript's text item delimiters to newDelims
set outlineName to item 2 of the text items of this_URL
set outlineName to urldecode(outlineName)
set theFullPath to OutlineLocation & outlineName & FileExtension
set AppleScript's text item delimiters to oldDelims
tell application "OmniOutliner"
open theFullPath
end tell
end open location
on run_scriptfile(this_scriptfile)
try
set the script_file to path to resource this_scriptfile
return (run script script_file)
on error
return false
end try
end run_scriptfile
on load_run(this_scriptfile, this_property_value)
try
set the script_file to path to resource this_scriptfile
set this_script to load script script_file
set main_property of this_script to this_property_value
return (run script this_script)
on error            
return false
end try
end load_run
-- http://harvey.nu/applescript_url_decode_routine.html
on urldecode(theText)
set sDst to ""
set sHex to "0123456789ABCDEF"
set i to 1
repeat while i ? length of theText
set c to character i of theText
if c = "+" then
set sDst to sDst & " "
else if c = "%" then
if i > ((length of theText) - 2) then
display dialog ("Invalid URL Encoded string - missing hex char") buttons {"Crap..."} with icon stop
return ""
end if
set iCVal1 to (offset of (character (i + 1) of theText) in sHex) - 1
set iCVal2 to (offset of (character (i + 2) of theText) in sHex) - 1
if iCVal1 = -1 or iCVal2 = -1 then
display dialog ("Invalid URL Encoded string - not 2 hex chars after % sign") buttons {"Crap..."} with icon stop
return ""
end if
set sDst to sDst & (ASCII character (iCVal1 * 16 + iCVal2))
set i to i + 2
else
set sDst to sDst & c
end if
set i to i + 1
end repeat
return sDst
end urldecode
iThoughts
I haven't been a huge user of mind maps, but I am beginning to see their value, so I am working to get the apps on all my devices. I am currently undecided on my desktop app. I have used Mindjet, but I am looking at some of the smaller, simpler (and cheaper) apps, like MindNode.

Listener

Currently, the listener has an issue with the Applescript that tries to open the file, a weird error regarding permission to open the file. I have sent an email to the developer.
The Applescript needed to be modified with the using some code from MindNode support.
on open location outlinerURL
set oldDelims to AppleScript's text item delimiters
set newDelims to {"ithoughts://Maps/"}
set AppleScript's text item delimiters to newDelims
set outlineName to item 2 of the text items of outlinerURL
set outlineName to outlineName & ".opml"
set outlineName to urldecode(outlineName)
set OutlineLocation to "/Users/00469508/Dropbox/Outliner/"
set theFullPath to OutlineLocation & outlineName
set AppleScript's text item delimiters to oldDelims
set PosixOutlineLocation to POSIX path of theFullPath
set PosixOutlineLocation to POSIX file PosixOutlineLocation
tell application "MindNode Pro"
open PosixOutlineLocation
end tell
end open location
on run_scriptfile(this_scriptfile)
try
set the script_file to path to resource this_scriptfile
return (run script script_file)
on error
return false
end try
end run_scriptfile
on load_run(this_scriptfile, this_property_value)
try
set the script_file to path to resource this_scriptfile
set this_script to load script script_file
set main_property of this_script to this_property_value
return (run script this_script)
on error
return false
end try
end load_run
-- http://harvey.nu/applescript_url_decode_routine.html
on urldecode(theText)
set sDst to ""
set sHex to "0123456789ABCDEF"
set i to 1
repeat while i ? length of theText
set c to character i of theText
if c = "+" then
set sDst to sDst & " "
else if c = "%" then
if i > ((length of theText) - 2) then
display dialog ("Invalid URL Encoded string - missing hex char") buttons {"Crap..."} with icon stop
return ""
end if
set iCVal1 to (offset of (character (i + 1) of theText) in sHex) - 1
set iCVal2 to (offset of (character (i + 2) of theText) in sHex) - 1
if iCVal1 = -1 or iCVal2 = -1 then
display dialog ("Invalid URL Encoded string - not 2 hex chars after % sign") buttons {"Crap..."} with icon stop
return ""
end if
set sDst to sDst & (ASCII character (iCVal1 * 16 + iCVal2))
set i to i + 2
else
set sDst to sDst & c
end if
set i to i + 1
end repeat
return sDst
end urldecode
Conclusion
This works for me, your mileage might vary. The code will definitely have to be modified to work on your system.