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 golang.org/x/sys/unix
|
||||
go get -u github.com/davecheney/profile
|
||||
go get -u gopkg.in/yaml.v2
|
||||
|
||||
build: deps
|
||||
go build $(FLAGS) github.com/derekparker/delve/cmd/dlv
|
||||
|
||||
@ -12,10 +12,12 @@ import (
|
||||
|
||||
sys "golang.org/x/sys/unix"
|
||||
|
||||
"github.com/derekparker/delve/config"
|
||||
"github.com/derekparker/delve/service"
|
||||
"github.com/derekparker/delve/service/api"
|
||||
"github.com/derekparker/delve/service/rpc"
|
||||
"github.com/derekparker/delve/terminal"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -28,6 +30,9 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Config setup and load.
|
||||
conf := config.LoadConfig()
|
||||
|
||||
// Main dlv root command.
|
||||
rootCommand := &cobra.Command{
|
||||
Use: "dlv",
|
||||
@ -88,7 +93,7 @@ starts and attaches to it, and enables you to immediately begin debugging your p
|
||||
defer os.Remove(fp)
|
||||
|
||||
processArgs := append([]string{"./" + debugname}, args...)
|
||||
return execute(0, processArgs)
|
||||
return execute(0, processArgs, conf)
|
||||
}()
|
||||
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]",
|
||||
Short: "Runs precompiled binary, attaches and begins debug session.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
os.Exit(execute(0, args))
|
||||
os.Exit(execute(0, args, conf))
|
||||
},
|
||||
}
|
||||
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)
|
||||
processArgs := append([]string{debugname}, args...)
|
||||
|
||||
return execute(0, processArgs)
|
||||
return execute(0, processArgs, conf)
|
||||
}()
|
||||
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])
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(execute(pid, nil))
|
||||
os.Exit(execute(pid, nil, conf))
|
||||
},
|
||||
}
|
||||
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")
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(connect(addr))
|
||||
os.Exit(connect(addr, conf))
|
||||
},
|
||||
}
|
||||
rootCommand.AddCommand(connectCommand)
|
||||
@ -266,11 +271,11 @@ starts and attaches to it, and enable you to immediately begin debugging your pr
|
||||
rootCommand.Execute()
|
||||
}
|
||||
|
||||
func connect(addr string) int {
|
||||
func connect(addr string, conf *config.Config) int {
|
||||
// Create and start a terminal - attach to running instance
|
||||
var client service.Client
|
||||
client = rpc.NewClient(addr)
|
||||
term := terminal.New(client)
|
||||
term := terminal.New(client, conf)
|
||||
err, status := term.Run()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
@ -278,7 +283,7 @@ func connect(addr string) int {
|
||||
return status
|
||||
}
|
||||
|
||||
func execute(attachPid int, processArgs []string) int {
|
||||
func execute(attachPid int, processArgs []string, conf *config.Config) int {
|
||||
// Make a TCP listener
|
||||
listener, err := net.Listen("tcp", Addr)
|
||||
if err != nil {
|
||||
@ -303,7 +308,7 @@ func execute(attachPid int, processArgs []string) int {
|
||||
// Create and start a terminal
|
||||
var client service.Client
|
||||
client = rpc.NewClient(listener.Addr().String())
|
||||
term := terminal.New(client)
|
||||
term := terminal.New(client, conf)
|
||||
err, status = term.Run()
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return func(client service.Client, args ...string) error {
|
||||
return fn()
|
||||
|
||||
@ -5,41 +5,36 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"os/user"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/peterh/liner"
|
||||
sys "golang.org/x/sys/unix"
|
||||
|
||||
"github.com/derekparker/delve/config"
|
||||
"github.com/derekparker/delve/service"
|
||||
)
|
||||
|
||||
const configDir string = ".dlv"
|
||||
const historyFile string = ".dbg_history"
|
||||
|
||||
type Term struct {
|
||||
client service.Client
|
||||
prompt string
|
||||
line *liner.State
|
||||
conf *config.Config
|
||||
}
|
||||
|
||||
func New(client service.Client) *Term {
|
||||
func New(client service.Client, conf *config.Config) *Term {
|
||||
return &Term{
|
||||
prompt: "(dlv) ",
|
||||
line: liner.NewLiner(),
|
||||
client: client,
|
||||
conf: conf,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Term) Run() (error, int) {
|
||||
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
|
||||
ch := make(chan os.Signal)
|
||||
signal.Notify(ch, sys.SIGINT)
|
||||
@ -53,7 +48,10 @@ func (t *Term) Run() (error, int) {
|
||||
}()
|
||||
|
||||
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 {
|
||||
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) {
|
||||
fullHistoryFile, err := getConfigFilePath(historyFile)
|
||||
fullHistoryFile, err := config.GetConfigFilePath(historyFile)
|
||||
if err != nil {
|
||||
fmt.Println("Error saving history file:", err)
|
||||
} else {
|
||||
@ -150,19 +148,3 @@ func parseCommand(cmdstr string) (string, []string) {
|
||||
vals := strings.Split(cmdstr, " ")
|
||||
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