Skip to content

Commit b861897

Browse files
committed
nvim/plugin: cleanup and optimize eval
name old time/op new time/op delta Eval-20 516ns ± 1% 491ns ± 1% -4.89% (p=0.008 n=5+5) name old alloc/op new alloc/op delta Eval-20 136B ± 0% 112B ± 0% -17.65% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Eval-20 9.00 ± 0% 8.00 ± 0% -11.11% (p=0.008 n=5+5) Signed-off-by: Koichi Shiraishi <[email protected]>
1 parent 8906321 commit b861897

File tree

1 file changed

+50
-27
lines changed

1 file changed

+50
-27
lines changed

nvim/plugin/plugin.go

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,13 @@ func (spec *pluginSpec) path() string {
4747
if i := strings.Index(spec.sm, ":"); i > 0 {
4848
return spec.sm[:i]
4949
}
50+
5051
return ""
5152
}
5253

5354
func isSync(f interface{}) bool {
5455
t := reflect.TypeOf(f)
56+
5557
return t.Kind() == reflect.Func && t.NumOut() > 0
5658
}
5759

@@ -60,6 +62,7 @@ func (p *Plugin) handle(fn interface{}, spec *pluginSpec) {
6062
if p.Nvim == nil {
6163
return
6264
}
65+
6366
if err := p.Nvim.RegisterHandler(spec.sm, fn); err != nil {
6467
panic(err)
6568
}
@@ -82,6 +85,7 @@ func (p *Plugin) Handle(method string, fn interface{}) {
8285
if p.Nvim == nil {
8386
return
8487
}
88+
8589
if err := p.Nvim.RegisterHandler(method, fn); err != nil {
8690
panic(err)
8791
}
@@ -124,9 +128,11 @@ type FunctionOptions struct {
124128
// {'GOPATH': $GOPATH, Cwd: getcwd()}
125129
func (p *Plugin) HandleFunction(options *FunctionOptions, fn interface{}) {
126130
m := make(map[string]string)
131+
127132
if options.Eval != "" {
128-
m[`eval`] = eval(options.Eval, fn)
133+
m["eval"] = eval(options.Eval, fn)
129134
}
135+
130136
p.handle(fn, &pluginSpec{
131137
sm: `0:function:` + options.Name,
132138
Type: `function`,
@@ -231,12 +237,13 @@ func (p *Plugin) HandleCommand(options *CommandOptions, fn interface{}) {
231237
m[`nargs`] = options.NArgs
232238
}
233239

234-
if options.Range != "" {
235-
if options.Range == `.` {
236-
options.Range = ""
237-
}
240+
switch {
241+
case options.Range == `.`:
242+
options.Range = ""
243+
fallthrough
244+
case options.Range != "":
238245
m[`range`] = options.Range
239-
} else if options.Count != "" {
246+
case options.Count != "":
240247
m[`count`] = options.Count
241248
}
242249

@@ -308,20 +315,26 @@ type AutocmdOptions struct {
308315
// documentation for information on how the expression is generated.
309316
func (p *Plugin) HandleAutocmd(options *AutocmdOptions, fn interface{}) {
310317
pattern := ""
318+
311319
m := make(map[string]string)
320+
312321
if options.Group != "" {
313322
m[`group`] = options.Group
314323
}
324+
315325
if options.Pattern != "" {
316326
m[`pattern`] = options.Pattern
317327
pattern = options.Pattern
318328
}
329+
319330
if options.Nested {
320-
m[`nested`] = "1"
331+
m[`nested`] = `1`
321332
}
333+
322334
if options.Once {
323-
m[`once`] = "1"
335+
m[`once`] = `1`
324336
}
337+
325338
if options.Eval != "" {
326339
m[`eval`] = eval(options.Eval, fn)
327340
}
@@ -330,6 +343,7 @@ func (p *Plugin) HandleAutocmd(options *AutocmdOptions, fn interface{}) {
330343
ep := options.Event + ":" + pattern
331344
i := p.eventPathCounts[ep]
332345
p.eventPathCounts[ep] = i + 1
346+
333347
sm := fmt.Sprintf(`%d:autocmd:%s`, i, ep)
334348

335349
p.handle(fn, &pluginSpec{
@@ -348,6 +362,7 @@ func (p *Plugin) RegisterForTests() error {
348362
for _, spec := range p.pluginSpecs {
349363
specs[spec.path()] = append(specs[spec.path()], spec)
350364
}
365+
351366
const host = "nvim-go-test"
352367
for path, specs := range specs {
353368
if err := p.Nvim.Call(`remote#host#RegisterPlugin`, nil, host, path, specs); err != nil {
@@ -363,20 +378,26 @@ func eval(eval string, f interface{}) string {
363378
if eval != `*` {
364379
return eval
365380
}
381+
366382
ft := reflect.TypeOf(f)
367383
if ft.Kind() != reflect.Func || ft.NumIn() < 1 {
368384
panic(`Eval: "*" option requires function with at least one argument`)
369385
}
386+
370387
argt := ft.In(ft.NumIn() - 1)
371388
if argt.Kind() != reflect.Ptr || argt.Elem().Kind() != reflect.Struct {
372389
panic(`Eval: "*" option requires function with pointer to struct as last argument`)
373390
}
391+
374392
return structEval(argt.Elem())
375393
}
376394

377395
func structEval(t reflect.Type) string {
378-
buf := []byte{'{'}
396+
var sb strings.Builder
397+
398+
sb.WriteByte('{')
379399
sep := ""
400+
380401
for i := 0; i < t.NumField(); i++ {
381402
sf := t.Field(i)
382403
if sf.Anonymous {
@@ -389,11 +410,11 @@ func structEval(t reflect.Type) string {
389410
if ft.Kind() == reflect.Ptr {
390411
ft = ft.Elem()
391412
}
413+
392414
if ft.Kind() == reflect.Struct {
393415
eval = structEval(ft)
394416
}
395417
}
396-
397418
if eval == "" {
398419
continue
399420
}
@@ -403,15 +424,16 @@ func structEval(t reflect.Type) string {
403424
name = sf.Name
404425
}
405426

406-
buf = append(buf, sep...)
407-
buf = append(buf, `'`...)
408-
buf = append(buf, name...)
409-
buf = append(buf, `':`...)
410-
buf = append(buf, eval...)
411-
sep = `, `
427+
sb.WriteString(sep)
428+
sb.WriteByte('\'')
429+
sb.WriteString(name)
430+
sb.WriteString("': ")
431+
sb.WriteString(eval)
432+
sep = ", "
412433
}
413-
buf = append(buf, '}')
414-
return string(buf)
434+
sb.WriteByte('}')
435+
436+
return sb.String()
415437
}
416438

417439
type byServiceMethod []*pluginSpec
@@ -432,18 +454,18 @@ func (p *Plugin) Manifest(host string) []byte {
432454
path := spec.path()
433455
if path != prevPath {
434456
if prevPath != "" {
435-
fmt.Fprintf(&buf, `\\ )`)
457+
fmt.Fprintf(&buf, "\\ )")
436458
}
437-
fmt.Fprintf(&buf, `call remote#host#RegisterPlugin('%s', '%s', [\n`, host, path)
459+
fmt.Fprintf(&buf, "call remote#host#RegisterPlugin('%s', '%s', [\n", host, path)
438460
prevPath = path
439461
}
440462

441-
sync := `0`
463+
sync := "0"
442464
if spec.Sync {
443-
sync = `1`
465+
sync = "1"
444466
}
445467

446-
fmt.Fprintf(&buf, `\\ {'type': '%s', 'name': '%s', 'sync': %s, 'opts': {`, spec.Type, spec.Name, sync)
468+
fmt.Fprintf(&buf, "\\ {'type': '%s', 'name': '%s', 'sync': %s, 'opts': {", spec.Type, spec.Name, sync)
447469

448470
var keys []string
449471
for k := range spec.Opts {
@@ -453,14 +475,15 @@ func (p *Plugin) Manifest(host string) []byte {
453475

454476
optDelim := ""
455477
for _, k := range keys {
456-
fmt.Fprintf(&buf, `%s'%s': '%s'`, optDelim, k, escape(spec.Opts[k]))
457-
optDelim = `,`
478+
fmt.Fprintf(&buf, "%s'%s': '%s'", optDelim, k, escape(spec.Opts[k]))
479+
optDelim = ","
458480
}
459481

460-
fmt.Fprintf(&buf, `}},\n`)
482+
fmt.Fprintf(&buf, "}},\n")
461483
}
462484
if prevPath != "" {
463-
fmt.Fprintf(&buf, `\\ ])\n`)
485+
fmt.Fprintf(&buf, "\\ ])\n")
464486
}
487+
465488
return buf.Bytes()
466489
}

0 commit comments

Comments
 (0)