Replace hand-rolled cli interface with Cobra
This commit is contained in:
parent
40284111d4
commit
d75ac75195
202
cmd/dlv/main.go
202
cmd/dlv/main.go
@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
@ -15,115 +14,116 @@ import (
|
||||
"github.com/derekparker/delve/service"
|
||||
"github.com/derekparker/delve/service/rpc"
|
||||
"github.com/derekparker/delve/terminal"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const version string = "0.5.0.beta"
|
||||
|
||||
var usage string = `Delve version %s
|
||||
flags:
|
||||
%s
|
||||
Invoke with the path to a binary:
|
||||
dlv ./path/to/prog
|
||||
or use the following commands:
|
||||
run - Build, run, and attach to program
|
||||
test - Build test binary, run and attach to it
|
||||
attach - Attach to running process
|
||||
`
|
||||
|
||||
func init() {
|
||||
flag.Usage = help
|
||||
}
|
||||
var (
|
||||
Log bool
|
||||
Headless bool
|
||||
Addr string
|
||||
)
|
||||
|
||||
func main() {
|
||||
var printv, printhelp bool
|
||||
var addr string
|
||||
var logEnabled bool
|
||||
var headless bool
|
||||
|
||||
flag.BoolVar(&printv, "version", false, "Print version number and exit.")
|
||||
flag.StringVar(&addr, "addr", "localhost:0", "Debugging server listen address.")
|
||||
flag.BoolVar(&logEnabled, "log", false, "Enable debugging server logging.")
|
||||
flag.BoolVar(&headless, "headless", false, "Run in headless mode.")
|
||||
flag.Parse()
|
||||
|
||||
if flag.NFlag() == 0 && len(flag.Args()) == 0 {
|
||||
help()
|
||||
os.Exit(0)
|
||||
// Main dlv root command.
|
||||
rootCommand := &cobra.Command{
|
||||
Use: "dlv",
|
||||
Short: "Delve is a debugger for the Go programming language.",
|
||||
}
|
||||
rootCommand.Flags().StringVarP(&Addr, "listen", "l", "localhost:0", "Debugging server listen address.")
|
||||
rootCommand.Flags().BoolVarP(&Log, "log", "", false, "Enable debugging server logging.")
|
||||
rootCommand.Flags().BoolVarP(&Headless, "headless", "", false, "Run debug server only, in headless mode.")
|
||||
|
||||
if printv {
|
||||
fmt.Printf("Delve version: %s\n", version)
|
||||
os.Exit(0)
|
||||
// 'version' subcommand.
|
||||
versionCommand := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Prints version.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Delve version: " + version)
|
||||
},
|
||||
}
|
||||
rootCommand.AddCommand(versionCommand)
|
||||
|
||||
if printhelp {
|
||||
help()
|
||||
os.Exit(0)
|
||||
// 'run' subcommand.
|
||||
runCommand := &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "Compile and begin debugging program.",
|
||||
Long: `Compiles your program with optimizations disabled,
|
||||
starts and attaches to it, and enable you to immediately begin debugging your program.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
const debugname = "debug"
|
||||
goBuild := exec.Command("go", "build", "-o", debugname, "-gcflags", "-N -l")
|
||||
goBuild.Stderr = os.Stderr
|
||||
err := goBuild.Run()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
fp, err := filepath.Abs("./" + debugname)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
processArgs := append([]string{"./" + debugname}, args...)
|
||||
status := execute(0, processArgs)
|
||||
os.Remove(fp)
|
||||
os.Exit(status)
|
||||
},
|
||||
}
|
||||
rootCommand.AddCommand(runCommand)
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
// 'test' subcommand.
|
||||
testCommand := &cobra.Command{
|
||||
Use: "test",
|
||||
Short: "Compile test binary and begin debugging program.",
|
||||
Long: `Compiles a test binary with optimizations disabled,
|
||||
starts and attaches to it, and enable you to immediately begin debugging your program.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
base := filepath.Base(wd)
|
||||
goTest := exec.Command("go", "test", "-c", "-gcflags", "-N -l")
|
||||
goTest.Stderr = os.Stderr
|
||||
err = goTest.Run()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
debugname := "./" + base + ".test"
|
||||
processArgs := append([]string{debugname}, args...)
|
||||
|
||||
status := run(addr, logEnabled, headless)
|
||||
fmt.Println("[Hope I was of service hunting your bug!]")
|
||||
os.Exit(status)
|
||||
status := execute(0, processArgs)
|
||||
os.Remove(debugname)
|
||||
os.Exit(status)
|
||||
},
|
||||
}
|
||||
rootCommand.AddCommand(testCommand)
|
||||
|
||||
// 'attach' subcommand.
|
||||
attachCommand := &cobra.Command{
|
||||
Use: "attach [pid]",
|
||||
Short: "Attach to running process and begin debugging.",
|
||||
Long: "Attach to running process and begin debugging.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
pid, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Invalid pid: %d", args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(execute(pid, nil))
|
||||
},
|
||||
}
|
||||
rootCommand.AddCommand(attachCommand)
|
||||
|
||||
rootCommand.Execute()
|
||||
}
|
||||
|
||||
func run(addr string, logEnabled, headless bool) int {
|
||||
// Collect launch arguments
|
||||
var processArgs []string
|
||||
var attachPid int
|
||||
switch flag.Args()[0] {
|
||||
case "run":
|
||||
const debugname = "debug"
|
||||
cmd := exec.Command("go", "build", "-o", debugname, "-gcflags", "-N -l")
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Println("Could not compile program:", err)
|
||||
return 1
|
||||
}
|
||||
fp, err := filepath.Abs("./" + debugname)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return 1
|
||||
}
|
||||
defer os.Remove(fp)
|
||||
|
||||
processArgs = append([]string{"./" + debugname}, flag.Args()[1:]...)
|
||||
case "test":
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return 1
|
||||
}
|
||||
base := filepath.Base(wd)
|
||||
cmd := exec.Command("go", "test", "-c", "-gcflags", "-N -l")
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Errorf("Could not compile program: %s\n", err)
|
||||
return 1
|
||||
}
|
||||
debugname := "./" + base + ".test"
|
||||
defer os.Remove(debugname)
|
||||
|
||||
processArgs = append([]string{debugname}, flag.Args()[1:]...)
|
||||
case "attach":
|
||||
pid, err := strconv.Atoi(flag.Args()[1])
|
||||
if err != nil {
|
||||
fmt.Errorf("Invalid pid: %d", flag.Args()[1])
|
||||
return 1
|
||||
}
|
||||
attachPid = pid
|
||||
default:
|
||||
processArgs = flag.Args()
|
||||
}
|
||||
|
||||
func execute(attachPid int, processArgs []string) int {
|
||||
// Make a TCP listener
|
||||
listener, err := net.Listen("tcp", addr)
|
||||
listener, err := net.Listen("tcp", Addr)
|
||||
if err != nil {
|
||||
fmt.Printf("couldn't start listener: %s\n", err)
|
||||
return 1
|
||||
@ -136,14 +136,14 @@ func run(addr string, logEnabled, headless bool) int {
|
||||
Listener: listener,
|
||||
ProcessArgs: processArgs,
|
||||
AttachPid: attachPid,
|
||||
}, logEnabled)
|
||||
}, Log)
|
||||
if err := server.Run(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 1
|
||||
}
|
||||
|
||||
var status int
|
||||
if !headless {
|
||||
if !Headless {
|
||||
// Create and start a terminal
|
||||
var client service.Client
|
||||
client = rpc.NewClient(listener.Addr().String())
|
||||
@ -162,13 +162,3 @@ func run(addr string, logEnabled, headless bool) int {
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
// help prints help text to os.Stderr.
|
||||
func help() {
|
||||
flags := ""
|
||||
flag.VisitAll(func(f *flag.Flag) {
|
||||
doc := fmt.Sprintf(" -%s=%s: %s\n", f.Name, f.DefValue, f.Usage)
|
||||
flags += doc
|
||||
})
|
||||
fmt.Fprintf(os.Stderr, usage, version, flags)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user