URL Scheme?

I recently noticed that some of my favorite apps are starting to use URL schemes again. I remember back in the day when Apple was trying to push those “schemes”, and also when Apple kind of just pulled out of doing things by URL schemes.(Devonthink is one of the few applications I know that kept using URL schemes).

I really thought that it was going to be the death of that form of automation; but after laying dormant for a while, it seems as if the URL scheme is coming back with a vengeance. It seems as if the developers have thought about what the schemes can and should do a little bit better, and it is showing in the implementation.

Honestly, I think that this could be a very powerful addition to TaskPaper/WriteRoom since the new schemes tend to forgo the complicated and what seemed as randomly created UID for a clearer and simplified text link that could well be used in Markup due to how understandable it is.

Have you @jessegrosjean given this some thought? What do other people think?

I never got around to adding a URL scheme to WriteRoom and TaskPaper 3. Though FoldingText supports one:

http://support.hogbaysoftware.com/t/details-of-x-foldingtext-and-x-taskpaper-url-schemes/277

Generally I like the idea, but don’t use them much myself, so don’t think about it too often. I could add to WriteRoom 4, though if that happens it won’t be until later in the beta process. Trying not to distract myself with extra todo’s at the moment.

I guess what would help me most if you want them is:

  1. How exactly you’d like to use them.
  2. List of other apps that you think work well with url schemes and what you like about the implementation.
  3. A link back to this post once the first beta of WriteRoom 4 arrives :slight_smile:
1 Like

Let me think about it.

Okay, coming up with something for TaskPaper is different for a big reason.

Most of the apps that make use of URL’s the best are are based on a database. Although the files used in the app itself maybe something that other’s can use, the apps themselves have a database. Before anyone gets defensive about the reasons TaskPaper does one thing or another, let me simply say that this is not a complain, just an observation.

I do think that the future is going towards two different ways of doing things in apps. Some apps have started to have a mix of open/close files that I think Devonthink pioneered back in the day where that seemed to be the direction Apple was taking (Contacts using CardDav, Calendar using CalDav, etc) where the apps themselves provide additional functionality and power to the open standard source files that are used by these databases.
Examples of those today are apps like NotePlan, Nvalt, and Typora.

The other is a more recent movement towards a close database based programs that use open standards to edit and maintain the information within the databases closed such as Bear, Ulysses (this app can do both, but the push has been towards their own model now), Agenda, etc. that has shown incredible potential and is able to do things that are simply not possible under any other model.

Whether TaskPaper chooses one or the other one, that of course, would change what can be accomplished with URL Schemes. What is clear is that one of these paths has to take place for TaskPaper to gain such features as;

  1. Global searches.
  2. To be able to sync preferences and certain searches across devices independently from the source files.

This would open up the ability to use Schemas to simply locate certain “files” within an app and reference them easily. For example, one could have an URL Schema that opens up my “Home” file. Or if I have a “general” todo list within a file, I could link have an URL to point me to a particular project within another file. So, one of the things URL’s could do is,

  1. Link/open TaskPaper Files

Now, one could also use an URL to create searches. I know that something like that is kind of possible using tags within TaskPaper, but it would be awesome if this could be accomplished from other Applications.

  1. Search.

The other thing that could be done would be adding a task. This wouldn’t be as useful right now because we cannot specify where this task ought to go; but it would still be useful since one can simply copy the task into the particular file/place the task needs to go. Specially since many of those actions can be automatically created by other apps, this would be a great gain regardless or the ability of where the task is created. An example of this would be to create templates for repetitive tasks.

  1. Create Tasks

Now, to answer your second question. The apps that come to my mind right now in the Mac are, Mindnote, Ulysses, Things, and Devonthink.

I think that Devonthink is probably the worse of the lot, but since there is so much already out there for Devonthink, it needed to be included. The best of them is Things. The reasons are many, but their documentation is excellent in explaining the possibilities, examples; and they even created a “URL creator” that I think is the cherry on top of the whole thing. Here is a link to it.

