Help understanding macro calls with transcluded parameters

I am having trouble understanding how macrocalls work in buttons that set fields to values resulting from a macro being called with transcluded text as a parameter.

Can anyone explain how to get the desired behaviour for the button?

Here is the example javascript macro:

/*\
title: mymacros/makelower.js
type: application/javascript
module-type: macro
\*/

/*
Macro to make a string lowercase
*/

"use strict";
exports.name = "makelower";
exports.params = [{name: "input"}];



exports.run = function(input) {

    const characters = input.toLowerCase()
    return characters;
};

In a is a tiddler called demolower:

<$edit-text tiddler=demolower field=input/>

Typing in Hello World into the above input field results in the following outputs for the following code:

<$transclude $variable="makelower" input={{!!input}}/>

:white_check_mark:gives: hello world

<<makelower input:{{demolower!!input}} >>

:x:gives: Hello World

<$button>
<$action-setfield $tiddler=demolower lowered=<<makelower input:"Hello World">> />
Set field "lowered" to lowercase version predefined text
</$button>

:white_check_mark: lowered field: hello world

<$button>
<$action-setfield $tiddler=demolower lowered=<<makelower {{!!input}}>> />
Set field "lowered" to lowercase version of entered input
</$button>

:x: lowered field: Hello World

Hi @twlinguist

The rule is quite simple: when you use the shortcut macro call notation with chevrons, ie <<makelower ...>>, you can only use constant parameter values.
If your parameter values need to be variables, fields, functions or filters, you must use <$macrocall> or, preferably, <$transclude> widgets.

Hope this helps,

Fred

Thanks for your reply, Fred. Is there a way to get the button working using <$transclude> then?

I have tried this which doesn’t work:

<$button>
<$action-setfield $tiddler=demolower lowered=<$transclude $variable=makelower input={{!!input}}/> />
Set field "lowered" to lowercase version of entered input
</$button>

Sorry, my answer below doesn’t work. I’m elaborating another answer.

I would advise to put triple double-quotes around the widget, like this (untested):

<$button>
<$action-setfield $tiddler=demolower lowered="""<$transclude $variable=makelower input={{!!input}}/>""" />
Set field "lowered" to lowercase version of entered input
</$button>

Please tell me how it goes

Fred

Hi Fred,

This is very interesting, your code seems to work, but doesn’t have the truly desired outcome. It sets the value of the “lowered” field to <$transclude $variable=makelower input={{!!input}}/> so it doesn’t have the desired outcome of setting the lowered field permanently
to the simple text string of “hello world”.

If you display {{demolower!!lowered}} what is displayed will change according to what is entered into the input box.

But I have now figured out the solution!

It is to use <$wikify>

As follows:

<$wikify name=processed text='<$transclude $variable="makelower" input={{demolower!!input}}/>' output="text">
<$button>
<$action-setfield lowered=<<processed>> />
Set field "lowered" to lowercase version of entered input
</$button>
</$wikify>

You are right, wikify is the solution in this case.

I suppose your makelower code is just an example (there’s already a core lowercase filter operator which does exactly this), but I think makelower should be a function, not a macro: it takes an input, transforms it and returns a result, which is better served by a function than a macro. Macros are supposed to substitute text with few transformations, not return a result. Functions are evaluated like filter operators, which adds more flexibility.

If makelower was a function, you could write this:

<$button>
<$action-setfield $tiddler=demolower lowered={{{ [function[makelower],{!!input}] }}} />
Set field "lowered" to lowercase version of entered input
</$button>

Links:

Fred

Thank you, Fred. Yes it was just an example, and what I have in mind is to create a more complex text processing operation, with lowercase just being the first step. AI created some elegant and short javascript code for me that does exactly what I want in terms of input and output.

I had already figured out a way to do this complex processing with filter operators, but it involves a huge number of search-replace:gi[x],[y] and other operations which feels clunky. I also like the idea of being able to call a macro in any tiddler, whereas I believe the function needs to be defined inside every tiddler where it is called?

But thank you for the insight, the truth is I have avoided learning how to use functions, and there are probably many places where using them would be the best option!

Maybe your existing javascript code can be turned into a javascript filter operator definition?

Wikitext function definitions, defined with the \function pragma, can be placed in a tiddler tagged $:/tags/Global in order to make them available in any tiddler.
Javascript filter operators are also available in any filter in any tiddler.

I tend to use filters and functions very frequently, so I may be biased, but I can’t recommend using them highly enough!

Fred

2 Likes

