提交 be2d9c3a 编写于 作者: T Tyler Bunnell 提交者: Derek Parker

Add config file and command alias config options.

上级 38e00513
......@@ -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)
......
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
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册