Could I get a substring from a string stored in a field of a Tiddler?

I set a field named t.level with the value "01.02" to a Tiddler named "2023001". The whole value is easily obtained by using codes as follows:

<$list filter="[tag[Things]field:t.level[01.02]]">
<div>
<$text text={{{[<currentTiddler>get[t.level]]}}}/>
</div>
</$list>

Is it possible I just get a part of the whole value, e.g., "01" (first half part) or "02" (latter half part)? If it is viable, I want to put the part into a variable as a condition to search for some Tiddlers.

You’re looking for the split operator! If your t.level fields always use the XX.XX format, then [<currentTiddler>get[t.level]split[.]first[]] will give you the first half, and [<currentTiddler>get[t.level]split[.]last[]] will give you the second. You could then define these filters as functions to get quick access to their values as variables:

\function t.level.first() [<currentTiddler>get[t.level]split[.]first[]]
\function t.level.second() [<currentTiddler>get[t.level]split[.]last[]]

which you can then reuse as variables (<<t.level.first>> or [tag[Things]search:t.level<t.level.first>]) or—assuming that you have at least one . in the name of the function, as custom filter operators (like [t.level.first[]is[tiddler]]).

For more complicated strings, you may also be interested in other order operators like butfirst, butlast, nth, etc. You can also use splitregexp to split a string at a point defined with a regular expression (so splitregexp[\n] will split its input at every line break, for instance.)

3 Likes

FYI:

There is no need to specify the current tiddler the way functions work, unless you want to specifically act on another value

\function t.level.first() [get[t.level]split[.]first[]]
\function t.level.second() [get[t.level]split[.]last[]]

<<t.level.first>>
<<t.level.second>>

In this case I would be inclined to call the second one last, because that is the truth. eg if the field contains 99.98.k

Second would more accurately be defined as;

\function t.level.second() [get[t.level]split[.]nth[2]]

Sorry, this isn’t true: the get operator takes all tiddlers with the t.level field as its input unless otherwise specified, so it won’t focus on <<currentTiddler>> by default. Here’s a very similar example tested at tiddlywiki.com to illustrate this difference:


vs.
image

Variable names are of course a matter of preference, and I picked one largely at random based on the data @likuan61 provided.

Sorry, you are correct with get because it is not restricted to the current title, other operators this is true.

\function format.today() [format:date[DDth of MMM, YYYY]]

{{{ [[3009232]format.today[]]

You’re still providing a specific input for format:date... — it’s just a literal value rather than a variable. Most filter operators will default to using [all[tiddlers]] in the absence of a specific input string; the list-constructing operators are the exceptions, marked with “C” or “C?” in the filter overview. This can be especially confusing when you’re using a function to define a variable—
since functions only return their first result, it’s easy to assume that it will be the one relevant to the current tiddler and not simply the first tiddler that matches the filter condition.

Notably, enlist is a selection constructor, so <currentTiddler> isn’t needed in filters like [enlist{!!tags}], although it’s functionally equivalent to [<currentTiddler>get[tags]enlist-input[]].

@etardiff @TW_Tones Thanks a lot!

I don’t think we are in disagreement, beyond my initial oversight, I am really making use of functions for the following purposes;

  • To return a single value to conditions tests or display the result of a filter using join for longer strings.
  • As a filter operator, in this case I invoke the function from inside another filter.
    • This is more like the example I wanted to document.

Try this on tiddly wiki

\function caption.title() [get[caption]else{!!title}]

# <<caption.title>> somewhat random title 
# {{{ [all[current]caption.title[]] }}} the "custom operator" only operated on the current tiddler
  • Note you do not need to start with [<currentTiddler> because that is set in the calling filter.
  • This follows a pattern I use to write my code to operate on the current tiddler, and change that.

[Edited] Here is an example I find curious, and tells me a lot.

\function comma.list() [join[, ]addsuffix[.]]

# <$text text={{{ a b c d +[comma.list[]] }}}/>
  • Output is a, b, c, d.
  • I understand the +/and “hand off” the whole list to the custom operator.