Script to replace @tomorrow with @today


#1

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!


Scripting question: changing @due to @today if the date is today
#2

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

Perfect, thank you so much! :smile:


#4

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
)

#5

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?)


#6

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.

#7

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.


#8

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.


#9

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()
})

#10

Brilliant, thank you! :smile:


#11

complex point and Jesse,

Thank you for the explanations.