This use of AI (LLM) is possibly why you are coming at this from the wrong direction, writing javascript macros to solve problems or develop solutions in TiddlyWiki is not the preferred approach, in TiddlyWiki, it should start with wikitext, filters, widgets and functions, what I call “TiddlyWiki Script”. These are the tools TiddlyWiki provides to manipulate TiddlyWiki. 96% of requirements can be satisfied this way, and most of the rest by using plugins already developed.

In a very small number of cases, writing a javascript solution may be needed, but these should also flag a need to update the core of TiddlyWiki to reduce the need in future. If we needed to do this we would more likely modify existing code to enhance feature or build on top of existing JavaScript definitions of filter operator, widgets etc…

  • People may give you answers that help but I think you are coming at this from the wrong direction

I would suggest describing the outcomes you are looking for free of code or AI examples and let the community help get you there.

1 Like

Thank you @TW_Tones and @tw-FRed for your nudging me away from using macros as a first approach. I understand from what you have written that it is for the best, and follows the TiddlyWiki philosophy.

Here is my attempt at just describing my problem and desired outcome:

This was all started with a frustration that there wasn’t already a built-in feature in the search operator.

I wish there were an accentinsensitive flag. Or I wish that, by default, searches were not sensitive to accent/diacritics.

In most blingual dictionary software, when you look up a word and are not sure of the accents in the spelling, or are too lazy to type them, it doesn’t matter. Typing “ele” into the input field will match both “element” and “élément”

My wikis are multilingual and I want to, for example, do a search such as [search:notefield:accentinsensitive[element]] and it would match tiddlers that contain any of these spellings in the notefield: element, Element,élement,Élement ,élément, Élément (the middle two are actually incorrect French spellings)

Currently, when using the search operator, “ele” will only match the first two, and “élé” will only match the last two.

My solution is that any time a notefield is created or updated in a tiddler, another unaccentednotefield is created (now with a javascript macro, but in my previous solution with transcluded filter operations) and when I search the wiki, I have things set up to search both of these fields when looking for a word [search:notefield,unaccentednotefield:[element]]

But maybe there is a simpler, built-in way of doing “accent-insensitive” searches of fields, without having to pre-generate “unaccented” duplicates of these fields, and include them in the search operation? If so, I am all ears!

1 Like

Being French myself, I had to use a similar technique in a wiki I designed which heavily relies on search. By the way, it’s also useful for sorting.

FWIW, I think it’s a typical problem for which the solution would be better suited inside the core search/sort functions. But the subject is complex (different alphabets, syllabic languages, ideograms, …) and a core solution would probably need to be generic enough to cover most languages peculiarities, probably with a plugin for each language category.

Does any javascript fluent community member know existing solutions for this?

Fred

Yes I use it for sorting as well! And yes I agree, it would be wonderful to have accent-insensitive searching and sorting, or a way to toggle it on or off, included in Tiddly Wiki’s core features.

@twlinguist

I understand your requirement here and think it is a reasonable to suggest its something the core should handle. How we achieve this needs to be determined, perhaps rather than a filter operator suffix we could have a global search setting in a config tiddler? Perhaps it could even turn on with the installation of any language that uses any “accent/diacritics”. There may need to be cases where only the literal is found for example if one was looking for words that did not use the accents.

Perhaps we should start a new topic with this specific need? As a discussion first, and if no solutions appear raise one for the developers topic.

If you are in desperate need of a workaround perhaps we can hack $:/core/modules/filters/search.js with an LLM to include diacritical’s. It will also demonstrate how we may change it in the core.

  • I can guide you on this or have ago myself but I don’t have the test data, perhaps you could provide it?

Ok @TW_Tones , i have created a new discussion.

1 Like

I and I have tried to kick it off, if none of the core team chime in, ask and I will create the hack with the LLM.

For a work around you can possible go a long way using regular expressions such as;

Note: I have not tested this.

Thank you for looking into this @TW_Tones

I already am happy enough with my current inelegant workaround of generating duplicate “unnaccented” fields of any data I want to be able to search or sort. It works for me in a reliable way, and as I don’t deal with many accented languages (only French amd German) this explicit definition of character replacements is fine for my use case. So I am not in urgent need of a solution.

But thank you for following up on this, as I do think it would be a great feature to have for the whole TiddlyWiki community, to have “diacritic insensitive” searching and sorting for all latin-script languages that use diacritics.

I have no technical skills to contribute to development here, so I can only express my encouragement and gratitude as an end-user, and also reassure you that I personally am not in urgent need of a solution (as I already have a usable workaround).