More thoughts:
I think I’m not entirely understanding which problem(s) you’re trying to solve and how your proposed improvements would function. Could you provide some pseudo-code illustrating what you’ve envisioning? For instance (just pulling from the attributes you suggested in a previous post; this may or may not capture your intended usage):
To add multiple items to a designated list field:
Current method:
<$action-listops
$tiddler="My Tiddler"
$field="my-field"
$subfilter="[[New Tiddler]] [<currentTiddler>] [[New Tiddler 2]]" />
Pseudocode:
<$action-listitems
$tiddler="My Tiddler"
$field="my-field"
$items="[[New Tiddler]] [<currentTiddler>] [[New Tiddler 2]]" />
Obviously, this pseudocode example is nearly identical to the extant $action-listops method — the only thing I changed was the widget and attribute names. But I want to emphasize that this was a good-faith effort; I was genuinely struggling to imagine a different way to do it.
- We need
$tiddler to specify the tiddler to be acted upon. (As you said, both the real widget and the hypothetical could support the fallback value $tiddler=<<currentTiddler>>, so I don’t see this as a point for or against either.)
- Similarly, we need to specify
$field. $action-listops uses $field="list" as its default if neither $field nor $index are defined; I suppose a new widget could do the same.
- Notably,
$action-listops and $action-setfield both allow you to condense the field-setting and value-setting attributes into a single pair in certain situations:
<$action-listops $tags="[[new tag]] -[[remove this tag]]" />
-
<$action-setfield myField="My new field value" /> or <$action-setfield myfield={{{ My [[new field]] value +[join[ ]] }}} />
-
$action-listitems would have to set the field name (if not = list) since it’s intended to work with any field. It could conceivably offer the fieldname=fieldvalue shortcut used in $action-setfield, but I would then expect it to follow the same rules regarding values in quote marks vs. filtered transclusions. ($action-listops does use quotes around the values of $filter="..." or $subfilter="..." despite not treating their values as literal strings to be added to the field… but IMO, since filter appears in the names of both attributes, this usage is clear and consistent with $list filter="...". If $action-listitems isn’t using a $filter attribute, it wouldn’t be reasonable to expect that myField="[[new item]]" means anything but a literal string.)
- The title list is the standard TW way to provide a list of multiple strings that may contain spaces, so
[[New Tiddler]] [[New Tiddler 2]] seemed like the obvious way to format the $items value. Since you’d previous alluded to adding/removing <<currentTiddler>> from a list, I added [<currentTiddler>] as well… using the filter syntax because [[New Tiddler]] <<currentTiddler>> [[New Tiddler 2]] isn’t proper syntax for items in a list anywhere in TW. Of course, this means we end up with something that looks very much like a simple filter, at which point I would begin to wonder, “Can I use other filter syntax? Is [<currentTiddler>] [tag[HelloThere]] a valid value for $items?”
- Your list of potential attributes didn’t include separate named attributes for items-to-be-added and items-to-be-removed — reasonable, I think, to avoid bloating the list.
- I’d assume this means we’d use something like
$items="-[<currentTiddler>] -[[Remove me]]" to remove items from a field.
- … and we could probably mix items-to-be-added and items-to-be-removed in the same value, giving us something like
$items="[[New Tiddler]] [[New Tiddler 2]] -[<currentTiddler>] -[[Remove me]]".
- Again, this just looks like a filter.
You also suggested an $item attribute. I assume this would take a single string, which could contain spaces — i.e, more similar to $action-setfield $field=my-Field $value="This multi-word string doesn't have to be wrapped in square brackets." /> So I’d imagine the following would be equivalent:
All pseudocode:
<$action-listitems
$field="my-field"
$items="[[New Tiddler]]" />
<$action-listitems
$field="my-field"
$item="New Tiddler" />
or
<$action-listitems
$field="my-field"
$items="[<currentTiddler>]" />
<$action-listitems
$field="my-field"
$item=<<currentTiddler>> />
As attribute names, $item and $items are clearly extremely similar and easy to typo or misread — but they seem to demand distinctly formatted values, as one accepts a title list and the other does not. IMO, this is a situation we certainly want to avoid.
It’s also unclear to me how you’d indicate a single $item to be removed from a field. <$action-listitems $field="my-field" $item="-New Tiddler" /> doesn’t work, because -New could be a valid string in its own right. So we’d seem to need either two distinct attributes, which could potentially be combined in a single widget…
(still pseudocode)
<$action-listitems
$field="my-field"
$addItem=<<currentTiddler>> />
<$action-listitems
$field="my-field"
$removeItem=<<currentTiddler>> />
<$action-listitems
$field="my-field"
$addItem=<<currentTiddler>>
$removeItem="Extant value" />
or we’d need an additional attribute that specifies how the value of $item should be handled…
<$action-listitems
$field="my-field"
$item=<<currentTiddler>>
$action="add" />
<$action-listitems
$field="my-field"
$item=<<currentTiddler>>
$action="remove" />
which would preclude mixing multiple action types in a single widget.
In either case, we’d have to define a list of valid actions as either named attributes or potential values of an $action attribute. By contrast, any extant filter operation (including but not limited to all the “listops” operators is automatically valid in $action-listops $subfilter="...".
While the examples above may make it pretty clear, I do also want to note that none of these imagined alternatives are even particularly shorter than their $action-listops or $action-setfield equivalents. To me, this means they don’t qualify as useful syntactic sugar: they’d require me to learn new conventions and/or new syntax for very little benefit in terms of time or characters saved.
I should say that I do make heavy use $action-listops and $action-setfield in my own wikis, and I do get tired of typing them, so I’ve made a few shortcuts for my own use. For instance, many of my tiddlers have associated data-tiddlers with programmatically-generated titles, so I’ve added the following to my global definitions:
\function data() [[$:/data/]] [<currentTiddler>] +[join[]]
<!-- macros rather than procedures only because this is old code I haven't bothered to update yet --->
\define set-index(index, value)
<$wikify name="set" text="{{{ [<__value__>!match[]] ~[<currentTiddler>] }}}">
<$action-setfield $tiddler=<<data>> $index=<<__index__>> $value=<<set>> />
</$wikify>
\end
\define delete-index(index)
<$action-setfield $tiddler=<<data>> $index=<<__index__>> />
\end
This allows me to use shortcuts like
<<set-index newIndex>>
in place of
<$action-setfield $tiddler=<<data>> $index="newIndex" $value=<<currentTiddler>> />
<<delete-index newIndex>>
in place of
<$action-setfield $tiddler=<<data>> $index="newIndex" />
While I’d probably write these as procedures rather than macros if I were starting fresh today, I would stand by my choice not to use widgets for this syntactic sugar — specifically because it allows me to use short-form macrocalls and positional parameters. Of course, this also means that (at least as of 5.3.x) I can’t use dynamic parameters without returning to widget syntax…
<<set-index newIndex>>
vs.
<$macrocall $name=set-index index={{{ [<currentTiddler>tag[myTag]then[X]] ~Y }}} />
or
<$transclude $variable=set-index index={{{ [<currentTiddler>tag[myTag]then[X]] ~Y }}} />
… at which point I might as well just use $action-setfield directly because I’m really not saving myself much typing.
I think this illustrates the fundamental tension between brevity/convenience and flexibility. IMO, any syntactic sugar worth using must be visually simpler than the alternative — and this means we have to make some assumptions about what a given shortcut doesn’t do and what the user can’t customize. If $tiddler=<<data>> wasn’t hard-coded into my macro definitions, I’d have to add another named parameter, and probably a fallback value… and I couldn’t use a <<variable>> value of that parameter without resorting to a long-form macrocall, at which point the shortcut is no longer truly short.
(As a side note, these examples also illustrate what I do see as a moderate gap in working with index values — and particularly in deleting them. While $action-setfield can take either a $field or $index value, $action-deletefield doesn’t have a corresponding $index attribute, so we have to use this unintuitive <$action-setfield $index="indexName" /> workaround. That missing parallel is something I would actually really like to see added, even if we never get an $action-setindex or $action-deleteindex, but given Jeremy’s views on data tiddlers in general, I’m not particularly optimistic.)
All this to say: I think I must be missing something about your imagined implementation, because what I can come up with myself doesn’t seem simpler at all.
As a bit of a digression, your comment here also stuck out to me:
In the past, you’ve been quite critical of user solutions that introduced new JS features to accomplish things that can be done with extant TW script. In fact, in your user profile, you still define yourself as a “super user intentionally understanding tiddlywiki from an advanced user perspective, rather than solving problems via javascript and development.” And historically, you’ve also been a major proponent of maximally flexible solutions over ones specialized for one particular use-case. So I’m curious what it is about this particular issue that makes you feel new JS widgets are the best solution. Do you simply feel that it’s no longer as important to delve into extant features now that we can all “vibe-code” equally well?
I’ve never worked with ChatGPT myself, but I have noticed (in reviewing others’ broken code) that while it has a notably poor grasp of extant syntax, it’s very fond of hallucinating new widgets and operators. I can imagine that, given the much greater sample size available for Javascript, it would also be easier to get it to spit out a new JS widget than to force it to provide a working solution using core TW script. Do you see this as the best way forward for “naive” and/or “power” users?