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.


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

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'));

  script: TaskPaperContextScript.toString()


Perfect, thank you so much! :smile:


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

    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 () {
                    function (item) {



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


    var ds = Application("com.hogbaysoftware.TaskPaper3")
        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,
            '@' + strOldTag + ' --> @' + strNewTag, {
                withTitle: dctResult.count + " lines updated in TaskPaper3"
    'tomorrow', // old tag
    'today' // new tag


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', '');

  script: TaskPaperContextScript.toString()


Brilliant, thank you! :smile:


complex point and Jesse,

Thank you for the explanations.