Question about loops or repeating


#1

This is an example of something that I’m sure is trivially easy, but I’m still claiming my “I don’t know how to code” card :joy:.

What I would like to do is take a draft and split it by lines, then run a script on each individual line. The splitting part I have this for which I use in a different action.

const lines = draft.content.split("\n");

but I can’t figure out how to then format it so I can write my script to run over each line’s content. This is the kind of thing that I could do in Workflow incredibly simply.

Long term I plan on a menu of three options, one of which will fire off a url scheme on the draft the other two would lead to this line splitting. but I’m trying to get one part at a time working… and just trying to learn in general.

Sorry for the (I assume trivial) question.


#2

I’m sure there are multiple examples for you to choose from in the directory, but you can take the split lines that you have and write the for loop:

for (var line of lines) {
  // do stuff with each line
}

Just put the Scripting you want in that middle section. That’s the basic gist of it.


#3

looks like that’s working for me. thanks!


#4

Seems as though I’m a bit slow in getting this repsonse together and Tim’s beaten me to it :sunglasses:. But just in case it is of use to anyone I’ll go ahead with what I planned to write.

I wasn’t quite clear on the long term goal, but suffice to say you probably want to think about the splitting within each separate action rather than splitting an then the selected action working on split text. But it is possible to put something together that’s pretty generic so you can get away with writing it once.

Here’s an example script that passes the name of a line processing function to a looping function and the looping function then runs that line processing against each line of the current draft.

//*** WHAT CAN BE DONE STARTS HERE ***
//Create a function to do something with each line
//This one displays a message containing the text of the line
let myFunction1 = strMsg => 
{
	alert(strMsg);
}

//Create another function to do something with each line
//This one displays a message containing the character count of the line
let myFunction2 = strInput => 
{
	alert(strInput.length);
}

//This next function defines a function called "perLine" which when passed the name of another function (e.g. myFunction1 or myFunction2 above), it will run that function with the line as input.
let perLine = (whichFunction) =>
{
	//Split the draft into lines and operate on each line
	let doSomething = draft.content.split("\n").map(strLine => {
		//This is where what we want to happen gets called
    	eval(whichFunction + "(\"" + strLine + "\")");
	})
}
//*** WHAT CAN BE DONE ENDS HERE ***

//*** FROM HERE ON WE'LL SAY WHAT WE WANT TO DO ***
//Let's say hello, then run a function on every line, then say we're going again, run another
//function on every line and then finally say we're done.

alert("Hello. Let's run the first function on every line..");

perLine("myFunction1");

alert("I think that should have worked. Let's try something else on every line...");

perLine("myFunction2");

alert("That's all I'm planning to do. Goodbye!");
//*** THE END ***

You can download this example as an action here.

The principle @nahumck outlined is all you really need to know, but hopefully the above will be of help to someone too.


#5

map is great for processing each line of a draft.

As an alternative to the above solution, rather than passing the name of the function, you could instead pass the function itself. You could then pass that input function directly to map, rather than constructing a string to run through eval.

Here’s a new version of perLine:

//This next function defines a function called "perLine" which when passed another function (e.g. myFunction1 or myFunction2 above), it will run that function with each line of the draft as input.
let perLine = whichFunction => 
{
	//Split the draft into lines and operate on each line
	draft.content.split("\n").map(whichFunction);
}

Now pass in the function itself (rather than the name of the function):

alert("Hello. Let's run the first function on every line..");

perLine(myFunction1);

alert("I think that should have worked. Let's try something else on every line...");

perLine(myFunction2);

alert("That's all I'm planning to do. Goodbye!");

#6

So ultimately I’m trying to fiddle down my total actions and learn at the same time.

I currently have an action that prompts me to know if I’m adding a Reminder (which then goes into the fantastical url scheme), or adding to a shopping list at two different stores (each of which does a List in Reminders action.) All three are just pointers using Include Action to the actual one.

I have written this in JavaScript which does the same thing and from my testing works. The lists go to their respective reminders list or the fantastical action runs as expected. My question is, if I do the fantastical one it always tells me the action failed (when it clearly didn’t). What am I missing? (and feel free to tell me anywhere of improvement)

var p = Prompt.create();

p.addButton("Fantastical");
p.addButton("Target");
p.addButton("Costco");

var didSelect = p.show();
var Choice = p.buttonPressed

if (Choice == "Fantastical") {
const baseURL = "fantastical2://x-callback-url/parse/";

	var cb = CallbackURL.create();
	cb.baseURL = baseURL;
	cb.addParameter("sentence", draft.content);
	cb.addParameter("reminder", 1);
	cb.addParameter("add", 1);
	var success = cb.open();
app.openURL(url);
} else { 
    
const lines = draft.content.split("\n");
for (var line of lines){
var list = ReminderList.findOrCreate(Choice);
var reminder = list.createReminder();
reminder.title = line;
reminder.update();
};
};

#7

:sunglasses: obvious if you stop to think about it and a beautiful refinement. Thanks @edgauthier.


#8

What does the log say exactly for this?

Available under the “i” in a circle in your draft.


#9

It’s likely the app.openUrl(url) statement. It doesn’t look like you defined url anywhere (I’m guessing leftover code before you switched to using a CallbackURL).


#10

Thank you to @sylumer and @edgauthier … that helped get me there. It was indeed the app.openURL(url) spot… and I didn’t even consider using the log to find it. the log itself said it couldn’t do that line.

and it works. thanks.


#11

I’ve updated this action to include the “Fantastically Good Reminder Parser” from @pdavisonreiber.

If you prefer Fantastical I’ve left that in, but disabled. Simply enable that block and disable the one with the Reminder Parser.

The updated action is here https://actions.getdrafts.com/a/1MB