From 23ee30922433f3e199b1ea92b01552fca28e75cf Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Tue, 20 Jun 2023 08:02:04 +0900 Subject: [PATCH] nvim: support v0.9.1 APIs (#156) * github/workflows: update nvim version to v0.9.1 * nvim: add alias of Cmd to Dictionary * nvim: add deprecatedSince to some APIs and fix Exec args * nvim: go generate * nvim: support v0.9.1 APIs * nvim: go generate * nvim: fix Exec args on testcases * nvim: add HL testcase to testHighlight * nvim: add SetFocusUI testcase * nvim: add ColorByName testcase --------- Signed-off-by: Koichi Shiraishi --- .github/workflows/benchmark.yml | 2 +- .github/workflows/test.yml | 2 +- nvim/api.go | 98 +++++----- nvim/api_def.go | 39 +++- nvim/api_deprecated.go | 48 +++++ nvim/api_test.go | 323 ++++++++++++++------------------ nvim/api_tool.go | 10 +- nvim/plugin/plugin_test.go | 119 +++++++++--- 8 files changed, 378 insertions(+), 263 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index e36d0444..1dbdd6f3 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -34,7 +34,7 @@ jobs: uses: rhysd/action-setup-vim@v1 with: neovim: true - version: v0.8.3 + version: v0.9.1 - name: Run Benchmark run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ca369c3b..d86b9d69 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: - 1.19.x - 1.20.x neovim-version: - - v0.8.3 + - v0.9.1 - nightly fail-fast: false diff --git a/nvim/api.go b/nvim/api.go index 5b64d2fa..5d8e93f4 100644 --- a/nvim/api.go +++ b/nvim/api.go @@ -1832,9 +1832,9 @@ func (b *Batch) AllOptionsInfo(opinfo *OptionInfo) { // flaglist // // List of single char flags. -func (v *Nvim) OptionInfo(name string) (opinfo *OptionInfo, err error) { +func (v *Nvim) OptionInfo(name string, opts map[string]interface{}) (opinfo *OptionInfo, err error) { var result OptionInfo - err = v.call("nvim_get_option_info", &result, name) + err = v.call("nvim_get_option_info2", &result, name, opts) return &result, err } @@ -1889,8 +1889,8 @@ func (v *Nvim) OptionInfo(name string) (opinfo *OptionInfo, err error) { // flaglist // // List of single char flags. -func (b *Batch) OptionInfo(name string, opinfo *OptionInfo) { - b.call("nvim_get_option_info", opinfo, name) +func (b *Batch) OptionInfo(name string, opts map[string]interface{}, opinfo *OptionInfo) { + b.call("nvim_get_option_info2", opinfo, name, opts) } // SetOption sets an option value. @@ -1991,6 +1991,16 @@ func (b *Batch) AttachUI(width int, height int, options map[string]interface{}) b.call("nvim_ui_attach", nil, width, height, options) } +// SetFocusUI tells the nvim server if focus was gained or lost by the GUI. +func (v *Nvim) SetFocusUI(gained bool) error { + return v.call("nvim_ui_set_focus", nil, gained) +} + +// SetFocusUI tells the nvim server if focus was gained or lost by the GUI. +func (b *Batch) SetFocusUI(gained bool) { + b.call("nvim_ui_set_focus", nil, gained) +} + // DetachUI unregisters the client as a remote UI. func (v *Nvim) DetachUI() error { return v.call("nvim_ui_detach", nil) @@ -2088,8 +2098,8 @@ func (b *Batch) SetPumBounds(width float64, height float64, row float64, col flo // Unlike Command, this function supports heredocs, script-scope (s:), etc. // // When fails with VimL error, does not update "v:errmsg". -func (v *Nvim) Exec(src string, output bool) (out string, err error) { - err = v.call("nvim_exec", &out, src, output) +func (v *Nvim) Exec(src string, opts map[string]interface{}) (out map[string]interface{}, err error) { + err = v.call("nvim_exec2", &out, src, opts) return out, err } @@ -2098,8 +2108,8 @@ func (v *Nvim) Exec(src string, output bool) (out string, err error) { // Unlike Command, this function supports heredocs, script-scope (s:), etc. // // When fails with VimL error, does not update "v:errmsg". -func (b *Batch) Exec(src string, output bool, out *string) { - b.call("nvim_exec", out, src, output) +func (b *Batch) Exec(src string, opts map[string]interface{}, out *map[string]interface{}) { + b.call("nvim_exec2", out, src, opts) } // Command executes an ex-command. @@ -2127,28 +2137,52 @@ func (b *Batch) ParseExpression(expr string, flags string, highlight bool, expre b.call("nvim_parse_expression", expression, expr, flags, highlight) } -// HLByID gets a highlight definition by name. +// HL gets a highlight definition by name. +// +// nsID get highlight groups for namespace ns_id [Namespaces]. Use 0 to get global highlight groups |:highlight|. +// +// opts dict: +// +// name // -// hlID is the highlight id as returned by HLIDByName. +// Get a highlight definition by name. // -// rgb is the whether the export RGB colors. +// id +// +// Get a highlight definition by id. +// +// link +// +// Show linked group name instead of effective definition. // -// The returned highlight is the highlight definition. -func (v *Nvim) HLByID(hlID int, rgb bool) (highlight *HLAttrs, err error) { +// The returned HLAttrs highlight groups as a map from group name to a highlight definition map as in SetHighlight, or only a single highlight definition map if requested by name or id. +func (v *Nvim) HL(nsID int, opts map[string]interface{}) (highlight *HLAttrs, err error) { var result HLAttrs - err = v.call("nvim_get_hl_by_id", &result, hlID, rgb) + err = v.call("nvim_get_hl", &result, nsID, opts) return &result, err } -// HLByID gets a highlight definition by name. +// HL gets a highlight definition by name. +// +// nsID get highlight groups for namespace ns_id [Namespaces]. Use 0 to get global highlight groups |:highlight|. +// +// opts dict: +// +// name // -// hlID is the highlight id as returned by HLIDByName. +// Get a highlight definition by name. // -// rgb is the whether the export RGB colors. +// id +// +// Get a highlight definition by id. +// +// link +// +// Show linked group name instead of effective definition. // -// The returned highlight is the highlight definition. -func (b *Batch) HLByID(hlID int, rgb bool, highlight *HLAttrs) { - b.call("nvim_get_hl_by_id", highlight, hlID, rgb) +// The returned HLAttrs highlight groups as a map from group name to a highlight definition map as in SetHighlight, or only a single highlight definition map if requested by name or id. +func (b *Batch) HL(nsID int, opts map[string]interface{}, highlight *HLAttrs) { + b.call("nvim_get_hl", highlight, nsID, opts) } // HLIDByName gets a highlight group by name. @@ -2174,30 +2208,6 @@ func (b *Batch) HLIDByName(name string, hlID *int) { b.call("nvim_get_hl_id_by_name", hlID, name) } -// HLByName gets a highlight definition by id. -// -// name is Highlight group name. -// -// rgb is whether the export RGB colors. -// -// The returned highlight is the highlight definition. -func (v *Nvim) HLByName(name string, rgb bool) (highlight *HLAttrs, err error) { - var result HLAttrs - err = v.call("nvim_get_hl_by_name", &result, name, rgb) - return &result, err -} - -// HLByName gets a highlight definition by id. -// -// name is Highlight group name. -// -// rgb is whether the export RGB colors. -// -// The returned highlight is the highlight definition. -func (b *Batch) HLByName(name string, rgb bool, highlight *HLAttrs) { - b.call("nvim_get_hl_by_name", highlight, name, rgb) -} - // SetHighlight sets a highlight group. // // nsID is number of namespace for this highlight. diff --git a/nvim/api_def.go b/nvim/api_def.go index c64becaf..5e8b8452 100644 --- a/nvim/api_def.go +++ b/nvim/api_def.go @@ -951,8 +951,8 @@ func AllOptionsInfo() (opinfo OptionInfo) { // flaglist // // List of single char flags. -func OptionInfo(name string) (opinfo OptionInfo) { - name(nvim_get_option_info) +func OptionInfo(name string, opts map[string]interface{}) (opinfo OptionInfo) { + name(nvim_get_option_info2) returnPtr() } @@ -1007,6 +1007,11 @@ func AttachUI(width, height int, options map[string]interface{}) { name(nvim_ui_attach) } +// SetFocusUI tells the nvim server if focus was gained or lost by the GUI. +func SetFocusUI(gained bool) { + name(nvim_ui_set_focus) +} + // DetachUI unregisters the client as a remote UI. func DetachUI() { name(nvim_ui_detach) @@ -1060,8 +1065,8 @@ func SetPumBounds(width, height, row, col float64) { // Unlike Command, this function supports heredocs, script-scope (s:), etc. // // When fails with VimL error, does not update "v:errmsg". -func Exec(src string, output bool) (out string) { - name(nvim_exec) +func Exec(src string, opts map[string]interface{}) (out map[string]interface{}) { + name(nvim_exec2) } // Command executes an ex-command. @@ -1078,6 +1083,30 @@ func ParseExpression(expr, flags string, highlight bool) (expression map[string] // vim.c +// HL gets a highlight definition by name. +// +// nsID get highlight groups for namespace ns_id [Namespaces]. Use 0 to get global highlight groups |:highlight|. +// +// opts dict: +// +// name +// +// Get a highlight definition by name. +// +// id +// +// Get a highlight definition by id. +// +// link +// +// Show linked group name instead of effective definition. +// +// The returned HLAttrs highlight groups as a map from group name to a highlight definition map as in SetHighlight, or only a single highlight definition map if requested by name or id. +func HL(nsID int, opts map[string]interface{}) (highlight HLAttrs) { + name(nvim_get_hl) + returnPtr() +} + // HLByID gets a highlight definition by name. // // hlID is the highlight id as returned by HLIDByName. @@ -1088,6 +1117,7 @@ func ParseExpression(expr, flags string, highlight bool) (expression map[string] func HLByID(hlID int, rgb bool) (highlight HLAttrs) { name(nvim_get_hl_by_id) returnPtr() + deprecatedSince(9) } // HLIDByName gets a highlight group by name. @@ -1111,6 +1141,7 @@ func HLIDByName(name string) (hlID int) { func HLByName(name string, rgb bool) (highlight HLAttrs) { name(nvim_get_hl_by_name) returnPtr() + deprecatedSince(9) } // SetHighlight sets a highlight group. diff --git a/nvim/api_deprecated.go b/nvim/api_deprecated.go index 877af5a4..0d63ac76 100644 --- a/nvim/api_deprecated.go +++ b/nvim/api_deprecated.go @@ -162,6 +162,54 @@ func (b *Batch) SetBufferVirtualText(buffer Buffer, nsID int, line int, chunks [ b.call("nvim_buf_set_virtual_text", id, buffer, nsID, line, chunks, opts) } +// HLByID gets a highlight definition by name. +// +// hlID is the highlight id as returned by HLIDByName. +// +// rgb is the whether the export RGB colors. +// +// The returned highlight is the highlight definition. +func (v *Nvim) HLByID(hlID int, rgb bool) (highlight *HLAttrs, err error) { + var result HLAttrs + err = v.call("nvim_get_hl_by_id", &result, hlID, rgb) + return &result, err +} + +// HLByID gets a highlight definition by name. +// +// hlID is the highlight id as returned by HLIDByName. +// +// rgb is the whether the export RGB colors. +// +// The returned highlight is the highlight definition. +func (b *Batch) HLByID(hlID int, rgb bool, highlight *HLAttrs) { + b.call("nvim_get_hl_by_id", highlight, hlID, rgb) +} + +// HLByName gets a highlight definition by id. +// +// name is Highlight group name. +// +// rgb is whether the export RGB colors. +// +// The returned highlight is the highlight definition. +func (v *Nvim) HLByName(name string, rgb bool) (highlight *HLAttrs, err error) { + var result HLAttrs + err = v.call("nvim_get_hl_by_name", &result, name, rgb) + return &result, err +} + +// HLByName gets a highlight definition by id. +// +// name is Highlight group name. +// +// rgb is whether the export RGB colors. +// +// The returned highlight is the highlight definition. +func (b *Batch) HLByName(name string, rgb bool, highlight *HLAttrs) { + b.call("nvim_get_hl_by_name", highlight, name, rgb) +} + // CommandOutput executes a single ex command and returns the output. // // Deprecated: Use Exec instead. diff --git a/nvim/api_test.go b/nvim/api_test.go index d4dc731b..f366e506 100644 --- a/nvim/api_test.go +++ b/nvim/api_test.go @@ -2152,7 +2152,7 @@ func testCmd(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2177,7 +2177,7 @@ func testCmd(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2278,7 +2278,7 @@ func testCommand(v *Nvim) func(*testing.T) { name string command UserCommand opts map[string]interface{} - want string + want map[string]interface{} }{ "SayHello": { name: "SayHello", @@ -2286,7 +2286,9 @@ func testCommand(v *Nvim) func(*testing.T) { opts: map[string]interface{}{ "force": false, }, - want: "Hello world!", + want: map[string]interface{}{ + "output": "Hello world!", + }, }, } for name, tt := range tests { @@ -2302,12 +2304,15 @@ func testCommand(v *Nvim) func(*testing.T) { } }) - got, err := v.Exec(tt.name, true) + opts := map[string]interface{}{ + "output": true, + } + got, err := v.Exec(tt.name, opts) if err != nil { t.Fatal(err) } - if !strings.EqualFold(tt.want, got) { - t.Fatalf("expected %s but got %s", tt.want, got) + if !reflect.DeepEqual(got, tt.want) { + t.Fatalf("got %v but expected %v", got, tt.want) } }) @@ -2327,13 +2332,16 @@ func testCommand(v *Nvim) func(*testing.T) { } }) - var got string - b.Exec(tt.name, true, &got) + opts := map[string]interface{}{ + "output": true, + } + var got map[string]interface{} + b.Exec(tt.name, opts, &got) if err := b.Execute(); err != nil { t.Fatal(err) } - if !strings.EqualFold(tt.want, got) { - t.Fatalf("expected %s but got %s", tt.want, got) + if !reflect.DeepEqual(got, tt.want) { + t.Fatalf("got %v but expected %v", got, tt.want) } }) } @@ -2344,7 +2352,7 @@ func testCommand(v *Nvim) func(*testing.T) { name string command UserCommand opts map[string]interface{} - want string + want map[string]interface{} }{ "SayHello": { name: "SayHello", @@ -2352,7 +2360,9 @@ func testCommand(v *Nvim) func(*testing.T) { opts: map[string]interface{}{ "force": false, }, - want: "Hello world!", + want: map[string]interface{}{ + "output": "Hello world!", + }, }, } for name, tt := range tests { @@ -2368,12 +2378,15 @@ func testCommand(v *Nvim) func(*testing.T) { } }) - got, err := v.Exec(tt.name, true) + opts := map[string]interface{}{ + "output": true, + } + got, err := v.Exec(tt.name, opts) if err != nil { t.Fatal(err) } - if !strings.EqualFold(tt.want, got) { - t.Fatalf("expected %s but got %s", tt.want, got) + if !reflect.DeepEqual(got, tt.want) { + t.Fatalf("got %v but expected %v", got, tt.want) } }) @@ -2393,13 +2406,16 @@ func testCommand(v *Nvim) func(*testing.T) { } }) - var got string - b.Exec(tt.name, true, &got) + opts := map[string]interface{}{ + "output": true, + } + var got map[string]interface{} + b.Exec(tt.name, opts, &got) if err := b.Execute(); err != nil { t.Fatal(err) } - if !strings.EqualFold(tt.want, got) { - t.Fatalf("expected %s but got %s", tt.want, got) + if !reflect.DeepEqual(got, tt.want) { + t.Fatalf("got %v but expected %v", got, tt.want) } }) } @@ -2532,12 +2548,19 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to Echo: %v", err) } - gotEcho, err := v.Exec("message", true) + opts := map[string]interface{}{ + "output": true, + } + gotEcho, err := v.Exec("message", opts) if err != nil { t.Fatalf("could not get v:statusmsg nvim variable: %v", err) } - if gotEcho != wantEcho { - t.Fatalf("Echo(%q) = %q, want: %q", wantEcho, gotEcho, wantEcho) + + want := map[string]interface{}{ + "output": wantEcho, + } + if !reflect.DeepEqual(gotEcho, want) { + t.Fatalf("Echo(%q) = %q, want: %q", want, gotEcho, wantEcho) } }) @@ -2548,7 +2571,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2574,7 +2597,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2600,7 +2623,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2626,20 +2649,27 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() const wantNotifyMsg = `hello Notify` + want := map[string]interface{}{ + "output": wantNotifyMsg, + } if err := v.Notify(wantNotifyMsg, LogInfoLevel, make(map[string]interface{})); err != nil { t.Fatalf("failed to Notify: %v", err) } - gotNotifyMsg, err := v.Exec(":messages", true) + + opts := map[string]interface{}{ + "output": true, + } + gotNotifyMsg, err := v.Exec(":messages", opts) if err != nil { t.Fatalf("failed to messages command: %v", err) } - if wantNotifyMsg != gotNotifyMsg { + if !reflect.DeepEqual(gotNotifyMsg, want) { t.Fatalf("Notify(%[1]q, %[2]q) = %[3]q, want: %[1]q", wantNotifyMsg, LogInfoLevel, gotNotifyMsg) } }) @@ -2651,7 +2681,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2682,12 +2712,19 @@ func testMessage(v *Nvim) func(*testing.T) { } b.Echo(chunk, true, make(map[string]interface{})) - var gotEcho string - b.Exec("message", true, &gotEcho) + opts := map[string]interface{}{ + "output": true, + } + var gotEcho map[string]interface{} + b.Exec("message", opts, &gotEcho) if err := b.Execute(); err != nil { t.Fatalf("failed to Execute: %v", err) } - if gotEcho != wantEcho { + + want := map[string]interface{}{ + "output": wantEcho, + } + if !reflect.DeepEqual(gotEcho, want) { t.Fatalf("Echo(%q) = %q, want: %q", wantEcho, gotEcho, wantEcho) } }) @@ -2698,7 +2735,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2728,7 +2765,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2757,7 +2794,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2786,7 +2823,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -2798,12 +2835,20 @@ func testMessage(v *Nvim) func(*testing.T) { if err := b.Execute(); err != nil { t.Fatalf("failed to Notify: %v", err) } - var gotNotifyMsg string - b.Exec(":messages", true, &gotNotifyMsg) + + opts := map[string]interface{}{ + "output": true, + } + var gotNotifyMsg map[string]interface{} + b.Exec(":messages", opts, &gotNotifyMsg) if err := b.Execute(); err != nil { t.Fatalf("failed to \":messages\" command: %v", err) } - if wantNotifyMsg != gotNotifyMsg { + + want := map[string]interface{}{ + "output": wantNotifyMsg, + } + if !reflect.DeepEqual(gotNotifyMsg, want) { t.Fatalf("Notify(%[1]q, %[2]q) = %[3]q, want: %[1]q", wantNotifyMsg, LogInfoLevel, gotNotifyMsg) } }) @@ -2815,7 +2860,7 @@ func testMessage(v *Nvim) func(*testing.T) { t.Fatalf("failed to SetVVar: %v", err) } // clear messages - if _, err := v.Exec(":messages clear", false); err != nil { + if _, err := v.Exec(":messages clear", make(map[string]interface{})); err != nil { t.Fatalf("failed to SetVVar: %v", err) } }() @@ -3780,90 +3825,48 @@ func testHighlight(v *Nvim) func(*testing.T) { t.Fatal(err) } - const testHighlight = `TestHighlight` - const cmd = `highlight ` + testHighlight + ` cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold` - if err := v.Command(cmd); err != nil { - t.Fatal(err) - } - - wantCTerm := &HLAttrs{ - Underline: true, - Foreground: -1, - Background: 10, - Special: -1, - CtermForeground: -1, - CtermBackground: -1, - } - wantGUI := &HLAttrs{ - Bold: true, - Foreground: cm[`Red`], - Background: cm[`Yellow`], - Special: cm[`Blue`], - CtermForeground: -1, - CtermBackground: -1, - } - - var nsID int - if err := v.Eval(`hlID('`+testHighlight+`')`, &nsID); err != nil { - t.Fatal(err) - } - - goHLID, err := v.HLIDByName(testHighlight) + color, err := v.ColorByName(`Red`) if err != nil { t.Fatal(err) } - if goHLID != nsID { - t.Fatalf("HLByID(%s)\n got %+v,\nwant %+v", testHighlight, goHLID, nsID) + if color != cm[`Red`] { + t.Fatalf("got red color is %v but want %v", color, cm[`Red`]) } - gotCTermHL, err := v.HLByID(nsID, false) + nsID, err := v.CreateNamespace(t.Name()) if err != nil { t.Fatal(err) } - if !reflect.DeepEqual(gotCTermHL, wantCTerm) { - t.Fatalf("HLByID(id, false)\n got %+v,\nwant %+v", gotCTermHL, wantCTerm) - } - gotGUIHL, err := v.HLByID(nsID, true) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(gotGUIHL, wantGUI) { - t.Fatalf("HLByID(id, true)\n got %+v,\nwant %+v", gotGUIHL, wantGUI) + const testHLName = `Test` + testHLAttrs := &HLAttrs{ + Bold: true, + CtermForeground: cm[`Red`], + CtermBackground: cm[`Yellow`], } - - errorMsgHL, err := v.HLByName(`ErrorMsg`, true) - if err != nil { + if err := v.SetHighlight(nsID, testHLName, testHLAttrs); err != nil { t.Fatal(err) } - errorMsgHL.Bold = true - errorMsgHL.Underline = true - errorMsgHL.Italic = true - if err := v.SetHighlight(nsID, "ErrorMsg", errorMsgHL); err != nil { + testHLID, err := v.HLIDByName(testHLName) + if err != nil { t.Fatal(err) } - wantErrorMsgEHL := &HLAttrs{ - Bold: true, - Underline: true, - Italic: true, - Foreground: 16777215, - Background: 16711680, - Special: -1, - CtermForeground: -1, - CtermBackground: -1, - } - if !reflect.DeepEqual(wantErrorMsgEHL, errorMsgHL) { - t.Fatalf("SetHighlight:\nwant %#v\n got %#v", wantErrorMsgEHL, errorMsgHL) + opts := map[string]interface{}{ + "id": testHLID, } - - const wantRedColor = 16711680 - gotColor, err := v.ColorByName("red") + got, err := v.HL(nsID, opts) if err != nil { t.Fatal(err) } - if wantRedColor != gotColor { - t.Fatalf("expected red color %d but got %d", wantRedColor, gotColor) + if got.Bold != testHLAttrs.Bold { + t.Fatalf("got bold is %t but want %t", got.Bold, testHLAttrs.Bold) + } + if got.CtermForeground != testHLAttrs.CtermForeground { + t.Fatalf("got cterm foreground is %v but want %v", got.CtermForeground, testHLAttrs.CtermForeground) + } + if got.CtermBackground != testHLAttrs.CtermBackground { + t.Fatalf("got cterm background is %v but want %v", got.CtermBackground, testHLAttrs.CtermBackground) } id, err := v.AddBufferHighlight(Buffer(0), 0, `NewHighlight2`, 0, 0, -1) @@ -3897,99 +3900,54 @@ func testHighlight(v *Nvim) func(*testing.T) { var cm map[string]int b.ColorMap(&cm) - const testHighlight = `TestHighlight` - const cmd = `highlight ` + testHighlight + ` cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold` - b.Command(cmd) + var color int + b.ColorByName(`Red`, &color) if err := b.Execute(); err != nil { t.Fatal(err) } - - wantCTerm := &HLAttrs{ - Underline: true, - Foreground: -1, - Background: 10, - Special: -1, - CtermForeground: -1, - CtermBackground: -1, - } - wantGUI := &HLAttrs{ - Bold: true, - Foreground: cm[`Red`], - Background: cm[`Yellow`], - Special: cm[`Blue`], - CtermForeground: -1, - CtermBackground: -1, + if color != cm[`Red`] { + t.Fatalf("got red color is %v but want %v", color, cm[`Red`]) } var nsID int - b.Eval(`hlID('`+testHighlight+`')`, &nsID) + b.CreateNamespace(t.Name(), &nsID) if err := b.Execute(); err != nil { t.Fatal(err) } - var goHLID int - b.HLIDByName(testHighlight, &goHLID) - if err := b.Execute(); err != nil { - t.Fatal(err) - } - if goHLID != nsID { - t.Fatalf("HLByID(%s)\n got %+v,\nwant %+v", testHighlight, goHLID, nsID) + const testHLName = `Test` + testHLAttrs := &HLAttrs{ + Bold: true, + CtermForeground: cm[`Red`], + CtermBackground: cm[`Yellow`], } - - var gotCTermHL HLAttrs - b.HLByID(nsID, false, &gotCTermHL) + b.SetHighlight(nsID, testHLName, testHLAttrs) if err := b.Execute(); err != nil { t.Fatal(err) } - if !reflect.DeepEqual(&gotCTermHL, wantCTerm) { - t.Fatalf("HLByID(id, false)\n got %+v,\nwant %+v", &gotCTermHL, wantCTerm) - } - var gotGUIHL HLAttrs - b.HLByID(nsID, true, &gotGUIHL) + var testHLID int + b.HLIDByName(testHLName, &testHLID) if err := b.Execute(); err != nil { t.Fatal(err) } - if !reflect.DeepEqual(&gotGUIHL, wantGUI) { - t.Fatalf("HLByID(id, true)\n got %+v,\nwant %+v", &gotGUIHL, wantGUI) - } - var errorMsgHL HLAttrs - b.HLByName(`ErrorMsg`, true, &errorMsgHL) - if err := b.Execute(); err != nil { - t.Fatal(err) + opts := map[string]interface{}{ + "id": testHLID, } - - errorMsgHL.Bold = true - errorMsgHL.Underline = true - errorMsgHL.Italic = true - b.SetHighlight(nsID, `ErrorMsg`, &errorMsgHL) + var got HLAttrs + b.HL(nsID, opts, &got) if err := b.Execute(); err != nil { t.Fatal(err) } - - wantErrorMsgEHL := &HLAttrs{ - Bold: true, - Underline: true, - Italic: true, - Foreground: 16777215, - Background: 16711680, - Special: -1, - CtermForeground: -1, - CtermBackground: -1, + if got.Bold != testHLAttrs.Bold { + t.Fatalf("got bold is %t but want %t", got.Bold, testHLAttrs.Bold) } - if !reflect.DeepEqual(&errorMsgHL, wantErrorMsgEHL) { - t.Fatalf("SetHighlight:\ngot %#v\nwant %#v", &errorMsgHL, wantErrorMsgEHL) + if got.CtermForeground != testHLAttrs.CtermForeground { + t.Fatalf("got cterm foreground is %v but want %v", got.CtermForeground, testHLAttrs.CtermForeground) } - - const wantRedColor = 16711680 - var gotColor int - b.ColorByName("red", &gotColor) - if err := b.Execute(); err != nil { - t.Fatal(err) - } - if wantRedColor != gotColor { - t.Fatalf("expected red color %d but got %d", wantRedColor, gotColor) + if got.CtermBackground != testHLAttrs.CtermBackground { + t.Fatalf("got cterm background is %v but want %v", got.CtermBackground, testHLAttrs.CtermBackground) } var id int @@ -4941,7 +4899,7 @@ func testOptions(v *Nvim) func(*testing.T) { skipVersion(t, "v0.7.0") } - got, err := v.OptionInfo(tt.name) + got, err := v.OptionInfo(tt.name, make(map[string]interface{})) if err != nil { t.Fatal(err) } @@ -4960,7 +4918,7 @@ func testOptions(v *Nvim) func(*testing.T) { b := v.NewBatch() var got OptionInfo - b.OptionInfo(tt.name, &got) + b.OptionInfo(tt.name, make(map[string]interface{}), &got) if err := b.Execute(); err != nil { t.Fatal(err) } @@ -5075,7 +5033,7 @@ func testOptionsInfo(v *Nvim) func(*testing.T) { skipVersion(t, "v0.7.0") } - got, err := v.OptionInfo(tt.name) + got, err := v.OptionInfo(tt.name, make(map[string]interface{})) if err != nil { t.Fatal(err) } @@ -5094,7 +5052,7 @@ func testOptionsInfo(v *Nvim) func(*testing.T) { b := v.NewBatch() var got OptionInfo - b.OptionInfo(tt.name, &got) + b.OptionInfo(tt.name, make(map[string]interface{}), &got) if err := b.Execute(); err != nil { t.Fatal(err) } @@ -5430,6 +5388,10 @@ func testUI(v *Nvim) func(*testing.T) { if err := v.TryResizeUIGrid(1, 50, 40); err != nil { t.Fatal(err) } + + if err := v.SetFocusUI(true); err != nil { + t.Fatal(err) + } }) t.Run("Batch", func(t *testing.T) { @@ -5471,6 +5433,11 @@ func testUI(v *Nvim) func(*testing.T) { if err := b.Execute(); err != nil { t.Fatal(err) } + + b.SetFocusUI(true) + if err := b.Execute(); err != nil { + t.Fatal(err) + } }) } } diff --git a/nvim/api_tool.go b/nvim/api_tool.go index a12025a2..a712f841 100644 --- a/nvim/api_tool.go +++ b/nvim/api_tool.go @@ -172,10 +172,8 @@ func parseAPIDef() ([]*Function, []*Function, error) { } } case "deprecatedSince": - if len(call.Args) == 1 { - if lit, ok := call.Args[0].(*ast.BasicLit); ok && lit.Kind == token.INT { - m.DeprecatedSince, _ = strconv.Atoi(lit.Value) - } + if lit, ok := call.Args[0].(*ast.BasicLit); ok && lit.Kind == token.INT { + m.DeprecatedSince, _ = strconv.Atoi(lit.Value) } case "returnPtr": m.ReturnPtr = true @@ -440,11 +438,14 @@ var nvimTypes = map[string]string{ "Process": "Object", "UserCommand": "Object", + "Cmd": "Dictionary", + "*Cmd": "Dictionary", "Channel": "Dictionary", "*Channel": "Dictionary", "ClientVersion": "Dictionary", "HLAttrs": "Dictionary", "*HLAttrs": "Dictionary", + "[]*HLAttrs": "Dictionary", "WindowConfig": "Dictionary", "*WindowConfig": "Dictionary", "ClientAttributes": "Dictionary", @@ -523,6 +524,7 @@ var specialAPIs = map[string]bool{ "nvim_chan_send": true, // FUNC_API_LUA_ONLY "nvim_win_call": true, // FUNC_API_LUA_ONLY "nvim_notify": true, // implements underling nlua(vim.notify) + "nvim_get_option_info": true, // deprecated } func compareFunctions(cmdName string, functions []*Function) error { diff --git a/nvim/plugin/plugin_test.go b/nvim/plugin/plugin_test.go index ea1657ac..8015bf8d 100644 --- a/nvim/plugin/plugin_test.go +++ b/nvim/plugin/plugin_test.go @@ -2,6 +2,7 @@ package plugin_test import ( "fmt" + "reflect" "strings" "testing" @@ -186,14 +187,20 @@ func TestRegister(t *testing.T) { } t.Run("SimpleHandler", func(t *testing.T) { - result, err := p.Nvim.Exec(`:echo Hello('John', 'Doe')`, true) + opts := map[string]interface{}{ + "output": true, + } + result, err := p.Nvim.Exec(`:echo Hello('John', 'Doe')`, opts) if err != nil { t.Fatalf("exec 'echo Hello' function: %v", err) } expected := `Hello, John Doe` - if result != expected { - t.Fatalf("Hello returned %q, want %q", result, expected) + want := map[string]interface{}{ + "output": expected, + } + if !reflect.DeepEqual(result, want) { + t.Fatalf("Hello returned %v, want %v", result, want) } }) @@ -223,104 +230,154 @@ func TestRegister(t *testing.T) { }) t.Run("CommandHandler", func(t *testing.T) { - result, err := p.Nvim.Exec(`Hello World`, true) + opts := map[string]interface{}{ + "output": true, + } + result, err := p.Nvim.Exec(`Hello World`, opts) if err != nil { t.Fatalf("exec 'Hello' command: %v", err) } expected := `Helloorld` - if result != expected { - t.Fatalf("Hello returned %q, want %q", result, expected) + want := map[string]interface{}{ + "output": expected, + } + if !reflect.DeepEqual(result, want) { + t.Fatalf("Hello returned %v, want %v", result, want) } }) t.Run("CommandRangeDotHandler", func(t *testing.T) { - result, err := p.Nvim.Exec(`HelloRangeDot`, true) + opts := map[string]interface{}{ + "output": true, + } + result, err := p.Nvim.Exec(`HelloRangeDot`, opts) if err != nil { t.Fatalf("exec 'Hello' command: %v", err) } expected := `Hello` - if result != expected { - t.Fatalf("Hello returned %q, want %q", result, expected) + want := map[string]interface{}{ + "output": expected, + } + if !reflect.DeepEqual(result, want) { + t.Fatalf("Hello returned %v, want %v", result, want) } }) t.Run("CommandCountHandler", func(t *testing.T) { - result, err := p.Nvim.Exec(`HelloCount`, true) + opts := map[string]interface{}{ + "output": true, + } + result, err := p.Nvim.Exec(`HelloCount`, opts) if err != nil { t.Fatalf("exec 'Hello' command: %v", err) } expected := `Hello` - if result != expected { - t.Fatalf("Hello returned %q, want %q", result, expected) + want := map[string]interface{}{ + "output": expected, + } + if !reflect.DeepEqual(result, want) { + t.Fatalf("Hello returned %v, want %v", result, want) } }) t.Run("CommandEvalHandler", func(t *testing.T) { - result, err := p.Nvim.Exec(`HelloEval`, true) + opts := map[string]interface{}{ + "output": true, + } + result, err := p.Nvim.Exec(`HelloEval`, opts) if err != nil { t.Fatalf("exec 'Hello' command: %v", err) } expected := `plugin` - if result != expected { - t.Fatalf("Hello returned %q, want %q", result, expected) + want := map[string]interface{}{ + "output": expected, + } + if !reflect.DeepEqual(result, want) { + t.Fatalf("Hello returned %v, want %v", result, want) } }) t.Run("AutocmdHandler", func(t *testing.T) { - result, err := p.Nvim.Exec(`doautocmd User Test`, true) + opts := map[string]interface{}{ + "output": true, + } + result, err := p.Nvim.Exec(`doautocmd User Test`, opts) if err != nil { t.Fatalf("exec 'doautocmd User Test' command: %v", err) } expected := `HelloAutocmd` - if result != expected { - t.Fatalf("'doautocmd User Test' returned %q, want %q", result, expected) + want := map[string]interface{}{ + "output": expected, + } + if !reflect.DeepEqual(result, want) { + t.Fatalf("'doautocmd User Test' returned %v, want %v", result, want) } - result2, err := p.Nvim.Exec(`doautocmd User Test`, true) + opts2 := map[string]interface{}{ + "output": true, + } + result2, err := p.Nvim.Exec(`doautocmd User Test`, opts2) if err != nil { t.Fatalf("exec 'doautocmd User Test' command: %v", err) } - - if result2 != expected { - t.Fatalf("'doautocmd User Test' returned %q, want %q", result, expected) + if !reflect.DeepEqual(result2, want) { + t.Fatalf("'doautocmd User Test' returned %v, want %v", result, want) } }) t.Run("AutocmdEvalHandler", func(t *testing.T) { - result, err := p.Nvim.Exec(`doautocmd User Eval`, true) + opts := map[string]interface{}{ + "output": true, + } + result, err := p.Nvim.Exec(`doautocmd User Eval`, opts) if err != nil { t.Fatalf("exec 'doautocmd User Eval' command: %v", err) } expected := `plugin` - if result != expected { - t.Fatalf("'doautocmd User Eval' returned %q, want %q", result, expected) + want := map[string]interface{}{ + "output": expected, + } + if !reflect.DeepEqual(result, want) { + t.Fatalf("'doautocmd User Eval' returned %v, want %v", result, want) } }) t.Run("AutocmdOnceHandler", func(t *testing.T) { - result, err := p.Nvim.Exec(`doautocmd User Once`, true) + opts := map[string]interface{}{ + "output": true, + } + result, err := p.Nvim.Exec(`doautocmd User Once`, opts) if err != nil { t.Fatalf("exec 'doautocmd User Once' command: %v", err) } expected := `HelloAutocmdOnce` - if result != expected { - t.Fatalf("'doautocmd User Once' returned %q, want %q", result, expected) + want := map[string]interface{}{ + "output": expected, + } + if !reflect.DeepEqual(result, want) { + t.Fatalf("'doautocmd User Once' returned %v, want %v", result, want) } - result2, err := p.Nvim.Exec(`doautocmd User Once`, true) + opts2 := map[string]interface{}{ + "output": true, + } + result2, err := p.Nvim.Exec(`doautocmd User Once`, opts2) if err != nil { t.Fatalf("exec 'doautocmd User Once' command: %v", err) } - if result2 == expected { - t.Fatalf("'doautocmd User Once' returned %q, want %q", result, "") + want2 := map[string]interface{}{ + "output": "", + } + if !reflect.DeepEqual(result2, want2) { + t.Fatalf("'doautocmd User Once' returned %v, want %v", result2, want2) } }) }