Things URL Scheme

But I think that the best examples and the reason of the resurgence of URL schemes is found within iOS. Many of those apps have a Mac counterpart that I mentioned above, but the iOS only apps that I think restarted the whole thing are Draft and Workflow. You should check some of the articles that MacStories and the Sweet Setup have created that explain and show the possibilities and power behind this.

Again, thank you for being open to suggestions and taking the time to read this (If you do :wink: )

Sorry to be so dense but, I don’t completely grasp what you mean when you mention a URL theme? I am guessing it might be something I am familiar with - if you could give an example?

If you mean embedding a link or using characters as this very post can do, when you bold or italicize them, Then heck yes. Otherwise, I am not catching your drift?

Curio is a truly unique app that can do so many things. One thing it can do is create a hyperlink to any text or object and you can past that hyperlink as a URL like text string that the finder will launch and open to that element in a Curio document from anywhere you click on it. I have many of these hyperlinks in TaskPaper and then I do the heavy lifting in the project through Curio.

But, maybe you are referring to something else here?

I just downloaded Folding Text. I still cannot grasp the intended differences. I tried pasting in some of the book I am working on outlining using TaskPaper. I am getting a clearer idea. FT seems to not fold unless you put in some hash tag or symbol for the markdown/markup set. I am sure it has it’s uses and I am sure that WriteRoom also has its uses. I think I will be staying with TaskPaper.

From where I am sitting I still can’t see anything better than TaskPaper for my needs. The tags, searches, and quick folding (expanding), etc. not to mention having fun with formatting using the less file and TaskPaper - just works.

I am going to dumb things now, so if someone has an issue with my explanation, just be aware that I am trying to simplify some of the concepts; and that I am not that knowledgeable in the history of the whole URL, but I am speaking from what I know.

In a few words URL Schemes are based on the idea of using text based links to open an application or applications and execute a set of instructions.

For example, there is the web URL Scheme that starts with “http://” and then it gives you an address. When you click on that address, the program in your system registered to handle that scheme (Safari, Firefox, Chrome, etc.) opens and takes you to where you want to go. This was popularized with the early advent of the internet and some of the services that made use of schemes like,

“ftp://”
“mailto:”
“smb://”

Later on, Apple implemented a way for developers to create their own scheme so that other applications could interact with others without creating complex bridge code or opening themselves to certain attacks. Imagine Object Oriented programing with the passing of instructions being done by the operating system itself.

For the examples, well…

Imagine opening a text file and including an URL like “http://taskpaper.com”. Now, when you click on that link, your computer opens a browser and takes you to that place. Or writing something like “mailto:billgates@microsoft.com” and when you click on it, your computer opens up your default email app and starts a new email to…

Apple makes use of these Schemes on their apps, to open preference panels. Go to a certain place in the iOS settings, etc.

Hopefully this helps you understand my previous post and the ideas I had. Also, read the implementation that Things had.

By the way… Have you tried OmniOutliner? It has all of the formatting that you want done in your lists. Hope that this helps. Have a good one!

OK, thanks. I understand the concept of a system link (what I was calling this). When I drag a file onto a TaskPaper document, I get a link that I can click on to launch that file (if it is a file on my Mac) or, if it is a web browser I can launch that URL address.

I was not following you as you were discussing this as some kind of a code that app developers could use or not use. I thought this was just a part of Apples OS, already built in as it were.

Curio was the example I gave where I can copy what it refers to as a hyperlink. Past that text URL - like command in any text app (like TaskPaper) and clicking on it opens Curio to that file and that location. I assume this was what you were wanting to see in TaskPaper? Other than the dragged in file leaving a clickable file path, I am still not clear on what you are wanting in TaskPaper?

Well, yes it is the simple, and the complex. Like I mentioned before, developers can come up with their own Scheme to add features so that when someone opens a link, a series of functions can be done in the app. I am going to link to a couple of articles that explain this in more detail and with better examples.

URL Scheme tutorial

A tutorial of the URL Scheme for Things

