No touch tags - or flags on tiddlers without editing or changing the tiddler

Great stuff @etardiff!

I know this wasn’t aimed at me, but my take is that the goal is mostly to override certain features of any tiddler without actually changing that tiddler. So while core tiddlers would probably be a major use-case, it would also help with MWS’s bags-and-recipes design and with anyplace you have tiddlers you want to override but don’t want to touch.

I really do think this would cover pretty well all the use-cases we’ve discussed here. Moreover it would serve as a substantial first step toward solving the issue I discuss in Tiddlers with JS-prototype tiddlers.

I would prefer $:/override/.

Major caveats

I’m learning little bits of the core, finally, but still don’t have nearly the experience to answer this. But my suspicions are that this would be huge. Every get for any field would need to check not only the tiddler object itself, but also its overriding peer. I don’t know how well those could be cached in the object itself. If they can’t it would be much worse, but even if they can, it would turn code like

tiddler.fields[fieldName]

into something logically like this:

tiddler?.__peer__.fields[fieldName] ?? tiddler.fields[fieldName]

I don’t know whether the code for this is already centralized so that we can fix this in a single place, so I don’t know how much work it would take to implement. But it’s possible that it would be a fairly simple change.

My other concern would be about how to remove an override. If for instance, we overrode the text field, and later realized that we no longer wanted to do that, we can easily set it to an empty string, but we can’t easily remove the field. However, for, say, the tags field, we would want the empty string to override the existing non-empty one. I imagine would could find a UI that helps with this, but I think it’s at least a potentially serious problem.

So I like the idea, but I’m still somewhat wary of it.

1 Like

As would I! I knew someone would have a better suggestion.

This is my major concern as well. I’d hoped the issue might be somewhat mitigated if this were a shadows-only affordance — but this was largely because I couldn’t immediately come up with any scenarios in which I wouldn’t want to modify a standard tiddler directly. Your MWS use-case is a good one, and there may be other uses I hadn’t considered.

Why not? In my mental model, removing a field from an $:/override tiddler is precisely how you’d revert to the “base” field content — just as you delete a shadowed tiddler to revert to the shadow. I see it as resembling the distinction between !has[field] and !has:field[field]: a field that’s present but empty would constitute an override. So this would be distinct from get[field], where “empty” and “absent” are treated the same way.

Unfortunately, I don’t have the technical proficiency to look into this myself. I hope someone who does can weigh in.

Thanks as always for your thoughts!

1 Like

It’s not hard to come up with others.

Here’s a JSON bundle of data tiddlers: US_States.json (10.7 KB). They look like this:

title: US State/Alabama
tags: [[US State]]
abbreviation: AL
capital: Montgomery
largest-city: Huntsville
established: 1819-12-14
square-miles: 52420
numbber-of-reps: 7
number-of-counties: 67

title: US State/Alaska
tags: [[US State]]
abbreviation: AK
capital: Juneau
largest-city: Anchorage
established: 1959-01-03
square-miles: 665384
numbber-of-reps: 1
number-of-counties: 30

...

(with data cribbed from Wikipedia.)

You can import this collection into your wiki in the usual way. But you can also share it with another wiki, even if you’ve lost the original JSON file, by simply dragging the custom tag pill to the new wiki. This makes for easy sharing of data across wikis.

However, if you update US State/Alabama with last-visited: 1981, this data is no longer pure. It gets hard to share when the next person doesn’t want that field, but needs a state-flower one. And someone else wants average-SAT-score. The data diverges and is not easily shareable. But with this mechanism in place, we can easily do our extensions like this:

title: $:/override/US State/Alabama
last-visited: 1981
scenery-rating: 3

title: $:/override/US State/New Mexico
last-visited: 1982
scenery-rating: 8

and the original data remains pristine.

Sure, but at the moment, there’s no obvious way to remove the text field. Yes, we can add an affordance for doing so, but there’s a few fields that would be awkward to delete.

I do. (Probably.) But I won’t have the time for at least a few days.

That’s interesting, and I think it may suggest an underlying difference in the way we conceptualize the role of a “standard” tiddler. Personally, if I wanted to preserve a “pure” data set that could be shared between wikis, I’d package it as a plugin. And conversely, when I’ve borrowed tiddlers either between my own wikis or from others’ wikis “in the wild”, I’ve never been remotely concerned with maintaining a record of the original data — or, indeed, with shareability. I expect the data in a “standard” tiddler to adapt to the needs of the wiki in which it’s used.

