Function as search-replace regexp parameter

Imagine the search-replace filter operator could operate like the javascript function of the same name. That is, it would now be able to call code for produciong the replacement!

I have an example ready (which I currently solved with a custon javascript filter operator).

be that filter:

[[one two*2 three four*4]search-replace:g:regexp[/\b(\w+)\*(\d+)\b/],[.expand]]

it would produce “one two two three four four four four”! with the following function:

\function .expand(matched, word, count) [<word>repeat<count>]

This is totally the same logic than in javascript.

Oh, I nearly forgot: “repeat” is not yet available as a standard filter op, but IMHO it really should be. As you have guessed, it is just duplicating the input by the indicated number. Not duplicating as new inputs, but by modifying each input titles…

Thus [[a]repeat[3]] is equal to [[aaa]] not to [[a] [a] [a]].

Here it is.

title: $:/user/common/filters/repeat.js
type: application/javascript
module-type: filteroperator

repeat the operand as many times as the value of the operand.

If the operand is negative, equivalent to zero or empty, returns an empty string.
(function() {

  /*jslint node: true, browser: true */
  /*global $tw: true */
  "use strict";

  exports.repeat = function(source, operator, options) {
    let factor = (operator.operand === "") ? 0 : parseInt(operator.operand, 10);
    if (isNaN(factor) || factor < 0) { factor = 0; }
    let tids = [];
    source(function(tiddler, title) {
      if (title) {
    return tids;

I am curious why you would want to repeat input, whilst also avoiding Dominant Append?

  • Although if other languages allow it, there is possibly an algorithum that can use it.

I think I could invent a work around, but it would possibly be verbose and make use of some more obscure methods.

  • It also depends on what you wish to do with the result.
    • Use it as a list imput
    • Simply display the result
    • To generate a variable(s)
    • Drive your code pattern

Is your javascript/filter operator workin? bespoke filter operators are fine.

  • Although it may still be possible to create a “custom operator” using functions.


  • Unfortunately I dont know how to read your regexp and my Javascript is weak.

Could you write a simple documentation of your filter operator?

Something like this, I think (if I’m following this thread correctly)

\function .repeat(inp, n) [range[1],<n>] :map[<inp>]

1 <$list filter="[function[.repeat],[a],[5]]"/>

2 <$list filter="[.repeat[b],[5]]"/>

<$set name=rpt filter="[.repeat[c],[5]]">

Not sure why the join[] is needed to rid the output of spaces in the $set example… :confused:

Because the output of a filter is usually a list of 0, 1 or more titles. There will be at least space separated, and in some cases [[tiddler with spaces]] wrapped as such.

There may be a way to use the pad operator as well.

The .repeat function is producing a list of multiple items, all the same (note: :map[...] does not “de-duplicate” the results)

Then, (1) and (2) output the list items without any intervening spaces. Note that the output is actually 5 separate linked items. In contrast, (3) uses $set to assign a value to rpt, which is a single variable that contains a list of 5 items. By definition, the output of a $set widget with a filter=... parameter is a space-separated list. Thus, the join[] is needed to merge all the items into a single string value.

Note that you could add the join[] operator directly into the \function definition, like this:

\function .repeat(inp, n) [range[1],<n>] :map[<inp>] +[join[]]

Then, the output for (1) and (2) would each be a single linked item of 5 repeated characters.

@EricShulman Yes your function is doing exactly what my javascript filter op do, but as a function.

@TW_Tones And my filter op is useful beyond dominant appending. Because my input is just a single title, which I want to transform into a single title but with a repetition of its previous self inside. And it leads to simple code where it is to be used. But what are you thinking when you write “Drive your code pattern”?

Other than querying about the example function code, none of you has reacted about my idea of using a function to extend the search-replace possibilities. Do you think it’s not a worthy idea? Why if so?

As opposed to displaying a result on screen, using the output to influence the process represented in your code.

  • For example generating a list (with a function), that is passed to a procedure, that calls another procedure for each list item.
  • I suppose I can’t imagine a need for the outcome you gave
  • If it can be done with existing filters there are less dependencies
  • If it was to be added;
    • What is a compelling reason?, I expect you have one, but I don’t know it
    • Are there other issues that can be addressed at the same time?

Don’t get me wrong, I am all for your exploration.

Hi @jypre I think there is a lot of scope for filter operators that take functions as parameters. The example I’ve been thinking of is a tree walker operator that takes two functions: one to return the child nodes of a parent node, and one to process a node. Applied to parse trees, it would make it possible to perform operations like extracting all the transclusions from a tiddler.

My function.  

I’m so sorry @CodaCoder for having been wrong.

My example : when you want to transform “a*3” into “aaa” with a regexp then you need a function callback. In javascript, you can see the need arose not so infrequently. Sometimes for convenience. Sometimes because that’s the only way.

I understand its all about juggling, availability, convenience, frequent or infrequent use etc… to decide javascript vs native tiddlywiki script.

  • I add to this a desire when working “down in the weeds/details” to identify when there is a “tiddlywiki script gap” or not and see, if we can fill it, with work arounds at least and ideally extend or supplement the core.
  • The more we fill the gaps in tiddlywiki the more comprehensive it is and the easier to use.
1 Like