OK, now that i have had a little time to digest this and look at those linked pages, I think I see the disconnect. This appears to be an argument for taking the MacOS goodness and making it more accessible to the iOS platform. Those articles are both about iOS and working with a “URL code” in iOS.

Now I see why I was not tracking your terms as I am not really into iOS development. I enjoy my iPhone, From time to time I have wished for an iPad (mini). It would be great if Jessie developed a TaskPaper version for iOS that could keep my notes in sync with a TaskPaper file.

But, that is not such a big deal, in my case. I use my iOS device to review what I have written when I have it read back to me with headphones on while I edit some print (when I want to go outside and have a cigar). I mostly use Notes for this. I also keep a shopping list or places to go for tasks in my Notes app and Notes on my iOS updates. It’s also great for texting, checking for an important email, getting directions, checking weather, checking the bus to see where it is on the route, quick looking up of things, watching YouTube videos, and so much more.

I love how the ios app can do so many things. But for me I doubt that it will replace my desktop Mac anytime soon. It will probably never replace a real sit down mac (desk top) for writing or photo editing. As for music I am not completely ready to say that yet. I wish more apps did a better job of allowing AppleScripting or inter-macOS operability. When I set tags in BusyCal for example they are not seen in the Finder tag searches.

I dabbled in file paths and such when I was using Panorama by Provue and building my own custom solutions. Curios ability to hyperlink any object is brilliant. Imagine you had some important task to review in a TaskPaper document. Highlight that task and right click and select copy as hyperlink. Now go anywhere else on your mac where you can paste text, a notes field in your calendar, a document you are working on, a different TaskPaper document, and paste in the hyperlink you just copied. From now on clicking on the hyperlink will launch TaskPaper if it is not already open and that TaskPaper document with that task and go right to that hyperlinked text. I am wondering why only Curio does this as I find it incredibly useful.

@jessegrosjean, I don’t know if you had a chance to see how Brett use the URL Scheme to implement themes in his last Marked app; but it is just phenomenal. This is the excerpt of the documentation that mentions the implementation.