On the other hand, one issue I’ve occasionally encountered is that while plugins offer a convenient method for packaging and sharing “pure” data between wikis, it’s less convenient to surface a plugin tiddler through standard search or even standard filters (unless you’re already in the habit of starting all your filters with all[shadows+tiddlers]). In this case, a package of standard tiddlers (with optional overrides) might be a good alternative to a plugin. That’s not a use-case that would have occurred to me, so thank you for the insight!

Ah, I think I see the point of miscommunication. You’re talking about UI methods for removing the text field in the current EditTemplate; I was thinking on a more theoretical level, where you can use $action-deletefield + a button to delete almost anything.

I do think a user-friendly override system would require some updates to the default editor. It would almost certainly require some extra buttons, but we’d probably also want to clearly highlight fields that were being overridden. Off the top of my head:

  • A button to create an $:/override tiddler for the current {!!draft.title} (perhaps only visible for non-shadow tiddlers, if shadows prioritize the override system by default?)
  • If an override exists (or if the tiddler is a shadow), display a tabbed field editor: the first tab corresponds to the override tiddler, the second to the “real” tiddler.
  • If no changes have been made, fields in the override tabs use the default attribute of $edit-text to display the value of the corresponding field on the “real” tiddler (or perhaps its draft?). This would let you start editing the override immediately, while also providing a live view of the “effective” field values.
  • Perhaps a $diff-text widget highlighting any changes? We already have this option in the text preview window; it would be nice to have it for “shadow” fields as well.
  • You could add and delete fields in the override tab as usual, with the caveat that deleting a field would restore the default value.

We’d probably also want to indicate any relevant overrides in the Info section of the ViewTemplate.

1 Like

I have no problem with this tread being expansive with related ideas.

Today I am trying to fix a fault in my solar panels, not sure how much time I will have here today.

I too have an interest in an additional cascade over existing tiddlers and shadows. However without giving you a full response @etardiff can you explain how your approach would deal with multiple plugins wanting to do the same thing?

  • core code that looks for tiddlers with a given tag is the most hackable method we have at this time. That is not tagging core tiddlers.
  • the flag model may help here too, but only once the core is coded to respond to such flags as is the current approach with system tags.

Although I did not elaborate my exploration of list tiddlers it was exploring mechanisms that may assist in some of these adjacent issues.

  • I did at length explore what I named ghost tiddlers not dissimilar to your idea, but different.
  • I think to achieve what you are suggesting we may want an additive process, and a subtractive one at least against list fields.
1 Like

Do you mean if, for instance, I installed multiple plugins that all included a different override for $:/core/ui/PageTemplate — that is, they all included a shadow tiddler $:/override/$:/core/ui/PageTemplate?

Honestly, I don’t have a good answer. I suppose I would expect the last version to win? This wouldn’t be any different from the current system, though (where, barring a non-shadow version, the last $:/core/ui/PageTemplate would be used), so I don’t think it’s particularly a downgrade.

How would your flags approach solve this issue? I apologize if you’ve explained this previously; it’s not coming readily to mind.

Good luck with the solar panels!

1 Like

I haven’t thought it through very carefully, as without this extension mechanism, it makes no real sense. But I needed a break from all the politics stuff I was working on last night. (I’m co-chair of my local Democratic Town Committee, and municipal elections are fast-approaching!) Creating that silly little states list was exactly the right 20-minute project. I don’t know that I would actually use states that way, but it might be a great way to deal with the lists of elements and compounds for my periodic table wiki. I’ll have to consider it more.

Yes, but I’ve spent no time imagining a design for this. Thanks for the start. It sounds like an excellent system. But I am worried about anything that steepens the learning curve for using TW. So I’m wondering if there is an alternative which makes a single up-front choice about whether this edit session is for a regular tiddler update, a shadow tiddler clone update, or an override update, and then everything happens on a single tiddler.


One more major caveat, also about deleting fields. Does an override tiddler simply set the value of a field to blank in order to override it? If so, are there places where this will cause problems? Because these two are distinguishable: has[xyz] and has:field[xyz]. What if we want our override to set the field value to the empty string? How do we distinguish between that and removing the field?

That’s the only thing I can see that makes sense.

Let me make sure I’m following…

  • Tiddler A has field foo: bar.
  • $:/override/Tiddler A has field foo: — that is, an empty field. (If the field’s not present, no override occurs.)

In this case (assuming that has and get and other similar operators look for override fields first) I’d expect [[Tiddler A]has[foo]] and [[Tiddler A]get[foo]] to return nothing, and [[Tiddler A]has:field[foo]] to return “Tiddler A”. This would make it functionally impossible to get [[Tiddler A]has:field[foo]] --> null if an override exists. Is that the issue?

