aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/danwakefield/fnmatch/fnmatch.go
diff options
context:
space:
mode:
authormrsdizzie <info@mrsdizzie.com>2020-06-30 17:34:03 -0400
committerGitHub <noreply@github.com>2020-07-01 00:34:03 +0300
commitaf7ffaa2798148e2a1b249da2330200bc032d7b1 (patch)
tree4f1f41767fa620dff4142ac7ebcd74b0abd61033 /vendor/github.com/danwakefield/fnmatch/fnmatch.go
parentce5f2b9845659efaca0b81998dca6cf03882b134 (diff)
downloadgitea-af7ffaa2798148e2a1b249da2330200bc032d7b1.tar.gz
gitea-af7ffaa2798148e2a1b249da2330200bc032d7b1.zip
Server-side syntax highlighting for all code (#12047)
* Server-side syntax hilighting for all code This PR does a few things: * Remove all traces of highlight.js * Use chroma library to provide fast syntax hilighting directly on the server * Provide syntax hilighting for diffs * Re-style both unified and split diffs views * Add custom syntax hilighting styling for both regular and arc-green Fixes #7729 Fixes #10157 Fixes #11825 Fixes #7728 Fixes #3872 Fixes #3682 And perhaps gets closer to #9553 * fix line marker * fix repo search * Fix single line select * properly load settings * npm uninstall highlight.js * review suggestion * code review * forgot to call function * fix test * Apply suggestions from code review suggestions from @silverwind thanks Co-authored-by: silverwind <me@silverwind.io> * code review * copy/paste error * Use const for highlight size limit * Update web_src/less/_repository.less Co-authored-by: Lauris BH <lauris@nix.lv> * update size limit to 1MB and other styling tweaks * fix highlighting for certain diff sections * fix test * add worker back as suggested Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Lauris BH <lauris@nix.lv>
Diffstat (limited to 'vendor/github.com/danwakefield/fnmatch/fnmatch.go')
-rw-r--r--vendor/github.com/danwakefield/fnmatch/fnmatch.go219
1 files changed, 219 insertions, 0 deletions
diff --git a/vendor/github.com/danwakefield/fnmatch/fnmatch.go b/vendor/github.com/danwakefield/fnmatch/fnmatch.go
new file mode 100644
index 0000000000..07ac7b37ca
--- /dev/null
+++ b/vendor/github.com/danwakefield/fnmatch/fnmatch.go
@@ -0,0 +1,219 @@
+// Provide string-matching based on fnmatch.3
+package fnmatch
+
+// There are a few issues that I believe to be bugs, but this implementation is
+// based as closely as possible on BSD fnmatch. These bugs are present in the
+// source of BSD fnmatch, and so are replicated here. The issues are as follows:
+//
+// * FNM_PERIOD is no longer observed after the first * in a pattern
+// This only applies to matches done with FNM_PATHNAME as well
+// * FNM_PERIOD doesn't apply to ranges. According to the documentation,
+// a period must be matched explicitly, but a range will match it too
+
+import (
+ "unicode"
+ "unicode/utf8"
+)
+
+const (
+ FNM_NOESCAPE = (1 << iota)
+ FNM_PATHNAME
+ FNM_PERIOD
+
+ FNM_LEADING_DIR
+ FNM_CASEFOLD
+
+ FNM_IGNORECASE = FNM_CASEFOLD
+ FNM_FILE_NAME = FNM_PATHNAME
+)
+
+func unpackRune(str *string) rune {
+ rune, size := utf8.DecodeRuneInString(*str)
+ *str = (*str)[size:]
+ return rune
+}
+
+// Matches the pattern against the string, with the given flags,
+// and returns true if the match is successful.
+// This function should match fnmatch.3 as closely as possible.
+func Match(pattern, s string, flags int) bool {
+ // The implementation for this function was patterned after the BSD fnmatch.c
+ // source found at http://src.gnu-darwin.org/src/contrib/csup/fnmatch.c.html
+ noescape := (flags&FNM_NOESCAPE != 0)
+ pathname := (flags&FNM_PATHNAME != 0)
+ period := (flags&FNM_PERIOD != 0)
+ leadingdir := (flags&FNM_LEADING_DIR != 0)
+ casefold := (flags&FNM_CASEFOLD != 0)
+ // the following is some bookkeeping that the original fnmatch.c implementation did not do
+ // We are forced to do this because we're not keeping indexes into C strings but rather
+ // processing utf8-encoded strings. Use a custom unpacker to maintain our state for us
+ sAtStart := true
+ sLastAtStart := true
+ sLastSlash := false
+ sLastUnpacked := rune(0)
+ unpackS := func() rune {
+ sLastSlash = (sLastUnpacked == '/')
+ sLastUnpacked = unpackRune(&s)
+ sLastAtStart = sAtStart
+ sAtStart = false
+ return sLastUnpacked
+ }
+ for len(pattern) > 0 {
+ c := unpackRune(&pattern)
+ switch c {
+ case '?':
+ if len(s) == 0 {
+ return false
+ }
+ sc := unpackS()
+ if pathname && sc == '/' {
+ return false
+ }
+ if period && sc == '.' && (sLastAtStart || (pathname && sLastSlash)) {
+ return false
+ }
+ case '*':
+ // collapse multiple *'s
+ // don't use unpackRune here, the only char we care to detect is ASCII
+ for len(pattern) > 0 && pattern[0] == '*' {
+ pattern = pattern[1:]
+ }
+ if period && s[0] == '.' && (sAtStart || (pathname && sLastUnpacked == '/')) {
+ return false
+ }
+ // optimize for patterns with * at end or before /
+ if len(pattern) == 0 {
+ if pathname {
+ return leadingdir || (strchr(s, '/') == -1)
+ } else {
+ return true
+ }
+ return !(pathname && strchr(s, '/') >= 0)
+ } else if pathname && pattern[0] == '/' {
+ offset := strchr(s, '/')
+ if offset == -1 {
+ return false
+ } else {
+ // we already know our pattern and string have a /, skip past it
+ s = s[offset:] // use unpackS here to maintain our bookkeeping state
+ unpackS()
+ pattern = pattern[1:] // we know / is one byte long
+ break
+ }
+ }
+ // general case, recurse
+ for test := s; len(test) > 0; unpackRune(&test) {
+ // I believe the (flags &^ FNM_PERIOD) is a bug when FNM_PATHNAME is specified
+ // but this follows exactly from how fnmatch.c implements it
+ if Match(pattern, test, (flags &^ FNM_PERIOD)) {
+ return true
+ } else if pathname && test[0] == '/' {
+ break
+ }
+ }
+ return false
+ case '[':
+ if len(s) == 0 {
+ return false
+ }
+ if pathname && s[0] == '/' {
+ return false
+ }
+ sc := unpackS()
+ if !rangematch(&pattern, sc, flags) {
+ return false
+ }
+ case '\\':
+ if !noescape {
+ if len(pattern) > 0 {
+ c = unpackRune(&pattern)
+ }
+ }
+ fallthrough
+ default:
+ if len(s) == 0 {
+ return false
+ }
+ sc := unpackS()
+ switch {
+ case sc == c:
+ case casefold && unicode.ToLower(sc) == unicode.ToLower(c):
+ default:
+ return false
+ }
+ }
+ }
+ return len(s) == 0 || (leadingdir && s[0] == '/')
+}
+
+func rangematch(pattern *string, test rune, flags int) bool {
+ if len(*pattern) == 0 {
+ return false
+ }
+ casefold := (flags&FNM_CASEFOLD != 0)
+ noescape := (flags&FNM_NOESCAPE != 0)
+ if casefold {
+ test = unicode.ToLower(test)
+ }
+ var negate, matched bool
+ if (*pattern)[0] == '^' || (*pattern)[0] == '!' {
+ negate = true
+ (*pattern) = (*pattern)[1:]
+ }
+ for !matched && len(*pattern) > 1 && (*pattern)[0] != ']' {
+ c := unpackRune(pattern)
+ if !noescape && c == '\\' {
+ if len(*pattern) > 1 {
+ c = unpackRune(pattern)
+ } else {
+ return false
+ }
+ }
+ if casefold {
+ c = unicode.ToLower(c)
+ }
+ if (*pattern)[0] == '-' && len(*pattern) > 1 && (*pattern)[1] != ']' {
+ unpackRune(pattern) // skip the -
+ c2 := unpackRune(pattern)
+ if !noescape && c2 == '\\' {
+ if len(*pattern) > 0 {
+ c2 = unpackRune(pattern)
+ } else {
+ return false
+ }
+ }
+ if casefold {
+ c2 = unicode.ToLower(c2)
+ }
+ // this really should be more intelligent, but it looks like
+ // fnmatch.c does simple int comparisons, therefore we will as well
+ if c <= test && test <= c2 {
+ matched = true
+ }
+ } else if c == test {
+ matched = true
+ }
+ }
+ // skip past the rest of the pattern
+ ok := false
+ for !ok && len(*pattern) > 0 {
+ c := unpackRune(pattern)
+ if c == '\\' && len(*pattern) > 0 {
+ unpackRune(pattern)
+ } else if c == ']' {
+ ok = true
+ }
+ }
+ return ok && matched != negate
+}
+
+// define strchr because strings.Index() seems a bit overkill
+// returns the index of c in s, or -1 if there is no match
+func strchr(s string, c rune) int {
+ for i, sc := range s {
+ if sc == c {
+ return i
+ }
+ }
+ return -1
+}