Filter to Count Number of Specific Chars at the Beginning of a String

Consider below example

<$list filter="[[!This is level 1]] [[!! This is level 2]] [[!!! This is level 3]]"  variable=item>
<$list filter="[<item>splitregexp[\!]count[]subtract[1]]">
<<currentTiddler>> 
</$list>
</$list>

Returns:  1 2 3

It counts the number of ! at the start of string to calculate the heading level!

What is the pattern if the input has a ! in the meddle (should be ignored) e.g.

[[!! This is amazing! level 2]]

This still should return 2.

1 Like

Mohammad;

Given the nature of the ! symbol you could test for a prefix of "!!!"then "!! " then β€œ!” because for example ! does not have a prefix of β€œ!!”

{{{ [<item>prefix[!!!]then[3]] ~[<item>prefix[!!]then[2]] ~[<item>prefix[!]then[1]] }}}

I have not tested it but expect it to work. You could also split into single characters [split[]first[5]join[]] to get the first three/five characters perhaps with trim[] to remove spaces and instead run the test on that. No chance of picking up a later β€œ!”

I expect since a heading is a line of its own I may have first obtained the rows from the text field like so meaning they are a heading then calculated which heading level.
[all[current]get[text]splitregexp[\n]prefix[!]]

People with more knowledge of regex could just ask for items beginning ! and as many as arrive until not β€œ!” then [split[]count[]]

Yes, it works!
While we know headings are between 1-5, then this method can be used!

Thank you Tones!

For who like to give a try!

<$list filter="[[!This is level! 1]] [[!! This is level 2]] [[!!! This is level 3]]"  variable=item>
<$text text={{{ [<item>prefix[!!!]then[3]] ~[<item>prefix[!!]then[2]] ~[<item>prefix[!]then[1]] }}}/>
</$list>


;Solved issue
:can handle ! in the middler of string
1 Like

A regex solution (if I’m understanding your need properly) that would work for any number of ! markings would look something like:

{{{ [[!!! This is the best !!]search-replace::regexp[(^!*).*],[$1]length[]] }}}

I know you (@Mohammad) are familiar with regex already, but for others finding this later:

Regex explanation of (^!*).*

  • The ^ means that the next character must start the line (preventing other !'s from counting)
  • The ! is the character you’re looking for
  • The * after that says that you should find 0 or more of last character, grab as many as you can
  • The ( ) surrounding those puts it into a grouping that allows for extracting a part of the line
  • The .* essentially matches the rest of the line. This is needed so it can be discarded later

Then the second part:

  • The [$1] is the replace part, and because we used ( ) before, we can use $1 to return the result of what matched in that first set. In our case, it was just the leading !'s

Lastly, what makes it through will just be the !!! matching part, so length[] counts the characters.

1 Like

Thank you @stobot - works! I just trim the leading spaces!

{{{ [<item>trim:prefix[]search-replace::regexp[(^!*).*],[$1]length[]] }}}

item comes from another list!

Hmm. Spaces might be a way for someone to say β€œdon’t use this as a section.”

1 Like

I thought about it, but I recommend to use …
I will try to the make the parser simpler than this! for example I am thinking to only parse sections (e.g headings) and ignore the preface texts (the one with no heading at the tiddler begining)