feat: Add custom help text

pull/2/head
Karan Sharma 2020-12-13 21:03:44 +05:30
parent 40c62216ec
commit 9d2245f72e
7 changed files with 114 additions and 43 deletions

View File

@ -1,9 +1,8 @@
DOGGO-BIN := doggo.bin
HASH := $(shell git rev-parse --short HEAD)
COMMIT_DATE := $(shell git show -s --format=%ci ${HASH})
BUILD_DATE := $(shell date '+%Y-%m-%d %H:%M:%S')
VERSION := ${HASH} (${COMMIT_DATE})
VERSION := ${HASH}
.PHONY: build
build: ## Build the doggo binary

22
TODO.md
View File

@ -1,4 +1,4 @@
# doggo - v1.0 Milestone
# doggo - Initial Release Milestone
## Resolver
- [x] Create a DNS Resolver struct
@ -6,20 +6,22 @@
- [x] Add a resolve method
- [x] Make it separate from Hub
- [x] Parse output into separate fields
- [ ] Test IPv6
- [ ] Test IPv6/IPv4 only options
- [x] Add DOH support
- [x] Add DOT support
- [x] Add DNS protocol on TCP mode support.
- [ ] Error on NXDomain (Realted upstream [bug](https://github.com/miekg/dns/issues/1198))
- [ ] Support all DNS records?
- [x] Major records supported
## CLI Features
- [ ] `digfile`
- [x] `ndots` support
- [ ] `ndots` support
- [x] `search list` support
- [x] JSON output
- [x] Colorized output
- [x] Table output
- [ ] Parsing options free-form
- [x] Parsing options free-form
- [x] Remove urfave/cli in favour of `flag`
## CLI Grunt
@ -27,15 +29,27 @@
- [x] Neatly package them to load args in different functions
- [x] Upper case is not mandatory for query type/classes
- [x] Output
- [ ] Custom Help Text
- [x] Add examples
- [ ] Colorize
- [ ] Add different commands
- [x] Add client transport options
- [ ] Fix an issue while loading free form args, where the same records are being added twice
## Tests
## Documentation
- [ ] Mkdocs init project
- [ ] Custom Index (Landing Page)
## Release Checklist
- [ ] Goreleaser
- [ ] Snap
- [ ] Homebrew
- [ ] ARM
## v1.0
- [ ] Support obscure protocal tweaks in `dig`

View File

@ -1,11 +1,11 @@
package main
import (
"fmt"
"os"
"github.com/knadh/koanf"
"github.com/knadh/koanf/providers/posflag"
"github.com/sirupsen/logrus"
flag "github.com/spf13/pflag"
)
@ -27,10 +27,7 @@ func main() {
// Configure Flags
// Use the POSIX compliant pflag lib instead of Go's flag lib.
f := flag.NewFlagSet("config", flag.ContinueOnError)
f.Usage = func() {
fmt.Println(f.FlagUsages())
os.Exit(0)
}
f.Usage = renderCustomHelp
// Path to one or more config files to load into koanf along with some config params.
f.StringSliceP("query", "q", []string{}, "Domain name to query")
f.StringSliceP("type", "t", []string{}, "Type of DNS record to be queried (A, AAAA, MX etc)")
@ -50,26 +47,32 @@ func main() {
// Output Options
f.BoolP("json", "J", false, "Set the output format as JSON")
f.Bool("time", false, "Display how long it took for the response to arrive")
f.Bool("color", true, "Show colored output")
f.Bool("debug", false, "Enable debug mode")
// Parse and Load Flags
f.Parse(os.Args[1:])
if err := k.Load(posflag.Provider(f, ".", k), nil); err != nil {
hub.Logger.Fatalf("error loading flags: %v", err)
fmt.Println(f.FlagUsages())
os.Exit(0)
hub.Logger.Errorf("error loading flags: %v", err)
f.Usage()
hub.Logger.Exit(2)
}
// set log level
if k.Bool("debug") {
// Set logger level
hub.Logger.SetLevel(logrus.DebugLevel)
} else {
hub.Logger.SetLevel(logrus.InfoLevel)
}
// Run the app.
hub.Logger.Debug("Starting doggo...")
hub.Logger.Debug("Starting doggo 🐶")
// Parse Query Args
hub.loadQueryArgs()
// Start App
if len(hub.QueryFlags.QNames) == 0 {
fmt.Println(f.FlagUsages())
os.Exit(0)
f.Usage()
}
hub.Lookup()

View File

@ -1,21 +1,42 @@
package main
import (
"fmt"
"io"
"html/template"
"os"
)
// Override Help Template
var helpTmpl = `NAME:
{{.Name}}
{{ range $key, $value := . }}
<li><strong>{{ $key }}</strong>: {{ $value }}</li>
{{ end }}
// AppHelpTemplate is the text template to customise the Help output.
// Uses text/template to render templates.
var AppHelpTemplate = `NAME:
{{.Name}} {{.Description}}
USAGE:
{{.Name}} [OPTIONS] [--] <arguments>
VERSION:
{{.Version}} Built at {{.Date}}
EXAMPLES:
doggo mrkaran.dev Query a domain using defaults
doggo mrkaran.dev CNAME Looks up for a CNAME record.
doggo mrkaran.dev MX @9.9.9.9 Uses a custom DNS resolver.
doggo -q mrkaran.dev -t MX -n 1.1.1.1 Using named arguments
`
func renderCustomHelp(w io.Writer, templ string, data interface{}) {
var helpTmplVars = map[string]string{}
helpTmplVars["Name"] = "doggo"
fmt.Fprintf(w, helpTmpl, helpTmplVars)
func renderCustomHelp() {
helpTmplVars := map[string]string{
"Name": "doggo",
"Description": "DNS Client for Humans",
"Version": buildVersion,
"Date": buildDate,
}
tmpl, err := template.New("test").Parse(AppHelpTemplate)
if err != nil {
panic(err)
}
err = tmpl.Execute(os.Stdout, helpTmplVars)
if err != nil {
panic(err)
}
os.Exit(0)
}

View File

@ -31,6 +31,7 @@ type QueryFlags struct {
ShowJSON bool `koanf:"json"`
UseSearchList bool `koanf:"search"`
Ndots int `koanf:"ndots"`
Color bool `koanf:"color"`
}
// NewHub initializes an instance of Hub which holds app wide configuration.

View File

@ -64,9 +64,15 @@ func (hub *Hub) outputJSON(out []Output, msgs []resolvers.Response) {
}
func (hub *Hub) outputTerminal(out []Output) {
green := color.New(color.FgGreen).SprintFunc()
blue := color.New(color.FgBlue).SprintFunc()
magenta := color.New(color.FgMagenta).SprintFunc()
green := color.New(color.FgGreen, color.Bold).SprintFunc()
blue := color.New(color.FgBlue, color.Bold).SprintFunc()
yellow := color.New(color.FgYellow, color.Bold).SprintFunc()
cyan := color.New(color.FgCyan, color.Bold).SprintFunc()
red := color.New(color.FgRed, color.Bold).SprintFunc()
if !hub.QueryFlags.Color {
color.NoColor = true // disables colorized output
}
table := tablewriter.NewWriter(os.Stdout)
header := []string{"Name", "Type", "Class", "TTL", "Address", "Nameserver"}
@ -87,7 +93,24 @@ func (hub *Hub) outputTerminal(out []Output) {
table.SetNoWhiteSpace(true)
for _, o := range out {
output := []string{green(o.Name), blue(o.Type), o.Class, o.TTL, magenta(o.Address), o.Nameserver}
var typOut string
switch typ := o.Type; typ {
case "A":
typOut = blue(o.Type)
case "AAAA":
typOut = blue(o.Type)
case "MX":
typOut = cyan(o.Type)
case "NS":
typOut = cyan(o.Type)
case "CNAME":
typOut = yellow(o.Type)
case "TXT":
typOut = yellow(o.Type)
default:
typOut = red(o.Type)
}
output := []string{green(o.Name), typOut, o.Class, o.TTL, o.Address, o.Nameserver}
// Print how long it took
if hub.QueryFlags.DisplayTimeTaken {
output = append(output, o.TimeTaken)
@ -125,10 +148,28 @@ func collectOutput(responses []resolvers.Response) []Output {
addr = t.AAAA.String()
case *dns.CNAME:
addr = t.Target
case *dns.CAA:
addr = t.Tag + " " + t.Value
case *dns.HINFO:
addr = t.Cpu + " " + t.Os
// case *dns.LOC:
// addr = t.String()
case *dns.PTR:
addr = t.Ptr
case *dns.SRV:
addr = strconv.Itoa(int(t.Priority)) + " " +
strconv.Itoa(int(t.Weight)) + " " +
t.Target + ":" + strconv.Itoa(int(t.Port))
case *dns.TXT:
addr = t.String()
case *dns.NS:
addr = t.String()
case *dns.MX:
addr = strconv.Itoa(int(t.Preference)) + " " + t.Mx
case *dns.SOA:
addr = t.String()
case *dns.NAPTR:
addr = t.String()
}
h := a.Header()

View File

@ -5,17 +5,9 @@ import (
"strings"
"github.com/miekg/dns"
"github.com/sirupsen/logrus"
)
func (hub *Hub) loadQueryArgs() error {
// set log level
if k.Bool("debug") {
// Set logger level
hub.Logger.SetLevel(logrus.DebugLevel)
} else {
hub.Logger.SetLevel(logrus.InfoLevel)
}
err := hub.loadNamedArgs()