It strikes me as a fringe issue, but worth pointing out. And I’m afraid I don’t have a good solution in mind.

In writing this, it occurs to me that we might also want additional suffixes for has and get — perhaps :original and :override to look only at the corresponding original/override tiddlers, rather than following the typical override → original priority list. So there would certainly be added complexity… :thinking:

I’m feeling ever less optimistic about the feasibility of this approach. Still, thank you for the reality check.

1 Like

Yes, that’s it exactly.

I think it’s likely a minor issue, but I’d want to know that the core, official plugins, and other popular plugins and editions don’t actually use that distinction. If they don’t, then it could be a documentation footnote. If they do, we have more issues.

Sorry. :frowning:

I do still have hope, although it too is somewhat diminished.

Part of the trouble is that what I’d really want is one large step further than this: the equivalent of nesting doll tiddlers, where an outer tiddler may have the field we want, but if not we check with the one inside it, and then the one inside that one, until we find it or run out of dolls. Jeremy explained in that thread why, although a possibly very useful approach, it cannot be added to the core. But I may one day try to get a version of it in userland.

1 Like

it does not solve the problem you pose, only demonstrates a no touch method. It needs further design.

I think I fixed the solar panels.

Today I pack for a house sit that starts tomorrow.

There may be some room to use the existing shadow tiddlers system, the last plugin wins but I wonder if we could provide more visibility and control of this process for targeted tiddlers. it is actually quite easy to move a tiddler into and out of a utility plugin. if we can read all versions of a shadow then we can see all variations and generate a synthetic tiddler. :thinking:

As Raised here Tip: Scoped Styling - #5 by TW_Tones I see that we have the core hackability relating to SystemTag: $:/tags/ClassFilters/TiddlerTemplate

  • This seems to be an opportunity to display on a tiddler a flag indicator without using a view template tag
  • However this feature is not well documented.

I just reviewed this issue, and one idea, which may be equivalent for you is redirection via transclusion.

If you get a field value through transclusion and that field has a transclusion in it, then it will keep transcluding multiple levels deep until if returns a value.

  • {{!!fieldname}} when fieldname contains {{parentTiddler!!fieldname}}
  • When the parentTiddlers “fieldname” contains {{otherTiddler!!fieldname}}
  • When the parent tiddlers “fieldname” contains a value it will return "a value’.

Of course this could be turned into a single filter cascade that looks at multiple locations until a value is returned, and one could make the tiddler names tested as programaticaly generated.

  • Moving it into a function even better get.fieldname[]

I would find this too heavyweight. It would mean that child tiddlers had to know and copy all the fields of their parents to add the transclusions necessary to follow through the chains. And if the parent changed, then all children would need updated.

This, on the other hand, is what I think would potentially work. It wouldn’t be just a single function. We would need extensions to the get operator, the $view widget, and many other things. The question is whether there is a relatively small core of these which the other could themselves call. I haven’t done any of that analysis, but I do worry that this would be quite a large undertaking. In that thread, IIRC, Jeremy mentioned some place where he’d done something like this Object inheritance, but I never looked deeply at it. When and if I do, I will be examining that closely.

Wether its light or heavy is realy dependant on meta issues. The children may not need updating.

However if such a field value cascade is going to work, there needs to be an identified logical pattern where to look. ie what ties the one or more tiddlers together.

  • Have you an idea for the cascade pattern in your mind?

I recently used a transclusion to invoke a template to replace headings here Table of Contents from Headers - #9 by TW_Tones lets say that we move the cascade to a tiddler such that a field value may contain {{fieldname||cascader}} and within the tiddler cascader was the logic to source the value from an established cascade, for example from the same fieldname in $:/ghost/currentTiddler then $:/default/currentTiddler and if nothing a default value.

  • Further work may allow the default to be provided in the transclusion {{fieldname||cascader|default}}
  • An importiant point is that transclusions can be nested, and a reference to transclude a field will work through the series of transclusions like other cascades.
  • keep in mind the currentTiddler will be the title in the transclusion, eg Fieldname, you can use storyTiddler to find the visible tiddler.

In this proposal a field is just a field with a value, unless that value is a transclusion. all be it accessed via transclusion or reference (not with a get in a filter). So in the “end tiddler” we can change the value that suggests you need to get it from elsewhere, elsewhere is resolved by the transclusion of a utility tiddler. eg the above cascader tiddler.

  • Think of this as giving the field a special value, one that can be sourced from a cascade.

I can give an example if you can answer;

Have you an idea for the cascade pattern in your mind?

