Script to replace @tomorrow with @today

Does anyone have a script to replace one tag (ex: @tomorrow) with another (ex: @today)? Alternately, is there some stupidly simple way to do this that I’ve missed? I’d like to be able to assign this to a keyboard shortcut.

Thanks!

Here’s one way to do it:

function TaskPaperContextScript(editor, options) {
  var outline = editor.outline;
  outline.groupUndoAndChanges(function() {
    outline.evaluateItemPath('//@tomorrow').forEach(function (each) {
      each.setAttribute('data-today', each.getAttribute('data-tomorrow'));
      each.removeAttribute('data-tomorrow');
    });
  });
}

Application("TaskPaper").documents[0].evaluate({
  script: TaskPaperContextScript.toString()
})
3 Likes

Perfect, thank you so much! :smile:

1 Like

As an example, FWIW, of generalising an existing script, the following might be one way of using withOptions to get a script which translates between any given pair of tags (preserving tag contents, as in Jesse’s original), and notifying the user of how many changes were made.

To use it with a different oldTag -> newTag translation, edit the closing lines at the bottom of the script:

(function (strOldTag, strNewTag) {

    // TASKPAPER 3 CONTEXT
    function updateTags(editor, options) {

        var outline = editor.outline,
            strOldAttrib = 'data-' + options.oldTag,
            strNewAttrib = 'data-' + options.newTag;

        var lstFound = outline.evaluateItemPath(
                '//@' + options.oldTag
            ),
            lngFound = lstFound.length;

        if (lngFound > 0) {
            outline.groupUndoAndChanges(function () {
                lstFound.forEach(
                    function (item) {

                        item.setAttribute(
                            strNewAttrib,
                            item.getAttribute(strOldAttrib)
                        );

                        item.removeAttribute(strOldAttrib);
                    }
                )
            });

            return {
                count: lngFound,
                linesChanged: lstFound.map(function (x) {
                    return x.bodyString;
                })
            }
        } else return undefined;
    }


    // JAVASCIPT FOR AUTOMATION CONTEXT:

    var ds = Application("com.hogbaysoftware.TaskPaper3")
        .documents,
        d = ds.length ? ds[0] : undefined,

        dctResult = d ? d.evaluate({
            script: updateTags.toString(),
            withOptions: {
                oldTag: strOldTag,
                newTag: strNewTag
            }
        }) : 'No document active in TaskPaper';

    if (dctResult) {
        var a = Application.currentApplication();

        (
            a.includeStandardAdditions = true,
            a
        )
        .displayNotification(
            '@' + strOldTag + ' --> @' + strNewTag, {
                withTitle: dctResult.count + " lines updated in TaskPaper3"
            });
    }
})(
    'tomorrow', // old tag
    'today' // new tag
)
1 Like

Apologies for asking what might be a simplistic question, why use a script when Find and Replace is available?

Being a very basic user I do not understand the significance of a script (other than automation perhaps?)

Good question : -)

  • You could do it with Find and Replace, but it would still be easier to launch the stored Find and Replace from a script, which can be attached to a keystroke.
  • The scripting model already knows how to find a class of tags, and replace the tag key without changing tag values like dates etc. You could write a regex for find and replace, but you might have to give some thought to edge cases and false positives, and laziness has its virtues and appeal.

One other issue is that find and replace only works on the visible document. For if you for instance are focused on a project it will only search in that project. But for this type of thing you probably want to always find and replace throughout your entire document.

What would be the script for adding a completely new tag (so that I can tag something with @tomorrow the way I can tag something @today using Command-Y)? I’ve been poking through the various scripts on this board and the scripting API guide, but I haven’t been able to figure it out with my (basically non-existant) knowledge of Javascript.

Here’s one way to do it:

function TaskPaperContextScript(editor, options) {
  editor.outline.groupUndoAndChanges(function() {
    editor.selection.selectedItems.forEach(function (each) {
      each.setAttribute('data-tomorrow', '');
    });
  });
}

Application("TaskPaper").documents[0].evaluate({
  script: TaskPaperContextScript.toString()
})

Brilliant, thank you! :smile:

1 Like

complex point and Jesse,

Thank you for the explanations.

1 Like