From f39a0b09904588eb130b570bc38f31915b4b9de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=BA=C5=A1=20Ollah?= Date: Fri, 4 Oct 2024 22:40:04 +0200 Subject: [PATCH] Initial commit --- .gitattributes | 2 ++ .gitignore | 21 +++++++++++++++++++++ LICENSE | 21 +++++++++++++++++++++ README.md | 24 ++++++++++++++++++++++++ go.mod | 3 +++ stripansi.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 go.mod create mode 100644 stripansi.go diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3b735ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2c1a22d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Matúš Ollah + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4e1ac3d --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# stripansi + +**stripansi** is a Go package for removing [ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code). + +## Basic Usage + +```go +package main + +import ( + "fmt" + "os" + + "github.com/MatusOllah/stripansi" +) + +func main() { + s := "\x1b[38;5;140mhello\x1b[0m world" + + fmt.Println(stripansi.String(s)) // "hello world" + fmt.Println(string(stripansi.Bytes([]byte(s)))) // "hello world" + stripansi.NewWriter(os.Stdout).Write([]byte(s)) // "hello world" +} +``` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1435702 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/MatusOllah/stripansi + +go 1.23.0 diff --git a/stripansi.go b/stripansi.go new file mode 100644 index 0000000..80c7c96 --- /dev/null +++ b/stripansi.go @@ -0,0 +1,44 @@ +// package stripansi provides utilities for removing ANSI escape sequences using regular expressions. +package stripansi + +import ( + "io" + "regexp" + "sync" +) + +var re *regexp.Regexp = regexp.MustCompile("[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))") + +// Regexp returns a copy of the underlying [regexp.Regexp]. +func Regexp() *regexp.Regexp { + return re.Copy() +} + +// Bytes removes ANSI escape sequences from the byte slice. +func Bytes(b []byte) []byte { + return re.ReplaceAll(b, nil) +} + +// String removes ANSI escape sequences from the string. +func String(s string) string { + return re.ReplaceAllString(s, "") +} + +// Writer wraps an [io.Writer] and removes ANSI sequences from its output. +type Writer struct { + w io.Writer + mu sync.Mutex +} + +// NewWriter creates a new [Writer]. +func NewWriter(w io.Writer) *Writer { + return &Writer{w: w} +} + +// Write removes ANSI escape sequences and writes to the underlying writer. +func (w *Writer) Write(p []byte) (n int, err error) { + w.mu.Lock() + defer w.mu.Unlock() + + return w.w.Write(Bytes(p)) +}