Filter all non-empty fields of a tid?

Hi y’all!

How do I list all non-empty fields of a tiddler? The intuitive way would be the following but with perhaps some suffix for fields:

[<currentTiddler>fields[]]

…but, nope, not possible. (This can be contrasted to has op which does feature an optional suffix to distinguish fields with vs without values.)

The following complexity does work… but come on it is way too convoluted:

[<currentTiddler>fields[]] :map[<..currentTiddler>has<currentTiddler>then<currentTiddler>] +[!is[blank]]

(Yes, +[!is[blank]] is needed and it must not be baked into the previous run. You can test this by creating two custom fields; one empty one one with value, and add a final +[count[]] to the filer. Apparently the preceding steps output also empty stuff, perhaps what is explained for the split op docs.)

Unless I’m missing something, I’m going to propose a fields[] suffix to remedy this, but I would appreciate a decent solution meanwhile or to at least hear that “yeah, that little monster is currently the way to do it”.

Thanx!

P.S
You haven’t seem much of me for these past months due to work. It’s like employers refuse to understand that tiddlyfiddling is more important. Hopefully the work vs tiddly ratio will go back to normal very soon.

1 Like

Try this:


[<currentTiddler>fields[]] :filter[<..currentTiddler>has<currentTiddler>]
2 Likes

Ah, that is definitely an improvement! Thanks Saq!

Do you have any opinions about the idea with a fields suffix to simplify this quite a bit?

i can’t comment on the tech but i loved the tiddlyfiddling commentary :slight_smile:

Pardon my ignorance. I have not seen the <…currenttiddler> notation before. What do the periods do?

In some filter prefixed runs, the <..currentTiddler> refers back to the “original/outer” currentTiddler, whereas <currentTiddler> refers to the “new one” as created by the previous filter which is input to the prefixed run. See docs for more details. (You can probably even search directly for ..currentTiddler)

It is the time of TW 5.3.0 :wink:
So you may write your own filter operator (using function)

Thanks @twMat . I somehow had missed that. Very useful indeed!

Keep in mind this is only an issue if you are trying to write a single filter

  • Single filters need map and reduce or other tricks if you want to access nested data,
    • Like the OT, that “asks for the fields with values, found within a tiddler”
    • Let us call these “compound filters” for this discussion.
  • If instead you just nest two lists,
    • not only can you get the result you asked for
    • but you now have the variables fieldname and fieldvalue to make use of which you do not get to define in a single filter.
    • You can even inset wikitext to appear before and after each nested item
<$list filter="[all[current]fields:exclude[text]]" variable=fieldname>
   <$list filter="[all[current]get<fieldname>]" variable=fieldvalue>
      <!-- here --><<fieldname>>=<<fieldvalue>><br>
   </$list>
</$list>
  • This gives you the result you asked for.

Conclusion

  • Not only can you use nested lists to solve the OT you get;
    • To name the variable from each nested list
    • Your filters are easier to read
    • Easier debugging
    • The option to have wikitext for every field, and or add counters etc…
  • Note the line with <!-- here --> is where you place what you want to do for each non-empty field, just as you would inside a list with a “compound filter”.
  • It really makes no appreciable difference if you force your logic into a single filter
    • beyond making the filter more complex to read.
    • I doubt for most cases there is even a possibility of a performance issue.
  • When tiddlywiki is rendering your result, it simply does what you ask whether you force it into one filter or nest filters
  • Using “compound filters” instead of nested lists can just make the filter more complex, return less information and be harder to read.
  • It is a personal impression that;
    • The shiny new filter operators ofthe distract people from a much better and self documenting set of solutions, using nested lists.

Not withstanding the above I believe making use of the subfilter operator or TW5.3.x ffff function, ie filter function, may allow us to make easier to read and follow compound filters.

  • I may return with an example.

Reference: Before and after wikitext annotated

<$list filter="[all[current]fields:exclude[text]]" variable=fieldname>
  <!-- before each fieldname found in tiddler -->
   <$list filter="[all[current]get<fieldname>]" variable=fieldvalue>
       <!-- before each field with a value -->
       <!-- here --><<fieldname>>=<<fieldvalue>><br>
       <!-- after each field with a value -->
   </$list>
  <!-- After each fieldname found in tiddler -->
</$list>

Note: the short cut use of get<fieldname> as it only generates a list item when a value is returned (non-empty), alternatively you could say [has<fieldname>get<fieldname>] but this is more verbose.

That is a tricky one as the interactions with the existing suffixes for that operator might be confusing. Overall, it isn’t very realistic to try to address all use cases with bespoke operators and the goal should be a to have a rich set of operators that can be combined to achieve most desired results. One the other hand, we do try to simplify the most common use cases, though I am not sure how often this requirement comes up.

As Mohammad mentions, v5.3.0 will also bring the ability to define custom operators via wikitext which should be helpful for users that find themselves running into specific uses cases often that are not otherwise catered for through bespoke operators.

1 Like