summaryrefslogtreecommitdiff
path: root/vendor/github.com/tdewolff/parse/v2/position.go
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2022-08-07 18:19:16 +0200
committerLibravatar GitHub <noreply@github.com>2022-08-07 18:19:16 +0200
commit879b4abde722cb66463ca81a4cf6ac5465ef276d (patch)
treecdbd98840bca27317ad0860a194072671ed04ebe /vendor/github.com/tdewolff/parse/v2/position.go
parent[feature] Photoswipe gallery (#740) (diff)
downloadgotosocial-879b4abde722cb66463ca81a4cf6ac5465ef276d.tar.xz
[bugfix] Markdown formatting updates (#743)
* add minify dependency specifically for markdown * rearrange markdown formatting * update markdown tests
Diffstat (limited to 'vendor/github.com/tdewolff/parse/v2/position.go')
-rw-r--r--vendor/github.com/tdewolff/parse/v2/position.go95
1 files changed, 95 insertions, 0 deletions
diff --git a/vendor/github.com/tdewolff/parse/v2/position.go b/vendor/github.com/tdewolff/parse/v2/position.go
new file mode 100644
index 000000000..38e38cee4
--- /dev/null
+++ b/vendor/github.com/tdewolff/parse/v2/position.go
@@ -0,0 +1,95 @@
+package parse
+
+import (
+ "fmt"
+ "io"
+ "strings"
+ "unicode"
+)
+
+// Position returns the line and column number for a certain position in a file. It is useful for recovering the position in a file that caused an error.
+// It only treates \n, \r, and \r\n as newlines, which might be different from some languages also recognizing \f, \u2028, and \u2029 to be newlines.
+func Position(r io.Reader, offset int) (line, col int, context string) {
+ l := NewInput(r)
+ line = 1
+ for l.Pos() < offset {
+ c := l.Peek(0)
+ n := 1
+ newline := false
+ if c == '\n' {
+ newline = true
+ } else if c == '\r' {
+ if l.Peek(1) == '\n' {
+ newline = true
+ n = 2
+ } else {
+ newline = true
+ }
+ } else if c >= 0xC0 {
+ var r rune
+ if r, n = l.PeekRune(0); r == '\u2028' || r == '\u2029' {
+ newline = true
+ }
+ } else if c == 0 && l.Err() != nil {
+ break
+ }
+
+ if 1 < n && offset < l.Pos()+n {
+ break
+ }
+ l.Move(n)
+
+ if newline {
+ line++
+ offset -= l.Pos()
+ l.Skip()
+ }
+ }
+
+ col = len([]rune(string(l.Lexeme()))) + 1
+ context = positionContext(l, line, col)
+ return
+}
+
+func positionContext(l *Input, line, col int) (context string) {
+ for {
+ c := l.Peek(0)
+ if c == 0 && l.Err() != nil || c == '\n' || c == '\r' {
+ break
+ }
+ l.Move(1)
+ }
+ rs := []rune(string(l.Lexeme()))
+
+ // cut off front or rear of context to stay between 60 characters
+ limit := 60
+ offset := 20
+ ellipsisFront := ""
+ ellipsisRear := ""
+ if limit < len(rs) {
+ if col <= limit-offset {
+ ellipsisRear = "..."
+ rs = rs[:limit-3]
+ } else if col >= len(rs)-offset-3 {
+ ellipsisFront = "..."
+ col -= len(rs) - offset - offset - 7
+ rs = rs[len(rs)-offset-offset-4:]
+ } else {
+ ellipsisFront = "..."
+ ellipsisRear = "..."
+ rs = rs[col-offset-1 : col+offset]
+ col = offset + 4
+ }
+ }
+
+ // replace unprintable characters by a space
+ for i, r := range rs {
+ if !unicode.IsGraphic(r) {
+ rs[i] = 'ยท'
+ }
+ }
+
+ context += fmt.Sprintf("%5d: %s%s%s\n", line, ellipsisFront, string(rs), ellipsisRear)
+ context += fmt.Sprintf("%s^", strings.Repeat(" ", 6+col))
+ return
+}