Skip to content

Instantly share code, notes, and snippets.

@zhsj
Created September 13, 2022 15:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhsj/429adb8b4af0dfe259ff7df7aa40f563 to your computer and use it in GitHub Desktop.
Save zhsj/429adb8b4af0dfe259ff7df7aa40f563 to your computer and use it in GitHub Desktop.
🐱
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"io"
"log"
"os"
)
var (
showAll = flag.Bool("A", false, "equivalent to -vET")
numberNonblank = flag.Bool("b", false, "number nonempty output lines, overrides -n")
showEv = flag.Bool("e", false, "equivalent to -vE")
showEnds = flag.Bool("E", false, "display $ at end of each line")
number = flag.Bool("n", false, "number all output lines")
squeezeBlank = flag.Bool("s", false, "suppress repeated empty output lines")
showTv = flag.Bool("t", false, "equivalent to -vT")
showTabs = flag.Bool("T", false, "display TAB characters as ^I")
showNonprinting = flag.Bool("v", false, "use ^ and M- notation, except for LFD and TAB")
lineno = 1
prevEmpty = false
)
func main() {
log.SetFlags(0)
parseFlag()
files := []string{}
if flag.NArg() == 0 {
files = append(files, "-")
} else {
files = os.Args[len(os.Args)-flag.NArg():]
}
for _, file := range files {
cat(file)
}
}
func parseFlag() {
t := true
flag.Parse()
if *showAll || *showEv || *showTv {
showNonprinting = &t
}
if *showAll || *showEv {
showEnds = &t
}
if *showAll || *showTv {
showTabs = &t
}
}
func open(filename string) (io.ReadCloser, error) {
if filename == "-" {
return os.Stdin, nil
}
return os.Open(filename)
}
func transformLine(line string) string {
var buffer bytes.Buffer
if (!*numberNonblank && *number) || (*numberNonblank && line != "") {
fmt.Fprintf(&buffer, "%6d\t", lineno)
lineno++
}
for _, c := range []byte(line) {
switch {
case *showTabs && c == '\t':
buffer.WriteString("^I")
case *showNonprinting && c < 32 && c != '\t' && c != '\n':
buffer.WriteByte('^')
buffer.WriteByte(c + '@')
case *showNonprinting && c == 127:
buffer.WriteString("^?")
case *showNonprinting && c >= 128 && c < 160:
buffer.WriteString("M-^")
buffer.WriteByte(c - 128 + '@')
case *showNonprinting && c >= 160 && c < 255:
buffer.WriteString("M-")
buffer.WriteByte(c - 160 + ' ')
case *showNonprinting && c == 255:
buffer.WriteString("M-^?")
default:
buffer.WriteByte(c)
}
}
if *showEnds {
buffer.WriteByte('$')
}
buffer.WriteByte('\n')
return buffer.String()
}
func cat(filename string) {
file, err := open(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if prevEmpty && *squeezeBlank && line == "" {
continue
}
prevEmpty = line == ""
_, err := os.Stdout.WriteString(transformLine(line))
if err != nil {
log.Fatal(err)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment