Add config file and command alias config options.
This commit is contained in:
parent
38e0051308
commit
be2d9c3a84
1
Makefile
1
Makefile
@ -28,6 +28,7 @@ deps: check-cert
|
|||||||
go get -u github.com/spf13/cobra
|
go get -u github.com/spf13/cobra
|
||||||
go get -u golang.org/x/sys/unix
|
go get -u golang.org/x/sys/unix
|
||||||
go get -u github.com/davecheney/profile
|
go get -u github.com/davecheney/profile
|
||||||
|
go get -u gopkg.in/yaml.v2
|
||||||
|
|
||||||
build: deps
|
build: deps
|
||||||
go build $(FLAGS) github.com/derekparker/delve/cmd/dlv
|
go build $(FLAGS) github.com/derekparker/delve/cmd/dlv
|
||||||
|
|||||||
@ -12,10 +12,12 @@ import (
|
|||||||
|
|
||||||
sys "golang.org/x/sys/unix"
|
sys "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
"github.com/derekparker/delve/config"
|
||||||
"github.com/derekparker/delve/service"
|
"github.com/derekparker/delve/service"
|
||||||
"github.com/derekparker/delve/service/api"
|
"github.com/derekparker/delve/service/api"
|
||||||
"github.com/derekparker/delve/service/rpc"
|
"github.com/derekparker/delve/service/rpc"
|
||||||
"github.com/derekparker/delve/terminal"
|
"github.com/derekparker/delve/terminal"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,6 +30,9 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Config setup and load.
|
||||||
|
conf := config.LoadConfig()
|
||||||
|
|
||||||
// Main dlv root command.
|
// Main dlv root command.
|
||||||
rootCommand := &cobra.Command{
|
rootCommand := &cobra.Command{
|
||||||
Use: "dlv",
|
Use: "dlv",
|
||||||
@ -88,7 +93,7 @@ starts and attaches to it, and enables you to immediately begin debugging your p
|
|||||||
defer os.Remove(fp)
|
defer os.Remove(fp)
|
||||||
|
|
||||||
processArgs := append([]string{"./" + debugname}, args...)
|
processArgs := append([]string{"./" + debugname}, args...)
|
||||||
return execute(0, processArgs)
|
return execute(0, processArgs, conf)
|
||||||
}()
|
}()
|
||||||
os.Exit(status)
|
os.Exit(status)
|
||||||
},
|
},
|
||||||
@ -100,7 +105,7 @@ starts and attaches to it, and enables you to immediately begin debugging your p
|
|||||||
Use: "exec [./path/to/binary]",
|
Use: "exec [./path/to/binary]",
|
||||||
Short: "Runs precompiled binary, attaches and begins debug session.",
|
Short: "Runs precompiled binary, attaches and begins debug session.",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
os.Exit(execute(0, args))
|
os.Exit(execute(0, args, conf))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
rootCommand.AddCommand(execCommand)
|
rootCommand.AddCommand(execCommand)
|
||||||
@ -220,7 +225,7 @@ starts and attaches to it, and enable you to immediately begin debugging your pr
|
|||||||
defer os.Remove(debugname)
|
defer os.Remove(debugname)
|
||||||
processArgs := append([]string{debugname}, args...)
|
processArgs := append([]string{debugname}, args...)
|
||||||
|
|
||||||
return execute(0, processArgs)
|
return execute(0, processArgs, conf)
|
||||||
}()
|
}()
|
||||||
os.Exit(status)
|
os.Exit(status)
|
||||||
},
|
},
|
||||||
@ -238,7 +243,7 @@ starts and attaches to it, and enable you to immediately begin debugging your pr
|
|||||||
fmt.Fprintf(os.Stderr, "Invalid pid: %s\n", args[0])
|
fmt.Fprintf(os.Stderr, "Invalid pid: %s\n", args[0])
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
os.Exit(execute(pid, nil))
|
os.Exit(execute(pid, nil, conf))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
rootCommand.AddCommand(attachCommand)
|
rootCommand.AddCommand(attachCommand)
|
||||||
@ -258,7 +263,7 @@ starts and attaches to it, and enable you to immediately begin debugging your pr
|
|||||||
fmt.Fprintf(os.Stderr, "An empty address was provided. You must provide an address as the first argument.\n")
|
fmt.Fprintf(os.Stderr, "An empty address was provided. You must provide an address as the first argument.\n")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
os.Exit(connect(addr))
|
os.Exit(connect(addr, conf))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
rootCommand.AddCommand(connectCommand)
|
rootCommand.AddCommand(connectCommand)
|
||||||
@ -266,11 +271,11 @@ starts and attaches to it, and enable you to immediately begin debugging your pr
|
|||||||
rootCommand.Execute()
|
rootCommand.Execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
func connect(addr string) int {
|
func connect(addr string, conf *config.Config) int {
|
||||||
// Create and start a terminal - attach to running instance
|
// Create and start a terminal - attach to running instance
|
||||||
var client service.Client
|
var client service.Client
|
||||||
client = rpc.NewClient(addr)
|
client = rpc.NewClient(addr)
|
||||||
term := terminal.New(client)
|
term := terminal.New(client, conf)
|
||||||
err, status := term.Run()
|
err, status := term.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -278,7 +283,7 @@ func connect(addr string) int {
|
|||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
func execute(attachPid int, processArgs []string) int {
|
func execute(attachPid int, processArgs []string, conf *config.Config) int {
|
||||||
// Make a TCP listener
|
// Make a TCP listener
|
||||||
listener, err := net.Listen("tcp", Addr)
|
listener, err := net.Listen("tcp", Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -303,7 +308,7 @@ func execute(attachPid int, processArgs []string) int {
|
|||||||
// Create and start a terminal
|
// Create and start a terminal
|
||||||
var client service.Client
|
var client service.Client
|
||||||
client = rpc.NewClient(listener.Addr().String())
|
client = rpc.NewClient(listener.Addr().String())
|
||||||
term := terminal.New(client)
|
term := terminal.New(client, conf)
|
||||||
err, status = term.Run()
|
err, status = term.Run()
|
||||||
} else {
|
} else {
|
||||||
ch := make(chan os.Signal)
|
ch := make(chan os.Signal)
|
||||||
|
|||||||
112
config/config.go
Normal file
112
config/config.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
configDir string = ".dlv"
|
||||||
|
configFile string = "config.yml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config defines all configuration options available to be set through the config file.
|
||||||
|
type Config struct {
|
||||||
|
Aliases map[string][]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConfig attempts to populate a Config object from the config.yml file.
|
||||||
|
func LoadConfig() *Config {
|
||||||
|
err := createConfigPath()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Could not create config directory: %v.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fullConfigFile, err := GetConfigFilePath(configFile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unable to get config file path: %v.", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Open(fullConfigFile)
|
||||||
|
if err != nil {
|
||||||
|
createDefaultConfig(fullConfigFile)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err := f.Close()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Closing config file failed: %v.", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unable to read config data: %v.", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var c Config
|
||||||
|
err = yaml.Unmarshal(data, &c)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unable to decode config file: %v.", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDefaultConfig(path string) {
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unable to create config file: %v.", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err := f.Close()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Closing config file failed: %v.", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err = writeDefaultConfig(f)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unable to write default configuration: %v.", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeDefaultConfig(f *os.File) error {
|
||||||
|
_, err := f.WriteString(
|
||||||
|
`# Configuration file for the delve debugger.
|
||||||
|
|
||||||
|
# This is the default configuration file. Available options are provided, but disabled.
|
||||||
|
# Delete the leading hash mark to enable an item.
|
||||||
|
|
||||||
|
# Provided aliases will be added to the default aliases for a given command.
|
||||||
|
aliases:
|
||||||
|
# command: ["alias1", "alias2"]
|
||||||
|
`)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// createConfigPath creates the directory structure at which all config files are saved.
|
||||||
|
func createConfigPath() error {
|
||||||
|
path, err := GetConfigFilePath("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.MkdirAll(path, 0700)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfigFilePath gets the full path to the given config file name.
|
||||||
|
func GetConfigFilePath(file string) (string, error) {
|
||||||
|
usr, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return path.Join(usr.HomeDir, configDir, file), nil
|
||||||
|
}
|
||||||
@ -110,6 +110,15 @@ func (c *Commands) Find(cmdstr string) cmdfunc {
|
|||||||
return noCmdAvailable
|
return noCmdAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge takes aliases defined in the config struct and merges them with the default aliases.
|
||||||
|
func (c *Commands) Merge(allAliases map[string][]string) {
|
||||||
|
for i := range c.cmds {
|
||||||
|
if aliases, ok := allAliases[c.cmds[i].aliases[0]]; ok {
|
||||||
|
c.cmds[i].aliases = append(c.cmds[i].aliases, aliases...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func CommandFunc(fn func() error) cmdfunc {
|
func CommandFunc(fn func() error) cmdfunc {
|
||||||
return func(client service.Client, args ...string) error {
|
return func(client service.Client, args ...string) error {
|
||||||
return fn()
|
return fn()
|
||||||
|
|||||||
@ -5,41 +5,36 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"os/user"
|
|
||||||
"path"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/peterh/liner"
|
"github.com/peterh/liner"
|
||||||
sys "golang.org/x/sys/unix"
|
sys "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
"github.com/derekparker/delve/config"
|
||||||
"github.com/derekparker/delve/service"
|
"github.com/derekparker/delve/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
const configDir string = ".dlv"
|
|
||||||
const historyFile string = ".dbg_history"
|
const historyFile string = ".dbg_history"
|
||||||
|
|
||||||
type Term struct {
|
type Term struct {
|
||||||
client service.Client
|
client service.Client
|
||||||
prompt string
|
prompt string
|
||||||
line *liner.State
|
line *liner.State
|
||||||
|
conf *config.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(client service.Client) *Term {
|
func New(client service.Client, conf *config.Config) *Term {
|
||||||
return &Term{
|
return &Term{
|
||||||
prompt: "(dlv) ",
|
prompt: "(dlv) ",
|
||||||
line: liner.NewLiner(),
|
line: liner.NewLiner(),
|
||||||
client: client,
|
client: client,
|
||||||
|
conf: conf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Term) Run() (error, int) {
|
func (t *Term) Run() (error, int) {
|
||||||
defer t.line.Close()
|
defer t.line.Close()
|
||||||
|
|
||||||
err := createConfigPath()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Could not create config directory: %v.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the debugger a halt command on SIGINT
|
// Send the debugger a halt command on SIGINT
|
||||||
ch := make(chan os.Signal)
|
ch := make(chan os.Signal)
|
||||||
signal.Notify(ch, sys.SIGINT)
|
signal.Notify(ch, sys.SIGINT)
|
||||||
@ -53,7 +48,10 @@ func (t *Term) Run() (error, int) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
cmds := DebugCommands(t.client)
|
cmds := DebugCommands(t.client)
|
||||||
fullHistoryFile, err := getConfigFilePath(historyFile)
|
if t.conf != nil && t.conf.Aliases != nil {
|
||||||
|
cmds.Merge(t.conf.Aliases)
|
||||||
|
}
|
||||||
|
fullHistoryFile, err := config.GetConfigFilePath(historyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Unable to load history file: %v.", err)
|
fmt.Printf("Unable to load history file: %v.", err)
|
||||||
}
|
}
|
||||||
@ -117,7 +115,7 @@ func (t *Term) promptForInput() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Term) handleExit() (error, int) {
|
func (t *Term) handleExit() (error, int) {
|
||||||
fullHistoryFile, err := getConfigFilePath(historyFile)
|
fullHistoryFile, err := config.GetConfigFilePath(historyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error saving history file:", err)
|
fmt.Println("Error saving history file:", err)
|
||||||
} else {
|
} else {
|
||||||
@ -150,19 +148,3 @@ func parseCommand(cmdstr string) (string, []string) {
|
|||||||
vals := strings.Split(cmdstr, " ")
|
vals := strings.Split(cmdstr, " ")
|
||||||
return vals[0], vals[1:]
|
return vals[0], vals[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func createConfigPath() error {
|
|
||||||
path, err := getConfigFilePath("")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return os.MkdirAll(path, 0700)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getConfigFilePath(file string) (string, error) {
|
|
||||||
usr, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return path.Join(usr.HomeDir, configDir, file), nil
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user