[Solved] Conditional change or delete line

After listening to an episode of MacSpary on Drafts I decided I would like to start using the tool again. I’m trying for a few days to achieve something that is probably very easy to automate.

I have a Drafts note with 2 types of lines:

[ ] This means the line needs to be removed
[x] This means the ‘[x]’ needs to be removed from the beginning of the line.
[ ] This means the line needs to be removed
[ ] This means the line needs to be removed
[x] This means the ‘[x]’ needs to be removed from the beginning of the line.

I did search on text handling examples in the forum, but I can’t get it working. Based on my search here I came up with:

// Remove all non selected lines starting with '[ ]'

const delPrefix = “[ ]”;

// Scan for the document prefix in the draft
var lines = draft.content.split("\n");

for (var line of lines) {
// Remove non selected lines from the final note
if (line.startsWith(delPrefix)) {

// Get the selection information
let [st, len] = editor.getSelectedLineRange();
// Add 1 to the length to remove any trailing new line
editor.setTextInRange(st, len, “”);
// Ensure we have the cursor at the start of the original line
editor.setSelectedRange(st, 0);
// Ensure we reactivate the editor
editor.activate();

}
}

Sorry, being new to javascript, but eager to learn. This script does remove the line at the cursor, but not the lines starting with ‘[ ]’. Any help or guidance in the right direction would be appreciated.

I think that the following will do what you want. It uses some regular expressions to do the removals by replacing the required matches with either nothing (for line removal), or the rest of the line (other option).

//Remove lines with "[ ] " at the start, including the neline character at the end if any
draft.content = draft.content.replace(/^\[ \] (.*)(\n)+/gm, "");
//Remove the matching text at the start of lines where they begin with "[x] " or "[X] "
draft.content = draft.content.replace(/^\[x\] (.*)/gmi, "$1");
//Update the draft content
draft.update();

Hope that helps.