I’ll need to document this one further, but there’s also a new method in the URL handler that lets you add a new Custom Style to Marked via a link (x-marked://addstyle?name=My+new+style&css=[url encoded CSS]). Just pass a name and the url encoded CSS and a new file is generated and added to the Custom Style menu automatically. This should make sharing styles even easier. I’ll be sharing an updated StyleStealer bookmarklet very soon to allow a one-click way to duplicate styles from your own sites into Marked for previewing.

This would be a great way to add themes into TaskPaper and WriteRoom, and maybe extend the idea into other aspects of the programs. If one could add scripts this way, it would be pretty amazing; but I understand the security problems.

Anyway, just mentioning this while I know you are working in the code for WriteRoom.

1 Like

I’d love to have a URL scheme for triggering searches inside the document.

I agree it would be nice, but I don’t know when I’ll have time to add.

In the meantime I think you can use a third party app to get the behavior. I haven’t tried this out, but I see Keyboard Maestro has a url scheme, which could then be used to script TaskPaper to set a search.

There may be other options as well, if anyone has another suggestion please post here.

1 Like

I use Keyboard Maestro to execute a lot of searches. This one shows me a list of projects, with their next actions (a GTD concept):

Of course, you can customize the code to whatever search you desire.

Here is the JavaScript for Automation code:

function TaskPaperContextScript(editor, itemPathFilter) {
  editor.itemPathFilter = itemPathFilter
}

Application("TaskPaper").documents[0].evaluate({
  script: TaskPaperContextScript.toString(),
  withOptions: "project *//not @done[0]"
})

I hope that helps!

One approach seems to be to use links like the one below, which:

  • opens any file with the path /Users/houthakker/notes2021-02-08.taskpaper
  • and applies the itemPath filter //@done
kmtrigger://macro=openTP3Path&value=%2FUsers%2Fhouthakker%2FNotes%2Fnotes2021-02-08.taskpaper%2F%2F%40done

The value= part is a uri-component encoding of the itemPath appended directly to the end of the filepath:

 /Users/houthakker/Notes/notes2021-02-08.taskpaper//@done

Where TP3Path would be the name of a macro handling the link, perhaps:

  • opening the URI-component-encoded file path,
  • and setting the trailling itemPathFilter

An openTP3Path Keyboard Maestro macro might look something like this:

openTP3path.kmmacros.zip (10.7 KB)

JS Source
(() => {
    'use strict';

    ObjC.import('AppKit');

    // main :: IO ()
    const main = () => {
        const [toFileName, itemPath] = Application(
                'Keyboard Maestro Engine'
            )
            .getvariable('tp3Path')
            .split('.taskpaper'),
            fp = toFileName + '.taskpaper';

        return either(
            msg => alert('TaskPaper itemPath Link')(msg)
        )(
            x => x
        )(
            bindLR(
                doesFileExist(fp) ? (
                    Right(fp)
                ) : Left(`File not found:\n\t${fp}`)
            )(
                fpFound => {
                    const
                        tp3 = Application('TaskPaper'),
                        doc = (
                            tp3.activate(),
                            tp3.open(fpFound)
                        );
                    return (
                        // In TaskPaper,
                        doc.evaluate({
                            script: (
                                `(editor, itemPath) => 
                            editor.itemPathFilter=itemPath`
                            ),
                            withOptions: itemPath
                        }),
                        // and in Keyboard Maestro.
                        Right(`${fpFound}\n${itemPath}`)
                    )
                }
            )
        );
    };

    // ----------------------- JXA -----------------------

    // alert :: String -> String -> IO String
    const alert = title =>
        s => {
            const sa = Object.assign(
                Application('System Events'), {
                    includeStandardAdditions: true
                });
            return (
                sa.activate(),
                sa.displayDialog(s, {
                    withTitle: title,
                    buttons: ['OK'],
                    defaultButton: 'OK',
                    withIcon: sa.pathToResource('TaskPaper.icns', {
                        inBundle: 'Applications/TaskPaper.app'
                    })
                }),
                s
            );
        };

    // doesFileExist :: FilePath -> IO Bool
    const doesFileExist = fp => {
        const ref = Ref();
        return $.NSFileManager.defaultManager
            .fileExistsAtPathIsDirectory(
                $(fp)
                .stringByStandardizingPath, ref
            ) && 1 !== ref[0];
    };

    // --------------------- GENERIC ---------------------

    // Left :: a -> Either a b
    const Left = x => ({
        type: 'Either',
        Left: x
    });

    // Right :: b -> Either a b
    const Right = x => ({
        type: 'Either',
        Right: x
    });

    // bindLR (>>=) :: Either a -> 
    // (a -> Either b) -> Either b
    const bindLR = m =>
        mf => undefined !== m.Left ? (
            m
        ) : mf(m.Right);

    // either :: (a -> c) -> (b -> c) -> Either a b -> c
    const either = fl =>
        // Application of the function fl to the
        // contents of any Left value in e, or
        // the application of fr to its Right value.
        fr => e => 'Either' === e.type ? (
            undefined !== e.Left ? (
                fl(e.Left)
            ) : fr(e.Right)
        ) : undefined;


    return main();
})();

Hey @Jim - where do you set the path for your .taskpaper file with this script?

Hi @taskSloth — I don’t set the path on purpose. The script affects the front document in TaskPaper, which makes it versatile.

ah I see thanks!

You’re welcome!

In case this is useful for anyone else, I created a solution solely using Keyboard Maestro and without any scripting.

  • Trigger the macro via a URL (this I place in Obsidian)
  • Open taskpaper
  • Delay by a fraction of a second (just in case)
  • Press Shift-cmd-F to activate the search in Taskpaper
  • Insert the search query

I found it super useful and very quick to manipulate if needed. I can imagine adding a TriggerValue to the URL for separate searches. The value can then be fed into a switch statement to change the search query. I’ve done something very similar for switching between other apps using URLs from KM.

2 Likes