From b5b6c26a0086c3a3a556d9b4012e17b3d65cdc7a Mon Sep 17 00:00:00 2001 From: nsf Date: Sat, 30 Dec 2017 15:26:55 +0500 Subject: [PATCH] Add "ignore-case" and "partials" config options. Also add new command "gocode options" which prints config options in an extended form (unlike "gocode set"). --- README.md | 14 +++++++++- autocompletecontext.go | 16 +++++++++-- client.go | 6 ++++ config.go | 62 +++++++++++++++++++++++++++++++++++++++++- gocode.go | 6 ++-- rpc.go | 24 ++++++++++++++++ server.go | 4 +++ 7 files changed, 126 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 11148c89..b36ea00d 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ You can change all available options using `gocode set` command. The config file - *propose-builtins* - A boolean option. If **true**, gocode will add built-in types, functions and constants to an autocompletion proposals. Default: **false**. + A boolean option. If **true**, gocode will add built-in types, functions and constants to autocompletion proposals. Default: **false**. - *lib-path* @@ -173,6 +173,18 @@ You can change all available options using `gocode set` command. The config file An integer option. If there have been no completion requests after this number of seconds, the gocode process will terminate. Defaults to 1800 (30 minutes). + - *unimported-packages* + + A boolean option. If set to true, gocode will try to import certain known packages automatically for identifiers which cannot be resolved otherwise. Currently only a limited set of standard library packages are supported. Default: **false**. + + - *partials* + + A boolean option. If set to false, gocode will not filter autocompletion results based on entered prefix before the cursor. Instead it will return all available autocompletion results viable for a given context. Whether this option is set to true or false, gocode will return a valid prefix length for output formats which support it. Setting this option to a non-default value may result in editor misbehaviour. Default: **true**. + + - *ignore-case* + + A boolean option. If set to true, gocode will perform case-insensitive matching when doing prefix-based filtering. Default: **false**. + ### Debugging If something went wrong, the first thing you may want to do is manually start the gocode daemon with a debug mode enabled and in a separate terminal window. It will show you all the stack traces, panics if any and additional info about autocompletion requests. Shutdown the daemon if it was already started and run a new one explicitly with a debug mode enabled: diff --git a/autocompletecontext.go b/autocompletecontext.go index d9f6a6ac..db243bcd 100644 --- a/autocompletecontext.go +++ b/autocompletecontext.go @@ -6,6 +6,7 @@ import ( "go/ast" "go/parser" "go/token" + "log" "os" "path/filepath" "runtime" @@ -361,9 +362,21 @@ func (c *auto_complete_context) apropos(file []byte, filename string, cursor int // And we're ready to Go. ;) b := new_out_buffers(c) + if g_config.IgnoreCase { + if *g_debug { + log.Printf("ignoring case sensitivity") + } + b.ignorecase = true + } - partial := 0 cc, ok := c.deduce_cursor_context(file, cursor) + partial := len(cc.partial) + if !g_config.Partials { + if *g_debug { + log.Printf("not performing partial prefix matching") + } + cc.partial = "" + } if !ok { var d *decl if ident, ok := cc.expr.(*ast.Ident); ok && g_config.UnimportedPackages { @@ -415,7 +428,6 @@ func (c *auto_complete_context) apropos(file []byte, filename string, cursor int c.get_candidates_from_decl(cc, class, b) } } - partial = len(cc.partial) if len(b.candidates) == 0 { return nil, 0 diff --git a/client.go b/client.go index b16f82c2..3174a2d1 100644 --- a/client.go +++ b/client.go @@ -50,6 +50,8 @@ func do_client() int { cmd_drop_cache(client) case "set": cmd_set(client) + case "options": + cmd_options(client) default: fmt.Printf("unknown argument: %q, try running \"gocode -h\"\n", flag.Arg(0)) return 1 @@ -180,3 +182,7 @@ func cmd_set(c *rpc.Client) { fmt.Print(client_set(c, flag.Arg(1), flag.Arg(2))) } } + +func cmd_options(c *rpc.Client) { + fmt.Print(client_options(c, 0)) +} diff --git a/config.go b/config.go index 01b198fb..96d2fb6f 100644 --- a/config.go +++ b/config.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "os" "reflect" + "regexp" "strconv" ) @@ -28,9 +29,25 @@ type config struct { PackageLookupMode string `json:"package-lookup-mode"` CloseTimeout int `json:"close-timeout"` UnimportedPackages bool `json:"unimported-packages"` + Partials bool `json:"partials"` + IgnoreCase bool `json:"ignore-case"` } -var g_config = config{ +var g_config_desc = map[string]string{ + "propose-builtins": "If set to {true}, gocode will add built-in types, functions and constants to autocompletion proposals.", + "lib-path": "A string option. Allows you to add search paths for packages. By default, gocode only searches {$GOPATH/pkg/$GOOS_$GOARCH} and {$GOROOT/pkg/$GOOS_$GOARCH} in terms of previously existed environment variables. Also you can specify multiple paths using ':' (colon) as a separator (on Windows use semicolon ';'). The paths specified by {lib-path} are prepended to the default ones.", + "custom-pkg-prefix": "", + "custom-vendor-dir": "", + "autobuild": "If set to {true}, gocode will try to automatically build out-of-date packages when their source files are modified, in order to obtain the freshest autocomplete results for them. This feature is experimental.", + "force-debug-output": "If is not empty, gocode will forcefully redirect the logging into that file. Also forces enabling of the debug mode on the server side.", + "package-lookup-mode": "If set to {go}, use standard Go package lookup rules. If set to {gb}, use gb-specific lookup rules. See {https://github.com/constabulary/gb} for details.", + "close-timeout": "If there have been no completion requests after this number of seconds, the gocode process will terminate. Default is 30 minutes.", + "unimported-packages": "If set to {true}, gocode will try to import certain known packages automatically for identifiers which cannot be resolved otherwise. Currently only a limited set of standard library packages is supported.", + "partials": "If set to {false}, gocode will not filter autocompletion results based on entered prefix before the cursor. Instead it will return all available autocompletion results viable for a given context. Whether this option is set to {true} or {false}, gocode will return a valid prefix length for output formats which support it. Setting this option to a non-default value may result in editor misbehaviour.", + "ignore-case": "If set to {true}, gocode will perform case-insensitive matching when doing prefix-based filtering.", +} + +var g_default_config = config{ ProposeBuiltins: false, LibPath: "", CustomPkgPrefix: "", @@ -39,7 +56,10 @@ var g_config = config{ PackageLookupMode: "go", CloseTimeout: 1800, UnimportedPackages: false, + Partials: true, + IgnoreCase: false, } +var g_config = g_default_config var g_string_to_bool = map[string]bool{ "t": true, @@ -175,3 +195,43 @@ func (this *config) read() error { return nil } + +func quoted(v interface{}) string { + switch v.(type) { + case string: + return fmt.Sprintf("%q", v) + case int: + return fmt.Sprint(v) + case bool: + return fmt.Sprint(v) + default: + panic("unreachable") + } +} + +var descRE = regexp.MustCompile(`{[^}]+}`) + +func preprocess_desc(v string) string { + return descRE.ReplaceAllStringFunc(v, func(v string) string { + return color_cyan + v[1:len(v)-1] + color_none + }) +} + +func (this *config) options() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "%sConfig file location%s: %s\n", color_white_bold, color_none, config_file()) + dv := reflect.ValueOf(g_default_config) + v, t := this.value_and_type() + for i, n := 0, t.NumField(); i < n; i++ { + f := t.Field(i) + index := f.Index + tag := f.Tag.Get("json") + fmt.Fprintf(&buf, "\n%s%s%s\n", color_yellow_bold, tag, color_none) + fmt.Fprintf(&buf, "%stype%s: %s\n", color_yellow, color_none, f.Type) + fmt.Fprintf(&buf, "%svalue%s: %s\n", color_yellow, color_none, quoted(v.FieldByIndex(index).Interface())) + fmt.Fprintf(&buf, "%sdefault%s: %s\n", color_yellow, color_none, quoted(dv.FieldByIndex(index).Interface())) + fmt.Fprintf(&buf, "%sdescription%s: %s\n", color_yellow, color_none, preprocess_desc(g_config_desc[tag])) + } + + return buf.String() +} diff --git a/gocode.go b/gocode.go index 19bf3346..b0dd5a27 100644 --- a/gocode.go +++ b/gocode.go @@ -40,9 +40,11 @@ func show_usage() { "\nCommands:\n"+ " autocomplete [] main autocompletion command\n"+ " close close the gocode daemon\n"+ - " status gocode daemon status report\n"+ " drop-cache drop gocode daemon's cache\n"+ - " set [ []] list or set config options\n") + " options list config options (extended)\n"+ + " set [ []] list or set config options\n"+ + " status gocode daemon status report\n"+ + "") } func main() { diff --git a/rpc.go b/rpc.go index 9955f4db..b1e0ea7a 100644 --- a/rpc.go +++ b/rpc.go @@ -136,3 +136,27 @@ func client_set(cli *rpc.Client, Arg0, Arg1 string) string { } return reply.Arg0 } + +// wrapper for: server_options + +type Args_options struct { + Arg0 int +} +type Reply_options struct { + Arg0 string +} + +func (r *RPC) RPC_options(args *Args_options, reply *Reply_options) error { + reply.Arg0 = server_options(args.Arg0) + return nil +} +func client_options(cli *rpc.Client, Arg0 int) string { + var args Args_options + var reply Reply_options + args.Arg0 = Arg0 + err := cli.Call("RPC.RPC_options", &args, &reply) + if err != nil { + panic(err) + } + return reply.Arg0 +} diff --git a/server.go b/server.go index 564fa28d..82813df6 100644 --- a/server.go +++ b/server.go @@ -241,3 +241,7 @@ func server_set(key, value string) string { g_daemon.drop_cache() return g_config.set_option(key, value) } + +func server_options(notused int) string { + return g_config.options() +}