โ– humdrum codex / glint v1.1.2
license AGPL-3.0
2.2 KB raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package editor

import (
	"regexp"

	"github.com/charmbracelet/lipgloss"
)

// tkRe matches the journalism "TK" placeholder ("to come"): a whole word made of
// one or more "tk" pairs, any case โ€” "TK", "tk", "TKTK". The \b anchors keep it
// from firing inside real words (catkin, Atkins, outkast), where no word boundary
// precedes the "tk".
var tkRe = regexp.MustCompile(`(?i)\b(?:tk)+\b`)

// tkPass paints TK placeholder markers as a bold filled badge so they pop as
// fill-in reminders. It runs after the spell and grammar passes (and wins over
// them on the same runes), splitting each prose span so only the "TK" text is
// restyled; the concatenation of span texts still equals the raw line, preserving
// the markup-visible invariant. Non-prose spans (code, URLs, markup) are untouched.
func (e *Editor) tkPass(all [][]Span) [][]Span {
	for li, spans := range all {
		var out []Span
		changed := false
		for _, sp := range spans {
			if !sp.Prose {
				out = append(out, sp)
				continue
			}
			split := e.splitTK(sp)
			if len(split) != 1 {
				changed = true
			}
			out = append(out, split...)
		}
		if changed {
			all[li] = out
		}
	}
	return all
}

// splitTK partitions one prose span's text, re-emitting each TK marker as a badge
// span (page-colored bold text on the loud theme.TK background). URLs are skipped.
// When no marker is present the original span is returned unchanged.
func (e *Editor) splitTK(sp Span) []Span {
	text := sp.Text
	locs := tkRe.FindAllStringIndex(text, -1)
	if len(locs) == 0 {
		return []Span{sp}
	}
	skips := urlRe.FindAllStringIndex(text, -1)
	badge := lipgloss.NewStyle().Foreground(e.theme.Background).Background(e.theme.TK).Bold(true)
	var out []Span
	last := 0
	emit := func(s string) {
		if s == "" {
			return
		}
		ns := sp
		ns.Text = s
		out = append(out, ns)
	}
	for _, m := range locs {
		if overlapsAny(m, skips) {
			continue
		}
		emit(text[last:m[0]])
		badgeSpan := sp
		badgeSpan.Text = text[m[0]:m[1]]
		badgeSpan.Style = badge
		badgeSpan.Wavy = false  // a badge never also carries a spell/grammar underline
		badgeSpan.Prose = false // and is inert to any later prose pass
		out = append(out, badgeSpan)
		last = m[1]
	}
	if last == 0 {
		return []Span{sp} // every match was inside a URL
	}
	emit(text[last:])
	return out
}