Going futher
This commit is contained in:
parent
3d4c08a7a0
commit
44ab1bf59c
3 changed files with 543 additions and 81 deletions
379
.golangci.yml
379
.golangci.yml
|
@ -68,7 +68,7 @@ output:
|
|||
print-linter-name: true
|
||||
|
||||
# make issues output unique by line, default is true
|
||||
#uniq-by-line: true
|
||||
uniq-by-line: false
|
||||
|
||||
# add a prefix to the output file references; default is no prefix
|
||||
path-prefix: ""
|
||||
|
@ -352,6 +352,7 @@ linters-settings:
|
|||
- github.com/stretchr/testify
|
||||
domains: # List of allowed module domains
|
||||
- golang.org
|
||||
- code.bcarlin.xyz
|
||||
blocked:
|
||||
modules: # List of blocked modules
|
||||
# - github.com/uudashr/go-module: # Blocked module
|
||||
|
@ -362,7 +363,7 @@ linters-settings:
|
|||
# - github.com/mitchellh/go-homedir: # Blocked module with version constraint
|
||||
# version: "< 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons
|
||||
# reason: "testing if blocked version constraint works." # Reason why the version constraint exists. (Optional)
|
||||
local_replace_directives: false # Set to true to raise lint issues for packages that are loaded from a local path via replace directive
|
||||
local_replace_directives: true # Set to true to raise lint issues for packages that are loaded from a local path via replace directive
|
||||
|
||||
gosec:
|
||||
# To select a subset of rules to run.
|
||||
|
@ -411,7 +412,7 @@ linters-settings:
|
|||
# run `go tool vet help` to see all analyzers
|
||||
#enable:
|
||||
# - atomicalign
|
||||
#enable-all: false
|
||||
enable-all: false
|
||||
#disable:
|
||||
# - shadow
|
||||
#disable-all: false
|
||||
|
@ -450,10 +451,12 @@ linters-settings:
|
|||
# alias: $1$2
|
||||
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
line-length: 100
|
||||
# tab width in spaces. Default to 1.
|
||||
# Max line length, lines longer will be reported.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option.
|
||||
# Default: 120.
|
||||
line-length: 90
|
||||
# Tab width in spaces.
|
||||
# Default: 1
|
||||
tab-width: 1
|
||||
|
||||
makezero:
|
||||
|
@ -525,19 +528,336 @@ linters-settings:
|
|||
- github.com/jmoiron/modl
|
||||
|
||||
revive:
|
||||
# see https://github.com/mgechev/revive#available-rules for details.
|
||||
# Maximum number of open files at the same time.
|
||||
# See https://github.com/mgechev/revive#command-line-flags
|
||||
# Defaults to unlimited.
|
||||
#max-open-files: 2048
|
||||
# When set to false, ignores files with "GENERATED" header, similar to golint.
|
||||
# See https://github.com/mgechev/revive#available-rules for details.
|
||||
# Default: false
|
||||
ignore-generated-header: true
|
||||
# Sets the default severity.
|
||||
# See https://github.com/mgechev/revive#configuration
|
||||
# Default: warning
|
||||
severity: warning
|
||||
#rules:
|
||||
# - name: indent-error-flow
|
||||
# severity: warning
|
||||
# - name: add-constant
|
||||
# severity: warning
|
||||
# arguments:
|
||||
# - maxLitCount: "3"
|
||||
# allowStrs: '""'
|
||||
# allowInts: "0,1,2"
|
||||
# allowFloats: "0.0,0.,1.0,1.,2.0,2."
|
||||
# Enable all available rules.
|
||||
# Default: false
|
||||
enable-all-rules: true
|
||||
# Sets the default failure confidence.
|
||||
# This means that linting errors with less than 0.8 confidence will be ignored.
|
||||
# Default: 0.8
|
||||
#confidence: 0.1
|
||||
rules:
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#add-constant
|
||||
- name: add-constant
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments:
|
||||
- maxLitCount: "3"
|
||||
allowStrs: '""'
|
||||
allowInts: "0,1"
|
||||
allowFloats: ""
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#atomic
|
||||
- name: argument-limit
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments: [4]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#atomic
|
||||
- name: atomic
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#banned-characters
|
||||
- name: banned-characters
|
||||
severity: warning
|
||||
disabled: true
|
||||
arguments: ["Ω", "Σ", "σ", "7"]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bare-return
|
||||
- name: bare-return
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#blank-imports
|
||||
- name: blank-imports
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bool-literal-in-expr
|
||||
- name: bool-literal-in-expr
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#call-to-gc
|
||||
- name: call-to-gc
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#cognitive-complexity
|
||||
- name: cognitive-complexity
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments: [7]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#confusing-naming
|
||||
- name: confusing-naming
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#confusing-results
|
||||
- name: confusing-results
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#constant-logical-expr
|
||||
- name: constant-logical-expr
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-as-argument
|
||||
- name: context-as-argument
|
||||
severity: info
|
||||
disabled: false
|
||||
arguments:
|
||||
- allowTypesBefore: "*testing.T"
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-keys-type
|
||||
- name: context-keys-type
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#cyclomatic
|
||||
- name: cyclomatic
|
||||
severity: error
|
||||
disabled: false
|
||||
arguments: [20]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#deep-exit
|
||||
- name: deep-exit
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#defer
|
||||
- name: defer
|
||||
severity: error
|
||||
disabled: false
|
||||
#arguments:
|
||||
# - ["call-chain", "loop"]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#dot-imports
|
||||
- name: dot-imports
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#duplicated-imports
|
||||
- name: duplicated-imports
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#early-return
|
||||
- name: early-return
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-block
|
||||
- name: empty-block
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-lines
|
||||
- name: empty-lines
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-naming
|
||||
- name: error-naming
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-return
|
||||
- name: error-return
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-strings
|
||||
- name: error-strings
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#errorf
|
||||
- name: errorf
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#exported
|
||||
- name: exported
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments:
|
||||
- "checkPrivateReceivers"
|
||||
- "sayRepetitiveInsteadOfStutters"
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#file-header
|
||||
- name: file-header
|
||||
severity: warning
|
||||
disabled: true
|
||||
arguments:
|
||||
- This is the text that must appear at the top of source files.
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#flag-parameter
|
||||
- name: flag-parameter
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#function-result-limit
|
||||
- name: function-result-limit
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments: [2]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#function-length
|
||||
- name: function-length
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments: [20, 0]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#get-return
|
||||
- name: get-return
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#identical-branches
|
||||
- name: identical-branches
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#if-return
|
||||
- name: if-return
|
||||
severity: warning
|
||||
disabled: true
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#increment-decrement
|
||||
- name: increment-decrement
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#indent-error-flow
|
||||
- name: indent-error-flow
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#imports-blacklist
|
||||
- name: imports-blacklist
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments:
|
||||
- "crypto/md5"
|
||||
- "crypto/sha1"
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-shadowing
|
||||
- name: import-shadowing
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#line-length-limit
|
||||
- name: line-length-limit
|
||||
severity: info
|
||||
disabled: false
|
||||
arguments: [90]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#max-public-structs
|
||||
- name: max-public-structs
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments: [3]
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#modifies-parameter
|
||||
- name: modifies-parameter
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#modifies-value-receiver
|
||||
- name: modifies-value-receiver
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#nested-structs
|
||||
- name: nested-structs
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#optimize-operands-order
|
||||
- name: optimize-operands-order
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#package-comments
|
||||
- name: package-comments
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range
|
||||
- name: range
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-in-closure
|
||||
- name: range-val-in-closure
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-address
|
||||
- name: range-val-address
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#receiver-naming
|
||||
- name: receiver-naming
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redefines-builtin-id
|
||||
- name: redefines-builtin-id
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-of-int
|
||||
- name: string-of-int
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-format
|
||||
- name: string-format
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments:
|
||||
- - 'fmt.Errorf[0]'
|
||||
- '/(^|[^\.!?])$/'
|
||||
- must not end in punctuation
|
||||
- - panic
|
||||
- '/^[^\n]*$/'
|
||||
- must not contain line breaks
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#struct-tag
|
||||
- name: struct-tag
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#superfluous-else
|
||||
- name: superfluous-else
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-equal
|
||||
- name: time-equal
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-naming
|
||||
- name: time-naming
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-naming
|
||||
- name: var-naming
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments:
|
||||
- ["ID"] # AllowList
|
||||
- ["VM"] # DenyList
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-declaration
|
||||
- name: var-declaration
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unconditional-recursion
|
||||
- name: unconditional-recursion
|
||||
severity: error
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-naming
|
||||
- name: unexported-naming
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return
|
||||
- name: unexported-return
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unhandled-error
|
||||
- name: unhandled-error
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments:
|
||||
- "fmt.Printf"
|
||||
- "myFunction"
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unnecessary-stmt
|
||||
- name: unnecessary-stmt
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unreachable-code
|
||||
- name: unreachable-code
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter
|
||||
- name: unused-parameter
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-receiver
|
||||
- name: unused-receiver
|
||||
severity: info
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break
|
||||
- name: useless-break
|
||||
severity: warning
|
||||
disabled: false
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#waitgroup-by-value
|
||||
- name: waitgroup-by-value
|
||||
severity: warning
|
||||
disabled: false
|
||||
|
||||
staticcheck:
|
||||
# Select the Go version to target. The default is '1.13'.
|
||||
|
@ -663,13 +983,15 @@ linters:
|
|||
- depguard
|
||||
- exhaustivestruct
|
||||
- goheader
|
||||
- golint
|
||||
- golint # Deprecated
|
||||
- interfacer
|
||||
- lll # Done by revive with better messages
|
||||
- maligned
|
||||
- paralleltest
|
||||
- prealloc
|
||||
- scopelint
|
||||
- scopelint # Deprecated
|
||||
- testpackage
|
||||
- varcheck # also done by unused and deadcode
|
||||
#presets:
|
||||
# - bugs
|
||||
# - unused
|
||||
|
@ -777,12 +1099,13 @@ severity:
|
|||
# If set to true severity-rules regular expressions become case sensitive.
|
||||
case-sensitive: false
|
||||
|
||||
# Default value is empty list.
|
||||
# When a list of severity rules are provided, severity information will be added to lint
|
||||
# issues. Severity rules have the same filtering capability as exclude rules except you
|
||||
# are allowed to specify one matcher per severity rule.
|
||||
# Only affects out formats that support setting severity information.
|
||||
# Default value is empty list. When a list of severity rules are
|
||||
# provided, severity information will be added to lint issues. Severity
|
||||
# rules have the same filtering capability as exclude rules except you
|
||||
# are allowed to specify one matcher per severity rule. Only affects out
|
||||
# formats that support setting severity information.
|
||||
rules:
|
||||
- linters:
|
||||
- dupl
|
||||
severity: info
|
||||
#- linters:
|
||||
# - dupl
|
||||
# - lll
|
||||
# severity: info
|
||||
|
|
205
rx.go
205
rx.go
|
@ -6,42 +6,65 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// Flags changes the meaning of the regex.
|
||||
type Flags uint
|
||||
|
||||
const (
|
||||
// CaseInsensitive makes the regex case insensitive (flag "i" set).
|
||||
CaseInsensitive Flags = 1 << iota
|
||||
|
||||
// CaseSensitive makes the regex case sensitive (flag "i" cleared,
|
||||
// default behavior).
|
||||
CaseSensitive
|
||||
|
||||
// MultiLine makes StartOfText and EndOfText match the beginning and
|
||||
// the end of each line (flag "m" set).
|
||||
MultiLine
|
||||
|
||||
// SingleLine makes StartOfText and EndOfText match the beginning and
|
||||
// the end of the whole text (flag "m" cleared, default behavior).
|
||||
SingleLine
|
||||
|
||||
// AnyNL makes Any match new lines(flag "s" set).
|
||||
AnyNL
|
||||
|
||||
// AnyNoNL makes Any not match new lines (flag "s" cleared, default
|
||||
// behavior).
|
||||
AnyNoNL
|
||||
|
||||
// Ungreedy makes the quantifiers match the shortest text possible
|
||||
// (flag "U" set).
|
||||
Ungreedy
|
||||
|
||||
// Greedy makes the quantifiers match the longest text possible (flag
|
||||
// "U" cleared, default behavior).
|
||||
Greedy
|
||||
)
|
||||
|
||||
// Regex represents a regular expression.
|
||||
type Regex string
|
||||
|
||||
const (
|
||||
// Any matches any character (".").
|
||||
Any = "."
|
||||
Any Regex = "."
|
||||
|
||||
nonGreedyOp Regex = "?"
|
||||
)
|
||||
|
||||
//
|
||||
// CHARACTER CLASSES
|
||||
//
|
||||
|
||||
// In generates a character class composed by the concatenation of all arguments.
|
||||
// In generates a character class composed by the concatenation of all
|
||||
// arguments.
|
||||
func (r Regex) In(rxs ...Regex) Regex {
|
||||
r += "["
|
||||
|
||||
for _, rx := range rxs {
|
||||
r += rx
|
||||
}
|
||||
|
||||
r += "]"
|
||||
|
||||
return r
|
||||
return r + "[" + joinRxs(rxs, "") + "]"
|
||||
}
|
||||
|
||||
// NotIn generates a negated character class composed by the concatenation of all arguments.
|
||||
// NotIn generates a negated character class composed by the concatenation
|
||||
// of all arguments.
|
||||
func (r Regex) NotIn(rxs ...Regex) Regex {
|
||||
r += "[^"
|
||||
|
||||
for _, rx := range rxs {
|
||||
r += rx
|
||||
}
|
||||
|
||||
r += "]"
|
||||
|
||||
return r
|
||||
return r + "[^" + joinRxs(rxs, "") + "]"
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -50,46 +73,33 @@ func (r Regex) NotIn(rxs ...Regex) Regex {
|
|||
|
||||
// Then appends the given regexes to the current one.
|
||||
func (r Regex) Then(rxs ...Regex) Regex {
|
||||
for _, rx := range rxs {
|
||||
r += rx
|
||||
}
|
||||
|
||||
return r
|
||||
return r + joinRxs(rxs, "")
|
||||
}
|
||||
|
||||
// AnyOf appends an alternative to the regex. The resulting alternative
|
||||
// matches any of the given regexes.
|
||||
func (r Regex) AnyOf(rxs ...Regex) Regex {
|
||||
r += "(?:"
|
||||
|
||||
for i, rx := range rxs {
|
||||
if i != 0 {
|
||||
r += "|"
|
||||
}
|
||||
|
||||
r += rx
|
||||
}
|
||||
|
||||
r += ")"
|
||||
|
||||
return r
|
||||
return r + "(?:" + joinRxs(rxs, "|") + ")"
|
||||
}
|
||||
|
||||
//
|
||||
// QUANTIFIERS
|
||||
//
|
||||
|
||||
// ZeroOrMore appends the given regex with a "zero or more" quantifier ("*"), prefer more.
|
||||
// ZeroOrMore appends the given regex with a "zero or more" quantifier
|
||||
// ("*"), prefer more.
|
||||
func (r Regex) ZeroOrMore(rx Regex) Regex {
|
||||
return r + protectMultiChar(rx) + "*"
|
||||
}
|
||||
|
||||
// OneOrMore appends the given regex with a "one or more" quantifier ("+"), prefer more.
|
||||
// OneOrMore appends the given regex with a "one or more" quantifier ("+"),
|
||||
// prefer more.
|
||||
func (r Regex) OneOrMore(rx Regex) Regex {
|
||||
return r + protectMultiChar(rx) + "+"
|
||||
}
|
||||
|
||||
// ZeroOrOne appends the given regex with a "one or more" quantifier ("?"), prefer more.
|
||||
// ZeroOrOne appends the given regex with a "one or more" quantifier ("?"),
|
||||
// prefer more.
|
||||
func (r Regex) ZeroOrOne(rx Regex) Regex {
|
||||
return r + protectMultiChar(rx) + "?"
|
||||
}
|
||||
|
@ -99,7 +109,8 @@ func (r Regex) NTimes(n int, rx Regex) Regex {
|
|||
return Regex(fmt.Sprintf("%s%s{%d}", r, protectMultiChar(rx), n))
|
||||
}
|
||||
|
||||
// NOrMore appends the given regex with an minimum number of repeats ("{N,}"), prefer more.
|
||||
// NOrMore appends the given regex with an minimum number of repeats
|
||||
// ("{N,}"), prefer more.
|
||||
func (r Regex) NOrMore(n int, rx Regex) Regex {
|
||||
return Regex(fmt.Sprintf("%s%s{%d,}", r, protectMultiChar(rx), n))
|
||||
}
|
||||
|
@ -110,35 +121,67 @@ func (r Regex) NUpToM(n, m int, rx Regex) Regex {
|
|||
return Regex(fmt.Sprintf("%s%s{%d,%d}", r, protectMultiChar(rx), n, m))
|
||||
}
|
||||
|
||||
// ZeroOrMoreLazy appends the given regex with a "zero or more" quantifier ("*"), prefer more.
|
||||
// ZeroOrMoreLazy appends the given regex with a "zero or more" quantifier
|
||||
// ("*"), prefer more.
|
||||
func (r Regex) ZeroOrMoreLazy(rx Regex) Regex {
|
||||
return r.ZeroOrMore(rx) + "?"
|
||||
return r.ZeroOrMore(rx) + nonGreedyOp
|
||||
}
|
||||
|
||||
// OneOrMoreLazy appends the given regex with a "one or more" quantifier ("+"), prefer more.
|
||||
// OneOrMoreLazy appends the given regex with a "one or more" quantifier
|
||||
// ("+"), prefer more.
|
||||
func (r Regex) OneOrMoreLazy(rx Regex) Regex {
|
||||
return r.OneOrMore(rx) + "?"
|
||||
return r.OneOrMore(rx) + nonGreedyOp
|
||||
}
|
||||
|
||||
// ZeroOrOneLazy appends the given regex with a "one or more" quantifier ("?"), prefer more.
|
||||
// ZeroOrOneLazy appends the given regex with a "one or more" quantifier
|
||||
// ("?"), prefer more.
|
||||
func (r Regex) ZeroOrOneLazy(rx Regex) Regex {
|
||||
return r.ZeroOrOne(rx) + "?"
|
||||
return r.ZeroOrOne(rx) + nonGreedyOp
|
||||
}
|
||||
|
||||
// NTimesLazy appends the given regex with an exact number of repeats ("{N}").
|
||||
func (r Regex) NTimesLazy(n int, rx Regex) Regex {
|
||||
return r.NTimes(n, rx) + "?"
|
||||
return r.NTimes(n, rx) + nonGreedyOp
|
||||
}
|
||||
|
||||
// NOrMoreLazy appends the given regex with an minimum number of repeats ("{N,}"), prefer more.
|
||||
// NOrMoreLazy appends the given regex with an minimum number of repeats
|
||||
// ("{N,}"), prefer more.
|
||||
func (r Regex) NOrMoreLazy(n int, rx Regex) Regex {
|
||||
return r.NOrMore(n, rx) + "?"
|
||||
return r.NOrMore(n, rx) + nonGreedyOp
|
||||
}
|
||||
|
||||
// NUpToMLazy appends the given regex with an minimum and maximum number of repeats
|
||||
// ("{N,M}"), prefer more.
|
||||
func (r Regex) NUpToMLazy(n, m int, rx Regex) Regex {
|
||||
return r.NUpToM(n, m, rx) + "?"
|
||||
return r.NUpToM(n, m, rx) + nonGreedyOp
|
||||
}
|
||||
|
||||
//
|
||||
// GROUPS
|
||||
//
|
||||
|
||||
// Capture appends a capture group to the regexes. The regexes given as
|
||||
// arguments are just concatenated.
|
||||
func (r Regex) Capture(rxs ...Regex) Regex {
|
||||
return r + "(" + joinRxs(rxs, "") + ")"
|
||||
}
|
||||
|
||||
// CaptureName appends a named capture group to the regexes. The regexes
|
||||
// given as arguments are just concatenated.
|
||||
func (r Regex) CaptureName(name string, rxs ...Regex) Regex {
|
||||
return r + "(?P<" + Regex(name) + ">" + joinRxs(rxs, "") + ")"
|
||||
}
|
||||
|
||||
// WithFlags appends a non-capturing group with the given flags set to the
|
||||
// regex. The regexes given as arguments are just concatenated.
|
||||
func (r Regex) WithFlags(flags Flags, rxs ...Regex) Regex {
|
||||
tmp := joinRxs(rxs, "")
|
||||
|
||||
if f := buildFlagString(flags); f != "" {
|
||||
tmp = "(?" + Regex(f) + ":" + tmp + ")"
|
||||
}
|
||||
|
||||
return r + tmp
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -215,3 +258,59 @@ func areHexaDigits(s string) bool {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
func buildFlagString(flags Flags) string {
|
||||
set, cleared := "", ""
|
||||
|
||||
if flags&CaseInsensitive != 0 {
|
||||
set += "i"
|
||||
}
|
||||
|
||||
if flags&MultiLine != 0 {
|
||||
set += "m"
|
||||
}
|
||||
|
||||
if flags&AnyNL != 0 {
|
||||
set += "s"
|
||||
}
|
||||
|
||||
if flags&Ungreedy != 0 {
|
||||
set += "U"
|
||||
}
|
||||
|
||||
if flags&CaseSensitive != 0 {
|
||||
cleared += "i"
|
||||
}
|
||||
|
||||
if flags&SingleLine != 0 {
|
||||
cleared += "m"
|
||||
}
|
||||
|
||||
if flags&AnyNoNL != 0 {
|
||||
cleared += "s"
|
||||
}
|
||||
|
||||
if flags&Greedy != 0 {
|
||||
cleared += "U"
|
||||
}
|
||||
|
||||
if cleared != "" {
|
||||
cleared = "-" + cleared
|
||||
}
|
||||
|
||||
return set + cleared
|
||||
}
|
||||
|
||||
func joinRxs(rxs []Regex, sep string) Regex {
|
||||
var rv Regex
|
||||
|
||||
for i := range rxs {
|
||||
if i != 0 {
|
||||
rv += Regex(sep)
|
||||
}
|
||||
|
||||
rv += rxs[i]
|
||||
}
|
||||
|
||||
return rv
|
||||
}
|
||||
|
|
40
rx_test.go
40
rx_test.go
|
@ -46,6 +46,31 @@ func TestRegex(t *testing.T) {
|
|||
require.Equal(t, tc.expected, string(a.ZeroOrMore(tc.rx)))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WithFlags() method", func(t *testing.T) {
|
||||
tcs := []struct {
|
||||
rx Flags
|
||||
expected string
|
||||
}{
|
||||
{0, "aa"},
|
||||
{CaseInsensitive, "a(?i:a)"},
|
||||
{CaseSensitive, "a(?-i:a)"},
|
||||
{MultiLine, "a(?m:a)"},
|
||||
{SingleLine, "a(?-m:a)"},
|
||||
{AnyNL, "a(?s:a)"},
|
||||
{AnyNoNL, "a(?-s:a)"},
|
||||
{Ungreedy, "a(?U:a)"},
|
||||
{Greedy, "a(?-U:a)"},
|
||||
{CaseInsensitive | MultiLine, "a(?im:a)"},
|
||||
{CaseInsensitive | SingleLine, "a(?i-m:a)"},
|
||||
{0b11111111, "a(?imsU-imsU:a)"},
|
||||
{CaseInsensitive | MultiLine | AnyNoNL | Greedy, "a(?im-sU:a)"},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
require.Equal(t, tc.expected, string(a.WithFlags(tc.rx, "a")))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func ExampleRegex_In() {
|
||||
|
@ -163,3 +188,18 @@ func ExampleRegex_NUpToMLazy() {
|
|||
// ab{3,5}?
|
||||
// a(?:abc){3,5}?
|
||||
}
|
||||
|
||||
func ExampleRegex_Capture() {
|
||||
fmt.Println(Regex("a").Capture("a", "b"))
|
||||
// Output: a(ab)
|
||||
}
|
||||
|
||||
func ExampleRegex_CaptureName() {
|
||||
fmt.Println(Regex("a").CaptureName("foo", "a", "b"))
|
||||
// Output: a(?P<foo>ab)
|
||||
}
|
||||
|
||||
func ExampleRegex_WithFlags() {
|
||||
fmt.Println(Regex("a").WithFlags(AnyNL|CaseSensitive, "a", "b"))
|
||||
// Output: a(?s-i:ab)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue