foreach output separator

Confirmed bugs should get a single post here. Check the READ ME FIRST sticky thread for the format.

Moderators: dorpond, trevor, Azhrei, giliath, jay, Mr.Ice, MapTool BugReport Manager

Forum rules
Posts that do not conform to the READ ME FIRST sticky thread are subject to deletion.
Post Reply
bobifle
Giant
Posts: 219
Joined: Thu Oct 19, 2017 12:36 pm

foreach output separator

Post by bobifle »

http://www.lmwcs.com/rptools/wiki/forea ... ay_Example
output_separator default value is null
list_separator default value is ",". Some examples of other useful separators: nothing "", space " " and break "<br>".
The following code

Code: Select all

[h:  data = json.append("","one", "two", "three")]<br>
<table border=1>
<tr>
[r,foreach(elem, data), code: {
  <td>[r: elem]</td>
}]
</tr>
</table>
generates extra spurious "," in the output despite a null default value.

Edit: the issue is reproducible when data = "one,two,three"
Edit2 : I guess "list_separator" is ignored in case of a json array ?

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: foreach output separator

Post by aliasmask »

The wiki is incorrect. My guess is when the code base was updated to remove NULL values this was updated with "," as the output separator, but never noted. It's an easy fix though:

Code: Select all

[h:  data = json.append("","one", "two", "three")]<br>
<table border=1>
<tr>
[r,foreach(elem, data, ""), code: {
  <td>[r: elem]</td>
}]
</tr>
</table>

bobifle
Giant
Posts: 219
Joined: Thu Oct 19, 2017 12:36 pm

Re: foreach output separator

Post by bobifle »

If I may, "" should be the default value.

Arbitrary deciding to insert ',' makes little sense and will probably puzzle a lot of MT macro new comers, as it puzzled to me.
Currently iterating over a json array of 3 elements actually produces 5 iterations, oh boy ... :mrgreen:

I can however see how problematic it would be to change a default value of a such common control. If the wiki is to be updated I suggest to add a big warning and advise people to always specify the output_separator (and set it to "" to get the classic iteration as most languages understand it) and then proceed with the more advanced usages...

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: foreach output separator

Post by aliasmask »

I recommend building output to a string and then outputting the string. To build an html table, one MT method is Wiki: listFormat() and may be worth looking in to. It requires a comma separated list, but converting a json array to a list is pretty easy.

Code: Select all

[h: data = json.append("","one", "two", "three")]
[H: list = json.toList(data)]
[H: table = listFormat(list,"<table border=1><tr>%list</tr></table>","<td>%item</td>","")]
[R: table] 
Here's a snippet of a more complicated use using listFormat. I'm building an input() string.

Code: Select all

...

<!-- define variables locally -->
[H: skillData = json.toStrProp(am.skills)]
[H: skillDataProps = json.fields(am.skills)]
[H: varsFromStrProp(skillData)]

<!-- eval roll mods -->
[H: rolls = listFormat(skillPropNames,"%list","[H: %item.rollMod = %item.rank + 3 * %item.class + eval(%item.ability+'B') + %item.acp * armorCheckPenalty + %item.mod + allSkillsMod]","")]
[H: evalMacro(rolls)]

<!-- get user input -->
[H: abilityNames = "Str,Dex,Con,Int,Wis,Cha"]
[H: colorList = json.set("{}","Str","Red","Dex","Blue","Con","Orange","Int","Purple","Wis","Green","Cha","Black")]
[H: skillInputs = listFormat(skillPropNames,"%list",
   '%item.tab|<html><b color=[r: json.get(colorList,"%{%item.ability}")]>%{%item.name}</b> (%{%item.rollMod})</html>|%{%item.name}|TAB ##'+
   "header|<html><b>%{%item.name}</b> ( %{%item.rollMod} )</html>|Skill Name|LABEL|span=true ##"+
   "%item.rank|%{%item.rank}|Rank|TEXT ##"+
   "%item.mod|%{%item.mod}|Modifier|TEXT ##"+
   "tip|<html><div width=300><HR>* In most cases, these values remain unchanged<HR></div></html>|Tip|LABEL|span=true ##"+
   "%item.ability|%{abilityNames}|Ability|LIST|SELECT=[r: listFind(abilityNames,%item.ability)] VALUE=STRING ##"+
   "%item.class|%{%item.class}|Class|CHECK ##"+
   "%item.acp|%{%item.acp}|Armor Check|CHECK ##"+
   "%item.untrained|%{%item.untrained}|Untrained|CHECK ","##"
)]

<!-- convert strprop to be used in input -->
[H: skillInputs = evalMacro(strformat(skillInputs))]

<!-- ##### INPUT ##### -->
[H: abort(input(skillInputs))]
 ...
Attachments
skill input example.jpg
skill input example.jpg (82.22 KiB) Viewed 5320 times

bobifle
Giant
Posts: 219
Joined: Thu Oct 19, 2017 12:36 pm

Re: foreach output separator

Post by bobifle »

Thanks, I'll chew on that.

User avatar
Full Bleed
Demigod
Posts: 4736
Joined: Sun Feb 25, 2007 11:53 am
Location: FL

Re: foreach output separator

Post by Full Bleed »

bobifle wrote:
Mon Jul 02, 2018 8:58 am
If I may, "" should be the default value.

Arbitrary deciding to insert ',' makes little sense and will probably puzzle a lot of MT macro new comers, as it puzzled to me.
Currently iterating over a json array of 3 elements actually produces 5 iterations, oh boy ... :mrgreen:

I can however see how problematic it would be to change a default value of a such common control. If the wiki is to be updated I suggest to add a big warning and advise people to always specify the output_separator (and set it to "" to get the classic iteration as most languages understand it) and then proceed with the more advanced usages...
I agree with all of this. This has been a bugaboo for awhile... I'm still finding instances of some of my old code where I didn't use the output separator field (usually unearthed when I find a mysterious comma somewhere.) I don't think it's intuitive to have to define "" each time and it's what I want about 95% of the time.
Maptool is the Millennium Falcon of VTT's -- "She may not look like much, but she's got it where it counts."

bobifle
Giant
Posts: 219
Joined: Thu Oct 19, 2017 12:36 pm

Re: foreach output separator

Post by bobifle »

Thanks again aliasmask for your code, I will have to implement some kind of token editor, this will be useful.

However I'm worried about the actual usage of json.toList. It seems to work properly only on json array not containing json objects.

I tried to use it on something like

Code: Select all

[{"type": "char", "name": "john"}, {"type": "char", "name": "bob"}]
It didn't go very well, I could not access inner json object fields easily. I still came up with a solution, fixing the foreach glitch (it's a big word for just adding "", I know...).

I'm still running into some minor issues, in the screen below I highlighted a glitch in the html table, I suspect the empty "else" clause of the if block to generate a spurious data in the html document. I'm not sure though. By the way, the Jamz version of the macro editor is so useful, I love it !
mt_macro.png
mt_macro.png (354.04 KiB) Viewed 5306 times

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: foreach output separator

Post by aliasmask »

Any [if:] with code should have { } for both true and false conditions.

Code: Select all

[H, if(condition): code: {
   <!-- stuff -->
};{}]
I recommend in your case the blank part should be <td>&nbsp;</td> when no button exists.

bobifle
Giant
Posts: 219
Joined: Thu Oct 19, 2017 12:36 pm

Re: foreach output separator

Post by bobifle »

That did it... This is really tricky.

Post Reply

Return to “Bug Reports”