List manipulation idea


#1

I’m wondering if anyone has attempted the following: Let’s say you have a draft that is a list (using the handy-dandy [x] boxes) and some of the items on the list have been checked off. Is there a method using scripting to reorder the lines in the draft so that all the checked lines move to the bottom and the unchecked lines move to the top of the list?
I have only rudimentary scripting skill and don’t even know where to begin, but it might be worth the time for someone who knows what they’re doing.

Thoughts?


#2

That’s definitely do-able via scripts. In fact, I’d suggest it’s a great first project if you’re looking to learn.

I’d start with the pseudo code. Something like:

// break draft into lines
// sort lines based on their leading characters
// recompile draft

#3

That look like a logical breakdown. I’d also like to make sure that the first line stays the same (as a title) and the moved lines retain their original order relative to each other.

Looks like I’ve got some learnin’ to do! Hopefully I’ll have it done before Drafts 6 :wink:

thx


#4

Would you want the order of items maintained, or does it not matter? I may have some ideas :slight_smile:


#5

Ideally, I would like to keep the lines in the same relative order. But I’m definitely open to all input. Thx.


#6

I have this completed already. If you can wait a week, it will be in an action group that is in the review I’m writing. :grin:


#7

A simple alphabetical sort would actually put the completed at the bottom whilst keeping unchecked at the top - and it would alphabetise all of the tasks between. As @nahumck has a solution already that likely preserves order I’ll leave that to him!


#8

Wow! You are a shining example of the true spirit of the Drafts community!

And no, I can’t wait :wink:


#9

It keeps the same order in which you check them off. I’m sure it can be modified as needed once it’s out there.


#10

Hi Tim I would be grateful if you can slot your script which orders ticked list items to the end of the list. I tried but could not get rid of the syntax error.Thanks a million.

/*
Ask for a category, and append to a tagged list for that category
*/

// setup categories
const categories = [“Shopping”, “Trip Packing List”, “May-2018 Develer”];
// tag to assign to list drafts
const listTag = “lists”;
const currentContent = draft.content.trim();

// prompt to select a category
var p = Prompt.create();
p.title = “Select list”;
for (var cat of categories) {
p.addButton(cat);
}

if (p.show()) { // user made a selection
const
category = p.buttonPressed,

// query for list drafts...
drafts = Draft.query(category, 'inbox', [listTag]),

// index of first draft that matches a condition
iDraft = drafts.findIndex(
    draft => draft.content.startsWith('## ' + category)
),

d = iDraft !== -1 ? (
    drafts[iDraft]
) : Object.assign(
    Draft.create(), {
        content: '## ' + category + '\n\n'
    });
// tag and update content
d.addTag(listTag);
d.content = d.content + "- [ ] " + currentContent + "\n"
d.update();

}
else { // user cancelled prompt
context.cancel();
}


#11

Here’s the action to move completed items down to the bottom. Uses the Markdown-formatted task indicator ("- [x]"). Can be modified to include others if needed.


#12

To make sure that peoples drafts are actually updated, I think you may need to make a small edit to that:

d.update becomes d.update()

( without the trailing (), d.update just evaluates to a reference to the function, and has no effect )


#13

Small oversight. Updated and fixed!


#14

Think there is a problem


#15

I put it back to what I had. Uploaded it. Seems to work. Maybe someone smarter than me can fix this all up :wink:


#16

I think a slight confusion about what d refers to has crept into your script.

In the first line, you are binding the name d to a string value (d.content), but the name you have chosen suggests that you may have thought it was a reference to the draft object.

by the time you get down to

d.update;
editor.focus(d);

You are trying to call a draft object method on a String.

d.update() fails because Strings don’t have an update method.

The impression that it ‘works’ when you remove the trailing parentheses is just created by the fact that nothing is happening at all, not even an error message.

The draft is not being updated.

editor.focus(d) also looks a bit unlikely to have much effect.

Javascript types are quite slippery – the automatic coercions, and silent failures with undefined can easily leave one with a slightly vague sense of what is happening.

Time wasted tracking down bugs can be reduced (both for you and for those you share code with) by depending less on automatic type conversion, and by using a slightly more defensive approach to staying clear about the type of values that names are bound to.

// UNFIXED SOURCE CODE OF https://actions.getdrafts.com/a/1Ec
// BEST NOT TO RUN THIS CODE – BUGS AHEAD

// Move lines containing a completed markdown task (“- [x]”) to the bottom of the current draft.

var d = draft.content;
var lines = d.split("\n");
var begin = '';
var end = '';
var c ="- [x]";

for (var line of lines) {
  var check = line.includes(c);
  //if line contains "- [x]"… 
  if (check) {
  //add it to var end
    end += line + "\n";
  }
  else {
    begin += line + "\n";
  }
}
begin = begin.slice(0,-1);
end = end.slice(0,-1);
editor.setText(begin + "\n" + end);
d.update;
editor.focus(d);

#17

Now that I’ve had some time to stop and think about what I was initially trying to do with it all, I cleaned it up. It should work now. Fixed the code:

// FIXED SOURCE CODE OF https://actions.getdrafts.com/a/1Ec
// FEEL FREE TO RUN THIS CODE – BUT ONLY IF YOU WANT TO

// Move lines containing a completed markdown task (“- [x]”) to the bottom of the current draft.

var lines = draft.content.split("\n");
var begin = '';
var end = '';
var c ="- [x]";

for (var line of lines) {
  var check = line.includes(c);
  //if line contains "- [x]"… 
  if (check) {
  //add it to var end
    end += line + "\n";
  }
  else {
    begin += line + "\n";
  }
}
begin = begin.slice(0,-1);
end = end.slice(0,-1);
editor.setText(begin + "\n" + end);
draft.update;
editor.focus(draft);