Skip to content

Commit

Permalink
fix: proper alignment of help text
Browse files Browse the repository at this point in the history
fixes #123
  • Loading branch information
mr-karan committed Jul 2, 2024
1 parent d74bb59 commit 8f60428
Showing 1 changed file with 101 additions and 58 deletions.
159 changes: 101 additions & 58 deletions cmd/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,84 +8,129 @@ import (
)

// appHelpTextTemplate is the text/template to customise the Help output.
// Uses text/template to render templates.
var appHelpTextTemplate = `{{ "NAME" | color "" "heading" }}:
{{ .Name | color "green" "bold" }} 🐶 {{.Description}}
{{ .Name | color "green" "bold" }} 🐶 {{ .Description }}
{{ "USAGE" | color "" "heading" }}:
{{ .Name | color "green" "bold" }} [--] {{ "[query options]" | color "yellow" "" }} {{ "[arguments...]" | color "cyan" "" }}
{{ "VERSION" | color "" "heading" }}:
{{.Version | color "red" "" }} - {{.Date | color "red" ""}}
{{ .Version | color "red" "" }} - {{ .Date | color "red" "" }}
{{ "EXAMPLES" | color "" "heading" }}:
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev" | color "cyan" "" }} Query a domain using defaults.
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev CNAME" | color "cyan" "" }} Query for a CNAME record.
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev MX @9.9.9.9" | color "cyan" "" }} Uses a custom DNS resolver.
{{ .Name | color "green" "bold" }} {{"-q mrkaran.dev -t MX -n 1.1.1.1" | color "yellow" ""}} Using named arguments.
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev --aa --ad" | color "cyan" "" }} Query with Authoritative Answer and Authenticated Data flags set.
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev --cd --do" | color "cyan" "" }} Query with Checking Disabled and DNSSEC OK flags set.
{{ "Free Form Arguments" | color "" "heading" }}:
{{- range $example := .Examples }}
{{ $.Name | color "green" "bold" }} {{ $example.Command | color "cyan" "" }}{{ printf "%-4s" "" }}{{ $example.Description }}
{{- end }}
{{ "FREE FORM ARGUMENTS" | color "" "heading" }}:
Supply hostnames, query types, and classes without flags. Example:
{{ .Name | color "green" "bold" }} {{"mrkaran.dev A @1.1.1.1" | color "cyan" "" }}
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev A @1.1.1.1" | color "cyan" "" }}
{{ "Transport Options" | color "" "heading" }}:
{{ "TRANSPORT OPTIONS" | color "" "heading" }}:
Specify the protocol with a URL-type scheme.
UDP is used if no scheme is specified.
{{"@udp://" | color "yellow" ""}} eg: @1.1.1.1 initiates a {{"UDP" | color "cyan" ""}} query to 1.1.1.1:53.
{{"@tcp://" | color "yellow" ""}} eg: @tcp://1.1.1.1 initiates a {{"TCP" | color "cyan" ""}} query to 1.1.1.1:53.
{{"@https://" | color "yellow" ""}} eg: @https://cloudflare-dns.com/dns-query initiates a {{"DOH" | color "cyan" ""}} query to Cloudflare via DoH.
{{"@tls://" | color "yellow" ""}} eg: @tls://1.1.1.1 initiates a {{"DoT" | color "cyan" ""}} query to 1.1.1.1:853.
{{"@sdns://" | color "yellow" ""}} initiates a {{"DNSCrypt" | color "cyan" ""}} or {{"DoH" | color "cyan" ""}} query using a DNS stamp.
{{"@quic://" | color "yellow" ""}} initiates a {{"DOQ" | color "cyan" ""}} query.
{{ "Query Options" | color "" "heading" }}:
{{"-q, --query=HOSTNAME" | color "yellow" ""}} Hostname to query the DNS records for (eg {{"mrkaran.dev" | color "cyan" ""}}).
{{"-t, --type=TYPE" | color "yellow" ""}} Type of the DNS Record ({{"A, MX, NS" | color "cyan" ""}} etc).
{{"-n, --nameserver=ADDR" | color "yellow" ""}} Address of a specific nameserver to send queries to ({{"9.9.9.9, 8.8.8.8" | color "cyan" ""}} etc).
{{"-c, --class=CLASS" | color "yellow" ""}} Network class of the DNS record ({{"IN, CH, HS" | color "cyan" ""}} etc).
{{"-x, --reverse" | color "yellow" ""}} Performs a DNS Lookup for an IPv4 or IPv6 address. Sets the query type and class to PTR and IN respectively.
{{ "Resolver Options" | color "" "heading" }}:
{{"--strategy=STRATEGY" | color "yellow" ""}} Specify strategy to query nameserver listed in etc/resolv.conf. ({{"all, random, first" | color "cyan" ""}}).
{{"--ndots=INT" | color "yellow" ""}} Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise.
{{"--search" | color "yellow" ""}} Use the search list defined in resolv.conf. Defaults to true. Set --search=false to disable search list.
{{"--timeout" | color "yellow" ""}} Specify timeout (in seconds) for the resolver to return a response.
{{"-4 --ipv4" | color "yellow" ""}} Use IPv4 only.
{{"-6 --ipv6" | color "yellow" ""}} Use IPv6 only.
{{"--ndots=INT" | color "yellow" ""}} Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise.
{{"--tls-hostname=HOSTNAME" | color "yellow" ""}} Provide a hostname for doing verification of the certificate if the provided DoT nameserver is an IP.
{{"--skip-hostname-verification" | color "yellow" ""}} Skip TLS Hostname Verification in case of DOT Lookups.
{{ "Query Flags" | color "" "heading" }}:
{{"--aa" | color "yellow" ""}} Set Authoritative Answer flag.
{{"--ad" | color "yellow" ""}} Set Authenticated Data flag.
{{"--cd" | color "yellow" ""}} Set Checking Disabled flag.
{{"--rd" | color "yellow" ""}} Set Recursion Desired flag (default: true).
{{"--z" | color "yellow" ""}} Set Z flag (reserved for future use).
{{"--do" | color "yellow" ""}} Set DNSSEC OK flag.
{{ "Output Options" | color "" "heading" }}:
{{"-J, --json " | color "yellow" ""}} Format the output as JSON.
{{"--short" | color "yellow" ""}} Short output format. Shows only the response section.
{{"--color " | color "yellow" ""}} Defaults to true. Set --color=false to disable colored output.
{{"--debug " | color "yellow" ""}} Enable debug logging.
{{"--time" | color "yellow" ""}} Shows how long the response took from the server.
{{- range $opt := .TransportOptions }}
{{ printf "%-12s" $opt.Scheme | color "yellow" "" }}{{ printf "%-68s" $opt.Example }}{{ $opt.Description | color "cyan" "" }}
{{- end }}
{{ "QUERY OPTIONS" | color "" "heading" }}:
{{- range $opt := .QueryOptions }}
{{ printf "%-30s" $opt.Flag | color "yellow" "" }}{{ $opt.Description }}
{{- end }}
{{ "RESOLVER OPTIONS" | color "" "heading" }}:
{{- range $opt := .ResolverOptions }}
{{ printf "%-30s" $opt.Flag | color "yellow" "" }}{{ $opt.Description }}
{{- end }}
{{ "QUERY FLAGS" | color "" "heading" }}:
{{- range $flag := .QueryFlags }}
{{ printf "%-30s" $flag.Flag | color "yellow" "" }}{{ $flag.Description }}
{{- end }}
{{ "OUTPUT OPTIONS" | color "" "heading" }}:
{{- range $opt := .OutputOptions }}
{{ printf "%-30s" $opt.Flag | color "yellow" "" }}{{ $opt.Description }}
{{- end }}
`

