mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-12-05 02:54:46 +01:00
88 lines
1.6 KiB
Go
88 lines
1.6 KiB
Go
|
package syntax
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"errors"
|
||
|
)
|
||
|
|
||
|
type ReplacerData struct {
|
||
|
Rep string
|
||
|
Strings []string
|
||
|
Rules []int
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
replaceSpecials = 4
|
||
|
replaceLeftPortion = -1
|
||
|
replaceRightPortion = -2
|
||
|
replaceLastGroup = -3
|
||
|
replaceWholeString = -4
|
||
|
)
|
||
|
|
||
|
//ErrReplacementError is a general error during parsing the replacement text
|
||
|
var ErrReplacementError = errors.New("Replacement pattern error.")
|
||
|
|
||
|
// NewReplacerData will populate a reusable replacer data struct based on the given replacement string
|
||
|
// and the capture group data from a regexp
|
||
|
func NewReplacerData(rep string, caps map[int]int, capsize int, capnames map[string]int, op RegexOptions) (*ReplacerData, error) {
|
||
|
p := parser{
|
||
|
options: op,
|
||
|
caps: caps,
|
||
|
capsize: capsize,
|
||
|
capnames: capnames,
|
||
|
}
|
||
|
p.setPattern(rep)
|
||
|
concat, err := p.scanReplacement()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if concat.t != ntConcatenate {
|
||
|
panic(ErrReplacementError)
|
||
|
}
|
||
|
|
||
|
sb := &bytes.Buffer{}
|
||
|
var (
|
||
|
strings []string
|
||
|
rules []int
|
||
|
)
|
||
|
|
||
|
for _, child := range concat.children {
|
||
|
switch child.t {
|
||
|
case ntMulti:
|
||
|
child.writeStrToBuf(sb)
|
||
|
|
||
|
case ntOne:
|
||
|
sb.WriteRune(child.ch)
|
||
|
|
||
|
case ntRef:
|
||
|
if sb.Len() > 0 {
|
||
|
rules = append(rules, len(strings))
|
||
|
strings = append(strings, sb.String())
|
||
|
sb.Reset()
|
||
|
}
|
||
|
slot := child.m
|
||
|
|
||
|
if len(caps) > 0 && slot >= 0 {
|
||
|
slot = caps[slot]
|
||
|
}
|
||
|
|
||
|
rules = append(rules, -replaceSpecials-1-slot)
|
||
|
|
||
|
default:
|
||
|
panic(ErrReplacementError)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if sb.Len() > 0 {
|
||
|
rules = append(rules, len(strings))
|
||
|
strings = append(strings, sb.String())
|
||
|
}
|
||
|
|
||
|
return &ReplacerData{
|
||
|
Rep: rep,
|
||
|
Strings: strings,
|
||
|
Rules: rules,
|
||
|
}, nil
|
||
|
}
|