Generally it’s best not to mix and match scripting with the editor and draft object, as they are conceptually a little different (discussed in Editor object docs.

If you are wanting to make edits across the whole text, it’s best to not manipulate the selection in the editor, but to make all your changes to the text, then update the selection to a new location when you are done.

I would recommend something like the following:

const delPrefix = "[ ]";
const stripPrefix = "[x]";

// get full text of editor and split into lines
let lines = editor.getText().split("\n");

// create a variable to hold the lines you want to keep
let newLines = [];

// loop over the lines
for(let line of lines) {
    // skip lines to be deleted
    if (line.startsWith(delPrefix)) { continue; }
    if (line.startsWith(stripPrefix)) {
        // strip out "[x]"
        newLines.append(line.replace(stripPrefix, ""));
    }
    else {
        // keep unaltered other lines
        newLines.append(line);
    }
}

// update the draft with the new lines
draft.content = newLines.join("\n");
draft.update();

The solution from sylumer does worrk in my workflow. The reposnse from agiletortoise does result in a script error: ‘NewLines.append is not a function. NewLines.append is undefined.
I will look into that. Thanks!

@sylumer @agiletortoise I tried a little more. It seems that if I type the text in the drafts editor with the prefix ‘[ ]’ or ‘[ ]’, the script works fine. If I copy text from a template text draft into a new draft, and run the action, only the ‘[x]’ are removed, but the lines with ‘[ ]’ are unchanged.

The action is as follows:

// Scan for the document prefix in the draft
var lines = draft.content.split("\n");

for (var line of lines) {
//Remove lines with "[ ] " at the start, including the neline character at the end if any
draft.content = draft.content.replace(/^[ ] (.)(\n)+/gm, “”);
//Remove the matching text at the start of lines where they begin with "[x] " or "[X] "
draft.content = draft.content.replace(/^[x] (.
)/gmi, “$1”);
//Update the draft content
draft.update();
}

Any clue why it does not work on copied text in a drafts note?

Let me make some suggestions on things to do and things to check.

1. Remove the Split and Loop

When I posted the code above, it is the entire code. If you use just this code, it should process everything.

draft.content = draft.content.replace(/^\[ \] (.*)(\n)+/gm, "");
draft.content = draft.content.replace(/^\[x\] (.*)/gmi, "$1");
draft.update();

If you look at your code, you first of all split the current draft content by new line into a variable lines, an array containing each line of the draft.

The for loop then loops over each of the lines held in the lines array with each line being held in a variable line, but that variable is never used.

The loop processes the entire draft content once for each line in the draft, when it only needs to process it once.

2. Check the Text

Since you are just repeating the logic with the above rather than changing it, I think the most likely reason for the failure to match one of the types of line is that they don’t match.

The regular expression on that first line is /^[ ] (.*)(\n)+/gm, so let’s break it down a bit.

The forward slashes are delimiters for the expression. The gm makes the regular expression global and multiline. The ^ indicates that the match should start at the beginning of a line.

That leaves \[ \] (.*)(\n)+, which is at the heart of what we need to make sure matches. So let’s spell out what it is doing. The match is looking for:

  1. An open square bracket.
  2. Followed immediately by a space.
  3. Followed immediately by a close square bracket.
  4. Followed immediately by another space.
  5. Followed immediately by some ‘other’ content (other than a line break).
  6. That might be followed by one or more newlines.

Now looking at this with fresh eyes, that last one I think should be different. Rather than a plus (+) I meant to use a question mark (?) as that then says zero or one new line, and accounts for the last line which has no newline character at the end as well as not overstepping into blank lines. That would then make the following code like this, but for the purposes of explanation, since this could be a contributing factor in one case, I’ll discuss below as per using the one or more newlines.

draft.content = draft.content.replace(/^\[ \] (.*)(\n)?/gm, "");
draft.content = draft.content.replace(/^\[x\] (.*)/gmi, "$1");
draft.update();

To my mind, I think your template, whatever it looks like` is likely to have the square brackets correct. It would be immediately obvious if they were not. So that leaves spaces, other content and newlines to consider.

Case 1
If you have inadvertently used a non-space at either of the two key positions. For example perhaps a non-breaking space or a tab character, that would not be matched by the above.

Case 2
You have missed out a space entirely between or after the square brackets.

Case 3
You have no content after the second space. The regular expression is expecting more on the line, and if it doesn’t find it, would fail to match.

Case 4
Because of my earlier mistake, if one of the matches is the last line of the draft, having no newline character at the end, it would not match.

3. Forum Formatting

When posting content on the forum that is code, it helps to wrap it in triple backpacks and optionally specify the language type for highlighting.

For example if I type this:

```javascript
//This is an example
let foo = "lorem ipsum";
```

It produces this:

//This is an example
let foo = "lorem ipsum";

This avoids lots of issues around the changes to the code the forum otherwise makes in terms of interpreting slashes as Markdown codes, changing quotes to smart quotes which don’t work in JavaScript, etc.

4. Example Data

Like you did on the initial post, it can be very useful to actually debug with an example that you can show is going wrong. Again, posting the content within triple backticks is advisable. But then any changes someone might suggest, they can try in advance, and it makes the whole process much quicker.

At the moment I’m guessing as to what is going on because I have no data to go on.

5. Example Action

Like the data, you can share your actual action (perhaps incorporating the template) so that can be looked at too. You’ll find when you share an action to the directory, there’s an option to leave it unlisted (default). If you share it, and copy the URL, you can paste it into the forum, so others can download and debug what’s going on with an exact copy of your entire action.

Do ensure that before doing either of the example steps that you sanitise whatever you are sharing, and if you can simplify things as much as possible in terms of, for example, rather than a novel’s worth of data, just a paragraph that works and a paragraph that doesn’t, that can really help speed things up.

Let us know if that shines a light on your issue.

@sylumer Thanks for the (basic) lesson in javascript and the guidance on how to format a post on this blog. Highly appreciated. Your code did the trick!

draft.content = draft.content.replace(/^\[ \] (.*)(\n)?/gm, "");
draft.content = draft.content.replace(/^\[x\] (.*)/gmi, "$1");
draft.update();

Thanks again.

2 Likes