vendor: add qod FOR MAGEFILE ONLY
This commit is contained in:
parent
13f59562cd
commit
01e5dc7b56
|
@ -136,3 +136,4 @@ da118f7b8e5954f39d0d2130ab35d4bf0e3cb344 golang.org/x/net/context
|
|||
4e1c5567d7c2dd59fa4c7c83d34c2f3528b025d6 github.com/oxtoacart/bpool
|
||||
a3b3ca73af22dd09dfac218f586a8f42c681298d github.com/Xe/ln
|
||||
c605e284fe17294bda444b34710735b29d1a9d90 github.com/pkg/errors
|
||||
3abb44dfc7ba8b5cdfdb634786f57e78c7004e1c github.com/jtolds/qod
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
// Copyright (C) 2017 JT Olds
|
||||
// See LICENSE for copying information.
|
||||
|
||||
// Package qod should NOT be used in a serious software engineering
|
||||
// environment. qod stands for Quick and Dirty bahaha I just realized I got the
|
||||
// acronym wrong. It's fine. It's on brand. Quick AND Dirty.
|
||||
//
|
||||
// The context is I noticed that Go is my favorite language, but when a task
|
||||
// gets too complicated for a shell pipeline or awk or something, I turn to
|
||||
// Python. Why not Go?
|
||||
//
|
||||
// In Python, I'd frequently write something like:
|
||||
//
|
||||
// for line in sys.stdin:
|
||||
// vals = map(int, line.split())
|
||||
//
|
||||
// Here that is in Go:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import (
|
||||
// "bufio"
|
||||
// "fmt"
|
||||
// "os"
|
||||
// "strconv"
|
||||
// "strings"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// scanner := bufio.NewScanner(os.Stdin)
|
||||
// for scanner.Scan() {
|
||||
// var vals []int64
|
||||
// for _, str := range strings.Fields(scanner.Text()) {
|
||||
// val, err := strconv.ParseInt(str, 10, 64)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// vals = append(vals, val)
|
||||
// }
|
||||
// }
|
||||
// if err := scanner.Err(); err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Ugh! Considering I don't care about this throwaway shell pipeline
|
||||
// replacement, I'm clearly fine with it blowing up if something's wrong, and
|
||||
// wow this was too much.
|
||||
//
|
||||
// Package qod allows me to write the same type of thing in Go. Here is a
|
||||
// reimplementation of the Python code above using qod:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import (
|
||||
// "os"
|
||||
// "strings"
|
||||
//
|
||||
// "github.com/jtolds/qod"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// for line := range qod.Lines(os.Stdin) {
|
||||
// vals := qod.Int64Slice(strings.Fields(line))
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Better! I'm more likely to use Go now for little scripts!
|
||||
//
|
||||
// Reminder: don't use this for anything real. Most of the stuff in here
|
||||
// panics at the sight of any errors. That's obviously Bad and Wrong and you
|
||||
// should actually handle your errors. Set up your build system's linter to
|
||||
// reject anything that imports github.com/jtolds/qod please. If you have a
|
||||
// build system for what you're doing at all this isn't for you. If you have
|
||||
// some one-off tab-delimited data you need to process real quick like I seem
|
||||
// to ALL THE TIME then okay.
|
||||
package qod
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// ANE stands for Assert No Error. It panics if err != nil.
|
||||
func ANE(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// AFH stands for Assert File Handle. It asserts there was no error and
|
||||
// passes the file handle on through. Usage like:
|
||||
//
|
||||
// fh := qod.AFH(os.Open(path))
|
||||
func AFH(f *os.File, err error) *os.File {
|
||||
ANE(err)
|
||||
return f
|
||||
}
|
||||
|
||||
// AI stands for Assert Int. It asserts there was no error and
|
||||
// passes the int on through. Usage like:
|
||||
//
|
||||
// qod.AI(fmt.Println("a line"))
|
||||
func AI(i int, err error) int {
|
||||
ANE(err)
|
||||
return i
|
||||
}
|
||||
|
||||
// Lines makes reading lines easier. Usage like:
|
||||
//
|
||||
// for line := range Lines(os.Stdin) {
|
||||
// // do something with the line
|
||||
// }
|
||||
//
|
||||
// Returned lines will be right-stripped of whitespace.
|
||||
// If you care about the lifetime of the channel that you're reading from and
|
||||
// don't want it to leak, you probably shouldn't be using this package at all.
|
||||
func Lines(r io.Reader) <-chan string {
|
||||
ch := make(chan string)
|
||||
go func() {
|
||||
defer close(ch)
|
||||
br := bufio.NewReader(r)
|
||||
for {
|
||||
l, err := br.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
if l != "" {
|
||||
ch <- strings.TrimRightFunc(l, unicode.IsSpace)
|
||||
}
|
||||
break
|
||||
}
|
||||
ANE(err)
|
||||
ch <- strings.TrimRightFunc(l, unicode.IsSpace)
|
||||
}
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
// Float64 converts a string to a float64
|
||||
func Float64(val string) float64 {
|
||||
casted, err := strconv.ParseFloat(val, 64)
|
||||
ANE(err)
|
||||
return casted
|
||||
}
|
||||
|
||||
// Float64Slice converts a []string to a []float64
|
||||
func Float64Slice(vals []string) (rv []float64) {
|
||||
rv = make([]float64, 0, len(vals))
|
||||
for _, val := range vals {
|
||||
rv = append(rv, Float64(val))
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
// Int64 converts a string to an int64
|
||||
func Int64(val string) int64 {
|
||||
casted, err := strconv.ParseInt(val, 10, 64)
|
||||
ANE(err)
|
||||
return casted
|
||||
}
|
||||
|
||||
// Int64Slice converts a []string to an []int64
|
||||
func Int64Slice(vals []string) (rv []int64) {
|
||||
rv = make([]int64, 0, len(vals))
|
||||
for _, val := range vals {
|
||||
rv = append(rv, Int64(val))
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
// Printlnf is just cause I constantly use Println, then turn it into Printf,
|
||||
// then get frustrated I forgot the newline.
|
||||
func Printlnf(format string, vals ...interface{}) {
|
||||
AI(fmt.Printf(format+"\n", vals...))
|
||||
}
|
||||
|
||||
// Bytes will take an integer amount of bytes and format it with units.
|
||||
func Bytes(amount int64) string {
|
||||
val := float64(amount)
|
||||
moves := 0
|
||||
for val >= 1024 {
|
||||
val /= 1024
|
||||
moves += 1
|
||||
}
|
||||
return fmt.Sprintf("%0.02f %s", val, []string{
|
||||
"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}[moves])
|
||||
}
|
||||
|
||||
// SortedKeysBool returns the keys of a map[string]bool in sorted order.
|
||||
func SortedKeysBool(v map[string]bool) []string {
|
||||
rv := make([]string, 0, len(v))
|
||||
for key := range v {
|
||||
rv = append(rv, key)
|
||||
}
|
||||
sort.Strings(rv)
|
||||
return rv
|
||||
}
|
Loading…
Reference in New Issue