added autocompletion to console

This commit is contained in:
Bas van Kervel 2015-06-10 17:51:23 +02:00
parent 88a0ba0895
commit eccf1f76b3
5 changed files with 171 additions and 5 deletions

View file

@ -28,6 +28,8 @@ import (
"encoding/json" "encoding/json"
"sort"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common/docserver" "github.com/ethereum/go-ethereum/common/docserver"
re "github.com/ethereum/go-ethereum/jsre" re "github.com/ethereum/go-ethereum/jsre"
@ -73,6 +75,54 @@ type jsre struct {
prompter prompter
} }
var (
loadedModulesMethods map[string][]string
)
func loadAutoCompletion(js *jsre, ipcpath string) {
modules, err := js.suportedApis(ipcpath)
if err != nil {
utils.Fatalf("Unable to determine supported modules - %v", err)
}
fmt.Printf("load autocompletion %v", modules)
loadedModulesMethods = make(map[string][]string)
for module, _ := range modules {
loadedModulesMethods[module] = api.AutoCompletion[module]
}
}
func apiWordCompleter(line string) []string {
results := make([]string, 0)
if strings.Contains(line, ".") {
elements := strings.Split(line, ".")
if len(elements) == 2 {
module := elements[0]
partialMethod := elements[1]
if methods, found := loadedModulesMethods[module]; found {
for _, method := range methods {
if strings.HasPrefix(method, partialMethod) { // e.g. debug.se
results = append(results, module+"."+method)
}
}
}
}
} else {
for module, methods := range loadedModulesMethods {
if line == module { // user typed in full module name, show all methods
for _, method := range methods {
results = append(results, module+"."+method)
}
} else if strings.HasPrefix(module, line) { // partial method name, e.g. admi
results = append(results, module)
}
}
}
return results
}
func newJSRE(libPath, ipcpath string) *jsre { func newJSRE(libPath, ipcpath string) *jsre {
js := &jsre{ps1: "> "} js := &jsre{ps1: "> "}
js.wait = make(chan *big.Int) js.wait = make(chan *big.Int)
@ -87,6 +137,9 @@ func newJSRE(libPath, ipcpath string) *jsre {
lr := liner.NewLiner() lr := liner.NewLiner()
js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) }) js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
lr.SetCtrlCAborts(true) lr.SetCtrlCAborts(true)
loadAutoCompletion(js, ipcpath)
lr.SetCompleter(apiWordCompleter)
lr.SetTabCompletionStyle(liner.TabPrints)
js.prompter = lr js.prompter = lr
js.atexit = func() { js.atexit = func() {
js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) }) js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
@ -242,11 +295,13 @@ func (self *jsre) welcome(ipcpath string) {
+ " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`) + " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`)
if modules, err := self.suportedApis(ipcpath); err == nil { if modules, err := self.suportedApis(ipcpath); err == nil {
modulesVersionString := "" loadedModules := make([]string, 0)
for api, version := range modules { for api, version := range modules {
modulesVersionString += fmt.Sprintf("%s:%s ", api, version) loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version))
} }
self.re.Eval(fmt.Sprintf("var modules = '%s';", modulesVersionString)) sort.Strings(loadedModules)
self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(loadedModules, " ")))
self.re.Eval(`console.log(" modules: " + modules);`) self.re.Eval(`console.log(" modules: " + modules);`)
} }
} }

View file

@ -104,7 +104,7 @@ func (self *debugApi) DumpBlock(req *shared.Request) (interface{}, error) {
return nil, nil return nil, nil
} }
return stateDb.Dump(), nil return stateDb.RawDump(), nil
} }
func (self *debugApi) GetBlockRlp(req *shared.Request) (interface{}, error) { func (self *debugApi) GetBlockRlp(req *shared.Request) (interface{}, error) {

View file

@ -39,6 +39,13 @@ web3._extend({
params: 1, params: 1,
inputFormatter: [web3._extend.formatters.formatInputInt], inputFormatter: [web3._extend.formatters.formatInputInt],
outputFormatter: web3._extend.formatters.formatOutputString outputFormatter: web3._extend.formatters.formatOutputString
}) ,
new web3._extend.Method({
name: 'dumpBlock',
call: 'debug_dumpBlock',
params: 1,
inputFormatter: [web3._extend.formatters.formatInputInt],
outputFormatter: function(obj) { return obj; }
}) })
], ],
properties: properties:

View file

@ -23,7 +23,7 @@ web3._extend({
properties: properties:
[ [
new web3._extend.Property({ new web3._extend.Property({
name: 'accounts', name: 'listAccounts',
getter: 'personal_listAccounts', getter: 'personal_listAccounts',
outputFormatter: function(obj) { return obj; } outputFormatter: function(obj) { return obj; }
}) })

View file

@ -10,6 +10,110 @@ import (
"github.com/ethereum/go-ethereum/xeth" "github.com/ethereum/go-ethereum/xeth"
) )
var (
// Mapping between the different methods each api supports
AutoCompletion = map[string][]string{
"admin": []string{
"addPeer",
"peers",
"nodeInfo",
"exportChain",
"importChain",
"verbosity",
"chainSyncStatus",
"setSolc",
"datadir",
},
"debug": []string{
"dumpBlock",
"getBlockRlp",
"printBlock",
"processBlock",
"seedHash",
"setHead",
},
"eth": []string{
"accounts",
"blockNumber",
"getBalance",
"protocolVersion",
"coinbase",
"mining",
"gasPrice",
"getStorage",
"storageAt",
"getStorageAt",
"getTransactionCount",
"getBlockTransactionCountByHash",
"getBlockTransactionCountByNumber",
"getUncleCountByBlockHash",
"getUncleCountByBlockNumber",
"getData",
"getCode",
"sign",
"sendTransaction",
"transact",
"estimateGas",
"call",
"flush",
"getBlockByHash",
"getBlockByNumber",
"getTransactionByHash",
"getTransactionByBlockHashAndIndex",
"getUncleByBlockHashAndIndex",
"getUncleByBlockNumberAndIndex",
"getCompilers",
"compileSolidity",
"newFilter",
"newBlockFilter",
"newPendingTransactionFilter",
"uninstallFilter",
"getFilterChanges",
"getFilterLogs",
"getLogs",
"hashrate",
"getWork",
"submitWork",
},
"miner": []string{
"hashrate",
"makeDAG",
"setExtra",
"setGasPrice",
"startAutoDAG",
"start",
"stopAutoDAG",
"stop",
},
"net": []string{
"peerCount",
"listening",
},
"personal": []string{
"listAccounts",
"newAccount",
"deleteAccount",
"unlockAccount",
},
"shh": []string{
"version",
"post",
"hasIdentity",
"newIdentity",
"newFilter",
"uninstallFilter",
"getFilterChanges",
},
"txpool": []string{
"status",
},
"web3": []string{
"sha3",
"version",
},
}
)
// Parse a comma separated API string to individual api's // Parse a comma separated API string to individual api's
func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.Ethereum) ([]EthereumApi, error) { func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.Ethereum) ([]EthereumApi, error) {
if len(strings.TrimSpace(apistr)) == 0 { if len(strings.TrimSpace(apistr)) == 0 {