Questions about TW Source Code

Just a general thread for questions which pop up as I attempt to understand TW’s inner workings.

What is this bit of dollar sign magic? How is this require() resolved?


var widget = require("$:/core/modules/widgets/widget.js")

TW implements its own require function, which works in the browser and for TW Node.js client server configurations. It does understand the TW “syntax” for system tiddlers.

In TW a tiddler prefixed $:/ is a system tiddler which by default is hidden from lists in the UI.

Is the TW “file system” explained somewhere?

$:/temp or $:/config make some sense but what about $:/status.

And, in general what does the path seperated hierarchy mean or imply? Why do it, what’s the functional implication of structuring titles this way in general?

As I wrote in the first reply. $:/ is the indicator for system tiddlers

The rest of the tiddler title we call a namespace. Namespaces can easily be listed with eg: [prefix[$:/temp/]]

Tiddlers prefixed $:/temp/ are not saved and have no effect on the TW dirty-indicator.

Tiddlers prefixed $:/state/ are saved but do not influence the dirty-indicator

$:/config/ tiddlers contain internal configuration data for default values. Most of the $:/ControlPanel settings are prefixed with $:/config.

Also See: Naming of System Tiddlers and StateMechanism

2 Likes

TW has 2 (3) types of tiddlers.

  1. Content tiddlers that have been modified by the user
  2. Shadow tiddlers that are delivered as plugins
  3. Modified shadow tiddlers, which become system tiddlers because they are prefixed $:/

The TW core is a plugin named: $:/core
At startup first the TW core and then the plugin tiddlers are extracted and initialized. They are stored into an internal memory we call “Shadow tiddlers”.

This memory is immutable, but can be overwritten. eg: If you open the link Animation Duration in the Control Panel and try to edit it, you get a warning.

You are about to edit a ShadowTiddler. …

It is perfectly fine to do so because ControlPanel settings are meant to be changed.
If they are changed shadow tiddlers become “normal” “system tiddlers”. They are saved and the next time you start your wiki they will be restored.

The advantage of shadow tiddlers is. If you delete the $:/config/AnimationDuration tiddler. The shadow tiddler will take over again

That’s a key feature of TW. The user has full control over every aspect of the UI, but there will always be a sensible default value, which can be re-activated again.

4 Likes

Thanks for the answer and the helpful link I somehow missed. What is “$:/status”?

I think that’s a typo. But it is like that since 11 years.

