A verbose filtered transclusion … can it be trimmed?

I was building a filter where I wanted to be able adjust the polarity of the sort mechanism while also taking into consideration a sorting method as it is declared in a field called sortquery, and eventually got it working with the filtered transclusion below.

{{{ [title[$:/templates/bookcase/full-list]search:sortquery[!sort]] :then[title[$:/templates/bookcase/full-list]get[sortquery]search-replace[!sort],[sort]] :else[title[$:/templates/bookcase/full-list]get[sortquery]search-replace[sort],[!sort]] }}}

The code is in use here gavart.ist — Gavin Gamboa 🌱 digital garden  work repository  🗂  personal wiki

My question is regarding syntax. This code seems too verbose. Am I missing a way to simplify this, e.g. not having to declare the title each time ?

I took a look at the linked tiddler and found several places that could be made more concise. The revised code follows.

  • Rather than using $:/templates/bookcase/full-list in each $action-setfield, I used the $tiddler widget to redefine <<currentTiddler>> around all the $button widgets. This lets us eliminate the $tiddler attribute from each $action-setfield.
  • You can set multiple fields of the same tiddler with a single $action-setfield by using the format fieldname="value" (or fieldname={{{ [[value]] }}}, etc.) rather than $field="fieldname" $value="value". This also lets us eliminate several unnecessary lines.
  • Re: title[$:/templates/bookcase/full-list]get[sortquery]
    • The title operator is unnecessary: [$:/templates/bookcase/full-list]get[sortquery] would be equivalent…
    • … but since we’ve set the <<currentTiddler>> variable to $:/templates/bookcase/full-list, <currentTiddler>get[sortquery] or {!!title}get[sortquery] would be shorter…
    • … and {!!sortquery} is the shortest possible equivalent.
  • This lets us simplify the filtered transclusion to {{{ [{!!sortquery}search[!sort]search-replace[!sort],[sort]] :else[{!!sortquery}search-replace[sort],[!sort]] }}}
`Reading log + Notes`

<div class="discography-types-categories">

🗂️&nbsp;&nbsp;<code class="hideOnMobile">Sort</code>
<$tiddler tiddler="$:/templates/bookcase/full-list">
<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		sortquery="[!sort[sortdate]]"
		tagquery=""
		sort="Chronological"/>
	Chronological
</$button> • 
<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		sortquery="[sort[author]]"
		tagquery=""
		sort="Author"/>
		Author
</$button> • 
<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		sortquery="[sort[date]]"
		tagquery=""
		sort="Year"/>
	Year
</$button> • 
<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		sortquery="[sort[title]]"
		tagquery=""
		sort="Title"/>
	Title
</$button> • 
<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		tagquery="Handwritten Notes"
		sort="Handwritten Notes"/>
	Handwritten Notes
</$button>
<br>
↕️&nbsp;&nbsp;<code class="hideOnMobile">Order</code>
<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		sortquery={{{ [{!!sortquery}search[!sort]search-replace[!sort],[sort]] :else[{!!sortquery}search-replace[sort],[!sort]] }}} />
	Reverse
</$button>
<br>
🖼️&nbsp;&nbsp;<code class="hideOnMobile">Views</code>
<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		view="$:/templates/bookcase/cover-display"/>
	Cover Grid
</$button> •
<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		view="$:/templates/bookcase/list-display"/>
	List
</$button>
</$tiddler>

</div>

<$transclude $tiddler={{!!view}} $mode="block" />

One further change not reflected in the code above would be to move the $action-setfield widgets out of the $button content and into \procedures defined at the top of the tiddler, which can then be called with the actions attribute of the button widget. For instance:

REPLACE:

<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible">
	<$action-setfield 
		sortquery="[sort[author]]"
		tagquery=""
		sort="Author"/>
		Author
</$button>

WITH:

\procedure author()
<$action-setfield 
	sortquery="[sort[author]]"
	tagquery=""
	sort="Author"/>
\end

<$button class="tc-tiddlylink tc-tiddlylink-resolves tc-btn-invisible" actions=<<author>>>
		Author
</$button>

In theory, externally defined actions are slightly more efficient as they’ll only get evaluated when you click the button, rather than every time the button is rendered. But since you’re only using a single filtered transclusion, I doubt it will make much noticeable difference, so I’d choose whichever option you find easier to read.

EDIT: IMO, you don’t really need tc-tiddlylink-resolves in your button classes. I think you can remove it everywhere it appears above without changing the styling.

3 Likes

Really cool! Deep explanation and I appreciate the example using my same code. Works the same and is much more elegant.

I now see that the $tiddler widget and the $tiddler object that $action-setfield are referring to are the same item, which would otherwise default to <<currentTiddler>>

Awesome tysm :slight_smile:

I am not looking at the specific filter here, and @etardiff has looked deeply so go with that advice but;

I tend to break filters into logical pieces and define them in a \function. Once you do this your key filter makes use of these functions and become much more readable. Its like Chunking;

Chunking is a memory strategy and cognitive process that involves breaking down large amounts of information into smaller, more manageable groups or chunks. This helps improve short-term retention and makes it easier to remember and recall information by bypassing the limited capacity of working memory. Chunking can be applied in various contexts, including teaching, learning, and even organizing tasks

However once you do state “modularising” parts of a filter you do start to see new opportunities to restate the filer and further simplify it. You also find it easier to recap on what you did when you return later.

1 Like