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

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.