It’s not exactly a typo, more an early convention that didn’t gain adoption elsewhere in the core. The idea was that the $:/status/* namespace was for tiddlers that were intended to be written by the system and only read by users. For example, changing $:/status/UserName isn’t sufficient to change the username throughout the system when using the client server configuration, it only changes the username visible to the user interface.

As it turned out we haven’t encountered very many configuration tiddlers of this type and so the prefix has fallen into disuse.

1 Like

I‘ll add some comments here on learning TW5.

  1. Filters should be renamed to TQL (Tiddly Query Language) or Pipelines or something to better indicate what they are rather than what they began life as. Most JS programmers identify „filter“ with the WHERE clause in SQL - something which limits results.

  2. The word „macro“ makes sense to C/C++ programmers or even to normal users as a way of reusing or automating functionality or content. However the new naming of functions, procedures and widgets makes little sense to me since, as the docs describe, they are all still just reusable blocks of text. IMHO a widget should be purely something which returns HTML and should possibly be called a „component“. Semantically I feel function is synonymous with procedure and there should be only one and it should be imperative code. A third type if required could be declarative.

As a JS programmer, it’s easy for me to forget that I am not the main target audience for TW. No programmers are. Familiarity for programmers is not a primary goal. Obviously when we can, we should use terms that won’t confuse programmers, but that is secondary.

Certainly, TW filters have much broader functionality than say Array.prototype.filter or SQL’s where. I’m guessing that they started out like those and grew. The filter run prefix, :filter is more similar to those. But the category of Filters in TW does much more. Trying to change the name in a 20-year old system is likely to confuse many more users than it helps.

Or in a broader way to LISP programmers.

I’m still new enough that I’m not certain about this, but I think of widgets as representing DOM nodes, represented that way in the code as well, with configuration stored in DOM attributes. Procedures are parameterized blocks of reusable HTML text, and functions are parameterized blocks of reusable filter text.

The functional programmer in me shudders!

3 Likes

The rationale for using the term “filter” was that in TW the initial input to queries is the list of all the tiddlers in the wiki, and so these queries could be seen as filtering the list of all tiddlers, rather than creating a list of tiddlers from nothing.

It’s not a perfect term, and suffers from the same issue as several other areas of TiddlyWiki’s design where it reuses an existing term to mean something slightly more specific than the generally understood meaning (other examples would be “tag”, “macros”, “variables”, and as you note “procedure” and “function”). it’s a trade-off; we can’t invent new words for everything, and so I tried to invent words for the things that I thought deserved them because they were genuinely distinctive (“TiddlyWiki” itself, and “tiddlers”), and reuse the least-worst existing term in other cases.

4 Likes

Yeah, I see how filter was initially called that - and someone famous once said “naming is hard”. I certainly admire your coining of domain-specific terms such as “tiddle” and “story” as opposed to generic “item”, “entities”, “list”, “system” etc.

I suspect “filter” was initially a search syntax and in that sense it initially did a WHERE/filter() on all tiddlers. But “adding 2 numbers with a filter”… that’s the kind of extension you see in SQL and I thought filters could get upgraded to an SQL naming where you have the query syntax TQL and then the query expressions or functions. I also personally find the double-meaning of square brackets confusing. They designate runs and steps if I’m not mistaken but it’s too late to change that.

Perhaps the docs could be updated to better deliniate and define when one would use a widget over a function over a procedure.

A procedure is a named snippet of text… Procedures are implemented as a special kind of variable. The only thing that distinguishes them from ordinary variables is the way that the parameters are handled.

A function is a named snippet of text containing a Filter Expression. Functions can have named parameters which are available within the function as variables. A procedure is a named snippet of text… Procedures are implemented as a special kind of variable. The only thing that distinguishes them from ordinary variables is the way that the parameters are handled.

This tells me almost nothing about what the difference is between functions and procedures.

For me a “procedure” contains some imperative code steps and cannot simply be a snippet of text (which happens to be code). That’s an implementation detail in a platform in which pretty much everything is a snippet of text.

Of course the target audience of TW is normal non-technical users who, IMHO, will not want to be confrontend with any query syntax however easy you make it. They want a UI which builds an advanced search query (filter).

The techies to make plugins and editions on the other hand are without question JS developers and I’ll be honest, it’s confusing nomenclature like this, which confused me and kept me on TW Classic for a decade instead of switching.

With apologies for diverging from the original intent of the thread…

IMO, the biggest reason not to change existing terminology is that it’s already in widespread use. We don’t have a huge community of regular posters, but we do have about a decade’s worth of TW5 questions and answers across the various forums. Changing the terms used in official documentation would make this valuable resource needlessly confusing.

I’d love to see some data, but I don’t see how this can be true. I believe that many of our most prolific contributors do have some formal programming experience, but authoring a plugin or an edition doesn’t require any JS knowledge, and JS developers don’t have a monopoly on the desire to tinker. As a data point of one, I have some heavily customized private wikis and write filters, functions, procedures, and plugins regularly, and I’d never previously dabbled in anything more technical than HTML. To me, the fact that TW doesn’t presuppose any particular background is one of its greatest strengths.

2 Likes

I’ll defend your right to tender your experience as you see it. It took me a long time to switch from classic to TW5 (though not 10 years).

Let me lay out a challenge for you (by way of friendly advice) – question your conclusions: it can be both painful and liberating.

Good luck!

1 Like