2021-12-23 05:48:19 +00:00
|
|
|
package emdbed
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"regexp"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
var endline = regexp.MustCompile(`(?m)$`)
|
|
|
|
|
|
|
|
type emdbed struct {
|
|
|
|
name string
|
|
|
|
contents string
|
|
|
|
language string
|
|
|
|
start string
|
|
|
|
end string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e emdbed) line(line int, end bool) (int, error) {
|
|
|
|
if line == 1 && !end {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
indexes := endline.FindAllStringIndex(e.contents, -1)
|
|
|
|
if len(indexes) < line {
|
|
|
|
return 0, fmt.Errorf("file %q has no line %d", e.name, line)
|
|
|
|
}
|
2021-12-26 04:53:20 +00:00
|
|
|
dec := 1
|
|
|
|
if !end {
|
|
|
|
dec++
|
|
|
|
}
|
|
|
|
var inc int
|
|
|
|
if !end {
|
|
|
|
inc++
|
|
|
|
}
|
|
|
|
return indexes[line-dec][0] + inc, nil
|
2021-12-23 05:48:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e emdbed) regex(pattern string, end bool) (int, error) {
|
|
|
|
re, err := regexp.Compile(pattern)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
match := re.FindStringIndex(e.contents)
|
|
|
|
if match == nil {
|
|
|
|
return 0, fmt.Errorf("file %q has no match for pattern %q", e.name, pattern)
|
|
|
|
}
|
|
|
|
var inc int
|
|
|
|
if end {
|
|
|
|
inc++
|
|
|
|
}
|
|
|
|
return match[0] + inc, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e emdbed) selector(selector string, end bool) (int, error) {
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(selector, "L"):
|
|
|
|
line, err := strconv.Atoi(selector[1:])
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return e.line(line, end)
|
|
|
|
case strings.HasPrefix(selector, "/"):
|
|
|
|
pattern := strings.Trim(selector, "/")
|
|
|
|
return e.regex(pattern, end)
|
|
|
|
default:
|
|
|
|
return 0, fmt.Errorf("unknown selector %q", selector)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e emdbed) Start() (int, error) {
|
|
|
|
if e.start == "" {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
return e.selector(e.start, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e emdbed) End() (int, error) {
|
|
|
|
if e.end == "" {
|
|
|
|
return len(e.contents), nil
|
|
|
|
}
|
|
|
|
return e.selector(e.end, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e emdbed) Selection() (string, error) {
|
|
|
|
start, err := e.Start()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
end, err := e.End()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return e.contents[start:end], nil
|
|
|
|
}
|