93 lines
2.4 KiB
Go
93 lines
2.4 KiB
Go
package reconcile
|
|
|
|
import (
|
|
"strings"
|
|
)
|
|
|
|
// Verwaltete Blöcke in Textdateien wie CLAUDE.md (→ KONZEPT.md 7.2, 11.4):
|
|
//
|
|
// <!-- hugin:begin — von hugin sync verwaltet, nicht von Hand ändern -->
|
|
// @.hugin/rules/pub-hausregeln.md
|
|
// <!-- hugin:end -->
|
|
|
|
func beginMarker(block string) string {
|
|
return "<!-- " + block + ":begin — von hugin sync verwaltet, nicht von Hand ändern -->"
|
|
}
|
|
|
|
func endMarker(block string) string { return "<!-- " + block + ":end -->" }
|
|
|
|
// findBlock liefert die Zeilennummern von Anfangs- und Endmarke, -1 wenn es
|
|
// den Block nicht gibt.
|
|
func findBlock(lines []string, block string) (begin, end int) {
|
|
begin, end = -1, -1
|
|
for i, z := range lines {
|
|
z = strings.TrimSpace(z)
|
|
if begin < 0 && strings.HasPrefix(z, "<!-- "+block+":begin") {
|
|
begin = i
|
|
} else if begin >= 0 && z == endMarker(block) {
|
|
return begin, i
|
|
}
|
|
}
|
|
return -1, -1
|
|
}
|
|
|
|
// readBlock liefert den Inhalt des Blocks mit \n als Zeilenende.
|
|
func readBlock(text, block string) (string, bool) {
|
|
lines, _ := split(text)
|
|
begin, end := findBlock(lines, block)
|
|
if begin < 0 {
|
|
return "", false
|
|
}
|
|
var b strings.Builder
|
|
for _, z := range lines[begin+1 : end] {
|
|
b.WriteString(z + "\n")
|
|
}
|
|
return b.String(), true
|
|
}
|
|
|
|
// setBlock ersetzt den Block, hängt ihn ans Ende an oder entfernt ihn
|
|
// (leerer inhalt). Das Zeilenende der Datei (LF oder CRLF) bleibt erhalten.
|
|
func setBlock(text, block, content string) string {
|
|
lines, nl := split(text)
|
|
begin, end := findBlock(lines, block)
|
|
|
|
var next []string
|
|
if content != "" {
|
|
next = append(next, beginMarker(block))
|
|
next = append(next, strings.Split(strings.TrimSuffix(content, "\n"), "\n")...)
|
|
next = append(next, endMarker(block))
|
|
}
|
|
|
|
switch {
|
|
case begin >= 0:
|
|
rest := lines[end+1:]
|
|
if len(next) == 0 && len(rest) > 0 && strings.TrimSpace(rest[0]) == "" {
|
|
rest = rest[1:]
|
|
}
|
|
lines = append(append(append([]string{}, lines[:begin]...), next...), rest...)
|
|
case len(next) > 0:
|
|
if len(lines) > 0 && strings.TrimSpace(lines[len(lines)-1]) != "" {
|
|
lines = append(lines, "")
|
|
}
|
|
lines = append(lines, next...)
|
|
}
|
|
for len(lines) > 0 && strings.TrimSpace(lines[len(lines)-1]) == "" {
|
|
lines = lines[:len(lines)-1]
|
|
}
|
|
if len(lines) == 0 {
|
|
return ""
|
|
}
|
|
return strings.Join(lines, nl) + nl
|
|
}
|
|
|
|
func split(text string) (lines []string, nl string) {
|
|
nl = "\n"
|
|
if strings.Contains(text, "\r\n") {
|
|
nl = "\r\n"
|
|
}
|
|
text = strings.TrimSuffix(text, nl)
|
|
if text == "" {
|
|
return nil, nl
|
|
}
|
|
return strings.Split(text, nl), nl
|
|
}
|