goutils/cmd/fragment/fragment.go

107 lines
1.7 KiB
Go

package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"git.wntrmute.dev/kyle/goutils/die"
)
func init() {
flag.Usage = func() { usage(os.Stdout); os.Exit(1) }
}
func usage(w io.Writer) {
progname := filepath.Base(os.Args[0])
fmt.Fprintf(w, `Usage: %s [-nl] file start [end]
Print a fragment of a file starting a line 'start' and ending
at line 'end', or EOF if no end is specified.
The -nl flag will suppress printing of line numbers.
`, progname)
}
func main() {
quiet := flag.Bool("nl", false, "No line-numbering.")
flag.Parse()
if flag.NArg() < 2 || flag.NArg() > 3 {
usage(os.Stderr)
os.Exit(1)
}
start, err := strconv.Atoi(flag.Arg(1))
die.If(err)
var end int
var offset bool
if flag.NArg() == 3 {
endStr := flag.Arg(2)
if endStr[0] == '+' {
offset = true
endStr = endStr[1:]
}
end, err = strconv.Atoi(endStr)
die.If(err)
if offset {
end += start
}
}
file, err := os.Open(flag.Arg(0))
die.If(err)
defer file.Close()
scanner := bufio.NewScanner(file)
// initial empty line to start numbering at 1.
var lines = make([]string, 1)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if end == 0 {
end = len(lines) - 1
}
if end < start {
fmt.Fprintln(os.Stderr, "[!] end < start, swapping values")
tmp := end
end = start
start = tmp
}
var fmtStr string
if !*quiet {
maxLine := fmt.Sprintf("%d", len(lines))
fmtStr = fmt.Sprintf("%%0%dd: %%s", len(maxLine))
}
endFunc := func(n int) bool {
if n == 0 {
return false
}
if n > end {
return true
}
return false
}
fmtStr += "\n"
for i := start; !endFunc(i); i++ {
if *quiet {
fmt.Println(lines[i])
} else {
fmt.Printf(fmtStr, i, lines[i])
}
}
}