func renderCustomHelp() {
helpTmplVars := map[string]string{
type Option struct {
Flag string
Description string
}

type Example struct {
Command string
Description string
}

type TransportOption struct {
Scheme string
Example string
Description string
}

helpTmplVars := map[string]interface{}{
"Name": "doggo",
"Description": "DNS Client for Humans",
"Version": buildVersion,
"Date": buildDate,
"Examples": []Example{
{"mrkaran.dev", "Query a domain using defaults."},
{"mrkaran.dev CNAME", "Query for a CNAME record."},
{"mrkaran.dev MX @9.9.9.9", "Uses a custom DNS resolver."},
{"-q mrkaran.dev -t MX -n 1.1.1.1", "Using named arguments."},
{"mrkaran.dev --aa --ad", "Query with Authoritative Answer and Authenticated Data flags set."},
{"mrkaran.dev --cd --do", "Query with Checking Disabled and DNSSEC OK flags set."},
},
"TransportOptions": []TransportOption{
{"@udp://", "eg: @1.1.1.1", "initiates a UDP query to 1.1.1.1:53."},
{"@tcp://", "eg: @tcp://1.1.1.1", "initiates a TCP query to 1.1.1.1:53."},
{"@https://", "eg: @https://cloudflare-dns.com/dns-query", "initiates a DOH query to Cloudflare via DoH."},
{"@tls://", "eg: @tls://1.1.1.1", "initiates a DoT query to 1.1.1.1:853."},
{"@sdns://", "initiates a DNSCrypt or DoH query using a DNS stamp.", ""},
{"@quic://", "initiates a DOQ query.", ""},
},
"QueryOptions": []Option{
{"-q, --query=HOSTNAME", "Hostname to query the DNS records for (eg mrkaran.dev)."},
{"-t, --type=TYPE", "Type of the DNS Record (A, MX, NS etc)."},
{"-n, --nameserver=ADDR", "Address of a specific nameserver to send queries to (9.9.9.9, 8.8.8.8 etc)."},
{"-c, --class=CLASS", "Network class of the DNS record (IN, CH, HS etc)."},
{"-x, --reverse", "Performs a DNS Lookup for an IPv4 or IPv6 address. Sets the query type and class to PTR and IN respectively."},
},
"ResolverOptions": []Option{
{"--strategy=STRATEGY", "Specify strategy to query nameserver listed in etc/resolv.conf. (all, random, first)."},
{"--ndots=INT", "Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise."},
{"--search", "Use the search list defined in resolv.conf. Defaults to true. Set --search=false to disable search list."},
{"--timeout", "Specify timeout (in seconds) for the resolver to return a response."},
{"-4 --ipv4", "Use IPv4 only."},
{"-6 --ipv6", "Use IPv6 only."},
{"--tls-hostname=HOSTNAME", "Provide a hostname for verification of the certificate if the provided DoT nameserver is an IP."},
{"--skip-hostname-verification", "Skip TLS Hostname Verification in case of DOT Lookups."},
},
"QueryFlags": []Option{
{"--aa", "Set Authoritative Answer flag."},
{"--ad", "Set Authenticated Data flag."},
{"--cd", "Set Checking Disabled flag."},
{"--rd", "Set Recursion Desired flag (default: true)."},
{"--z", "Set Z flag (reserved for future use)."},
{"--do", "Set DNSSEC OK flag."},
},
"OutputOptions": []Option{
{"-J, --json", "Format the output as JSON."},
{"--short", "Short output format. Shows only the response section."},
{"--color", "Defaults to true. Set --color=false to disable colored output."},
{"--debug", "Enable debug logging."},
{"--time", "Shows how long the response took from the server."},
},
}
tmpl, err := template.New("test").Funcs(template.FuncMap{

tmpl, err := template.New("help").Funcs(template.FuncMap{
"color": func(clr string, format string, str string) string {
formatter := color.New()
switch c := clr; c {
switch clr {
case "yellow":
formatter = formatter.Add(color.FgYellow)
case "red":
Expand All @@ -95,7 +140,7 @@ func renderCustomHelp() {
case "green":
formatter = formatter.Add(color.FgGreen)
}
switch f := format; f {
switch format {
case "bold":
formatter = formatter.Add(color.Bold)
case "underline":
Expand All @@ -107,12 +152,10 @@ func renderCustomHelp() {
},
}).Parse(appHelpTextTemplate)
if err != nil {
// should ideally never happen.
panic(err)
}
err = tmpl.Execute(color.Output, helpTmplVars)
if err != nil {
// should ideally never happen.
panic(err)
}
os.Exit(0)
Expand Down

0 comments on commit 8f60428

Please sign in to comment.