[Post script]
The other approach is to reference the field value as a filter allowing the field value to contain the cascade filter itself.

  • Just as we have the ability to provide a custom field editor, we could do this to view or retrieve the field as well. Where that field contains a filter or transclusion (function or procedure) to resolve the value.

Yes, I discussed it in that thread we’ve mentioned. The idea is simply that a tiddler may have a field, let’s say, _parent_tiddler that contains the title of another tiddler.

A new get' operator begins to work like the current get, but if the target tiddler (Tiddler Z) does not have the field we’re seeking, then it checks if Tiddler Z has _parent_tiddler. If it does, and let’s say it has value “Tiddler Y”, then we check if this tiddler has that field. If it does, we just return that. If it doesn’t, we check if Tiddler Y has _parent_tiddler, rinse and repeat. Eventually we’ll hit a tiddler that doesn’t have a _parent_tiddler… maybe all the way down to “Tiddler A”. Only if that final one also does not have the field do we return an empty value.

Setting a field wouldn’t change. We would set on Tiddler Z. But we do have access to the other tiddlers, and if we updated the value in, say, Tiddler M, the new value would show up in Tiddler N, unless it was overridden, and then in Tiddler O, again unless it was overridden… and eventually in Tiddler Z. In practice, I would not expect very deep hierarchies, but they would be available if necessary.

This would not be only the get operator. It would also involve the $view widget, and probably many other places.

The whole point is to answer this question from that thread:

We have a shadowing mechanism, allowing us to use our tiddler in place of another, even though that other one still exists and will be resurrected the minute our own is deleted. Could we do the same thing at the field level?

So as a test perhaps we could use the parent field using TOCP of marios?

So a tiddler has zero or one parent and if no value is returned (or the field does not exist) we look in the parent… then if not found use a default.

  • Why do you mention the view widget? My personal feeling is widgets are where things go to be displayed. I would not use it as a result.
  • Another alternative is the lookup operator.

I am doing a few tests off line and it all looks promising, down various routes.

  • I have often used a macro to retrieve a field value because that macro can be arbitarily complex, if it cant return the value from the actual field it can go and find it elsewhere. Including climbing a tree. Although now days I would preferentialy use a function, even custom operator, it returns the first value, as text and nowikification required.

Here is a working example using a function (not chasing parents)

In a global tiddler;

\function get.fieldcascade(fieldname default:"default value") [<storyTiddler>lookup[$:/ghost/],<fieldname>!is[blank]] [<storyTiddler>lookup[$:/temp/],<fieldname>!is[blank]] [<default>]
  • note although having to give the fieldname looks redundant, it allows for redirection and makes the examples below work.

In a subject tiddler the value for fieldname is set to <<get.fieldcascade fieldname "the default value">>

You can access the fields value on the current tiddler in the story using;

{{!!fieldname}}

<$transclude $field=fieldname/>

<<get.fieldcascade fieldname "the default value">>

Not

{{{ [{!!fieldname}] }}}

{{{ [all[current]get[fieldname]] }}}

I can’t test the TOCP equivalent until I have a TOCP test data set.

  • However I would possibly use the decendants operator to get the set of titles in which to look, returning the first non blank value.
  • We could even ignore fields with the prefix << so the “redirect” can be set at multiple levels.

Maybe, I’ve only glanced at it; I’ve never really tried it.

We might have

title: Element/Iron
tags: [[Chemical Element]]
atomic-mass: 55.845
atomic-number: 26
atomic-radius: 1.7
boiling-point: 3134
...

and

title My Iron Research
_parent_tiddler: Element/Iron
boiling-point: 3122

Iron is an amazing element, made famous of course by the suit of
[[Marvel Comic|https://en.wikipedia.org/wiki/Iron_Man]]'s ''Iron Man''.

It has an atomic number of <$view' field="atomic-number"/> and
an atomic mass of <$view' field="atomic-mass"/>  My lab partner
and I calculated its boiling point as <$view' field="boiling-point"/>

But you want to know the crazy thing?  Iron Man's suit isn't actually
made of Iron!  I know, false advertising, right?
...

When we view that latter tiddler, we want the atomic number and mass to shine through from the parent tiddler, but we want the text and boiling point from the child.

That’s my goal.

The following will do that. The $view widget cant display anything but something found in a tiddler field (by default text) so it is of no value when wanting to view the result of a function, transclusion or procedure.

  • I rarely use the view widget now, and the format operator helps out as well.

Instead you would use one of the following;

  • With your required fieldnames.
  • This would be if I modify get.fieldcascade to follow the parent
  • we could add a parameter that rather than seek the first value, it can seek the Nth parent, then above.