sobjornstad / TiddlyRemember

Embed Anki notes in your TiddlyWiki
https://sobjornstad.github.io/TiddlyRemember/
MIT License
65 stars 7 forks source link

Add this technique for multi-line code blocks to documentation #85

Open uzvg opened 1 month ago

uzvg commented 1 month ago

Assuming I want to create a note as follows:

<<rememberq "20240818113240343"
    "A specific example of function pragma in tiddlywiki"
    """
        \function my-function(parameter:"2")
        [<parameter>multiply[1.5]]
        \end
    """>>

Then the card will displayed like follow:

image

The <<parameter>> seems like to be expanded in the note. how can I avoid this?

The workaround I came up with is as follows:

<<rememberq "20240818113240343"
    "A specific example of function pragma in tiddlywiki"
    """
        `\function my-function(parameter:"2")` <br>
        `[<parameter>multiply[1.5]]` <br>
        `\end` <br>
    """>>

It will behave like this:

image

Do we have any other convenient solutions?

sobjornstad commented 1 month ago

To understand what's going on here, look at the definition of the rememberq macro:

\define rememberq(id, question, answer, reference: "", sched: "", class:"")
    <div class={{{ [[rememberq remembertwo ]addsuffix<__class__>addsuffix[ ]addsuffix{$:/config/TiddlyRemember/DefaultClasses}] }}}>
        <div class="rquestion tr-ritem">
            <div>Q:</div>
            <p>$question$</p>
        </div>
        <div class="ranswer tr-ritem">
            <div>A:</div>
            <p>$answer$</p>
        </div>
        <$macrocall $name=remembertwo id=<<__id__>> reference=<<__reference__>> sched=<<__sched__>>/>
    </div>
\end

Since the text of the question and answer parameters is being substituted into the macro, it's interpreted as wikitext when rendering the card. So what you're actually typing there is an HTML tag called <parameter>. Since the browser doesn't know what to do with a <parameter> element (since you made it up, and anyway the opening tag is unmatched), it disappears.

The direct way to tell your browser you don't mean <parameter> to be an HTML tag is to XML-escape the angle brackets, which we do using the character entities &lt; and &gt; rather than < and >:

image

However, if you have multiple lines of code, you probably really want it in a code block. You can achieve that with the $codeblock widget, like this:

<<rememberq "20240818113240343"
    "A specific example of function pragma in tiddlywiki"
    '<$codeblock code="""\function my-function(parameter:"2")
    [<parameter>multiply[1.5]]
\end"""/>
        '>>

image

(The $codeblock widget also has a language parameter which you can use to get syntax highlighting if you like, if you have the appropriate plugin installed.)

Notice that here, the $codeblock widget takes care of interpreting the quoted text in its code parameter correctly; it knows that its contents should be interpreted as a string of code rather than HTML instructions, and thus generates its own HTML containing the formatted code. When that HTML hits your browser, the angle brackets will already be escaped.

That said, dealing with all the nested quotes in that snippet is liable to be a massive pain if you're making more than a couple of these! We can fix this with a helper procedure that allows you to specify the answer field as a raw code snippet with no quotes, and automatically trims leading or trailing whitespace and wraps it in the $codeblock widget.

\procedure remembercodesnippet(id, prompt, code, reference:"", sched:"", class:"")
  <$let
    trimmedCode={{{ [<code>trim[]] }}}
    blockedCode=`<$codeblock code="""$(trimmedCode)$"""/>`
    >
      <$macrocall
        $name="rememberq"
        id=<<id>>
        question=<<prompt>>
        answer=<<blockedCode>>
        reference=<<reference>>
        sched=<<sched>>
        class=<<class>>
      />
  </$let>
\end

<<remembercodesnippet "20240818113240343"
    "A specific example of function pragma in tiddlywiki"
    """
\function my-function(parameter:"2")
    [<parameter>multiply[1.5]]
\end
    """
>>

(You can put that procedure in a tiddler tagged $:/tags/Global to make it available in all tiddlers.)

uzvg commented 4 weeks ago

Very clear and specific, thank you 👍🏻