mirror of
https://github.com/peco/peco.git
synced 2026-09-10 07:16:29 -04:00
Benchmark (10k lines): plain text: 1023us -> 37us (-96%), 1.7MiB -> 0B (-100%), 30k -> 0 allocs 95% plain: 1064us -> 162us (-85%), 1720KiB -> 63KiB (-96%), 30.5k -> 2k allocs
99 lines
2.3 KiB
Go
99 lines
2.3 KiB
Go
package util
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
type fder interface {
|
|
Fd() uintptr
|
|
}
|
|
|
|
// CaseInsensitiveIndexFunc returns a function that matches runes equal to r, ignoring case.
|
|
func CaseInsensitiveIndexFunc(r rune) func(rune) bool {
|
|
lr := unicode.ToUpper(r)
|
|
return func(v rune) bool {
|
|
return lr == unicode.ToUpper(v)
|
|
}
|
|
}
|
|
|
|
// CaseInsensitiveIndex returns the byte index of the first rune in s that
|
|
// is case-insensitively equal to r. Returns -1 if not found. This avoids
|
|
// the closure allocation of CaseInsensitiveIndexFunc + strings.IndexFunc.
|
|
func CaseInsensitiveIndex(s string, r rune) int {
|
|
upper := unicode.ToUpper(r)
|
|
for i, c := range s {
|
|
if unicode.ToUpper(c) == upper {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// ContainsUpper reports whether the string contains any uppercase letter.
|
|
func ContainsUpper(query string) bool {
|
|
for _, c := range query {
|
|
if unicode.IsUpper(c) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Global var used to strips ansi sequences
|
|
var reANSIEscapeChars = regexp.MustCompile("\x1B\\[(?:[0-9]{1,2}(?:;[0-9]{1,2})?)*[a-zA-Z]")
|
|
|
|
// StripANSISequence strips ANSI escape sequences from the given string.
|
|
// Fast-path: if the string contains no ESC byte, return it unchanged
|
|
// to avoid a regexp allocation.
|
|
func StripANSISequence(s string) string {
|
|
if !strings.Contains(s, "\x1b") {
|
|
return s
|
|
}
|
|
return reANSIEscapeChars.ReplaceAllString(s, "")
|
|
}
|
|
|
|
type ignorable interface {
|
|
Ignorable() bool
|
|
}
|
|
|
|
type collectResults interface {
|
|
CollectResults() bool
|
|
}
|
|
|
|
type exitStatuser interface {
|
|
ExitStatus() int
|
|
}
|
|
|
|
// IsIgnorableError checks whether err implements the Ignorable interface and returns true.
|
|
func IsIgnorableError(err error) bool {
|
|
for e := err; e != nil; e = errors.Unwrap(e) {
|
|
if v, ok := e.(ignorable); ok {
|
|
return v.Ignorable()
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsCollectResultsError checks whether err signals that results should be collected.
|
|
func IsCollectResultsError(err error) bool {
|
|
for e := err; e != nil; e = errors.Unwrap(e) {
|
|
if v, ok := e.(collectResults); ok {
|
|
return v.CollectResults()
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// GetExitStatus extracts the exit status code from an error, returning 1 and false if not found.
|
|
func GetExitStatus(err error) (int, bool) {
|
|
for e := err; e != nil; e = errors.Unwrap(e) {
|
|
if ese, ok := e.(exitStatuser); ok {
|
|
return ese.ExitStatus(), true
|
|
}
|
|
}
|
|
return 1, false
|
|
}
|