Updated 2017-06-22 07:51:51 by RJM

RJM Here, a simple proc is proposed that allows simple wiki-like formatting for text widgets. Intended use case: help/manual text in Tcl sources. The insert subcommand's ability to have multiple text|tag-pairs is not bad, but common wiki markup would be better. In typical manual or help pages, basic markup as headings, underline, bold and italic would be very helpful.

A difficulty is the fact that you cannot have tags for bold and italic. Here one is forced to create a tag for both options together in the tag configure subcommand. In my proposal, I used some Creole markup features, because of its intuitively logical appearance. BTW: the same markup is also used in Dokuwiki, which - to my opinion - resembles the best of Creole and Markdown (and perhaps some other ideas, too).


witext .t "This is //italic __underline italic__ **bold italic**//\n"
witext .t "This is **bold __underline bold__ //italic bold//**, yeah\n"
witext .t "== Heading ==\nNormal text //italic// Text, __underline__ and **bold** text.\n"
witext .t "Normal text //italic// Text, __underline__ and **bold** text.\n" warning

The latter code line shows the support of the insert subcommand optional tag argument for the whole string. In this example warning was defined as simple brown foreground.


(RJM Update: there was a regexp problem when two identical markups in words were found in a string - see comment in code. Moreover, now the tags definition occurs on the first call of witext).
proc witext_tags t {
    $t tag config ** -font {Courier 9 bold}
    $t tag config // -font {Courier 9 italic}
    $t tag config //** -font {Courier 9 italic bold}
    $t tag config __ -underline 1
    $t tag config == -font {Verdana 10 bold}
# note:
#    set pattern {(==|__|//|\*\*)(.+?)(\1)}
#    if {[regsub -all $pattern $str {\x1d\2\x1e\1\x1d} str] || !$recurlevel} {
# ... effectively results in greedy match only due to the alternation in the pattern
proc witext {t str args} {
    upvar #0 $t.recurlevel recurlevel
    if {![info exists recurlevel]} {
        set recurlevel 0
        witext_tags $t
        update idletasks
    set pattern {([=/_*])\1(.+?)\1\1}
    if {[regsub -all $pattern $str {\x1d\2\x1e\1\1\x1d} str] || !$recurlevel} {
        foreach str [split [subst $str] \x1d] {
            lassign [split $str \x1e] s tag
            incr recurlevel
            if {![witext $t $s [join "$tag $args" ""]]} {
                if {[regexp {//\*\*|\*\*//} $tag$args]} {
                    set $args ""
                    set tag //**  ;# treat italic and bold as one compound tag (necessary)
                $t insert end $s [list $tag $args]
            incr recurlevel -1
        return 1
    return 0

I'm not sure whether the algorithmical approach makese sense or not. It seems to be difficult to convert wiki markup to a string that can be used as a compound single string to a text insert subcommand argument. Instead I subdivided the input string in sections using an ascii control code. Hence, a foreach handles each section: those without markup and those with markup.

Another ascii control code is used as a split marker in the inner loop. Another approach should be possible, here. The recursive approach allows nesting of markup. The recurlevel serves as a flag to ensure that text without any markup is passed as well.

For my purpose (help text in tcl-code) this helper proc is fully sufficient. Bullet and numeric listing would be nice as a next step.

MG See also Google Code Wiki parser/help widget