├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ └── default.md ├── workflows │ ├── git.yml │ └── test.yml ├── CONTRIBUTING.md └── issue_template.md ├── autoload ├── go │ ├── test-fixtures │ │ ├── test │ │ │ ├── .gitignore │ │ │ └── src │ │ │ │ ├── play │ │ │ │ ├── go.mod │ │ │ │ ├── mock │ │ │ │ │ └── controller.go │ │ │ │ └── play_test.go │ │ │ │ ├── example │ │ │ │ ├── go.mod │ │ │ │ ├── example.go │ │ │ │ └── example_test.go │ │ │ │ ├── timeout │ │ │ │ ├── go.mod │ │ │ │ └── timeout_test.go │ │ │ │ ├── showname │ │ │ │ ├── go.mod │ │ │ │ └── showname_test.go │ │ │ │ ├── veterror │ │ │ │ ├── go.mod │ │ │ │ └── veterror.go │ │ │ │ ├── compilerror │ │ │ │ ├── go.mod │ │ │ │ └── compilerror.go │ │ │ │ └── testcompilerror │ │ │ │ ├── go.mod │ │ │ │ └── testcompilerror_test.go │ │ ├── package │ │ │ └── src │ │ │ │ └── package │ │ │ │ ├── bar │ │ │ │ └── .gitkeep │ │ │ │ ├── baz │ │ │ │ └── .gitkeep │ │ │ │ ├── vendor │ │ │ │ └── foo │ │ │ │ │ └── .gitkeep │ │ │ │ ├── go.mod │ │ │ │ └── package.go │ │ ├── config │ │ │ └── buildtags │ │ │ │ ├── go.mod │ │ │ │ ├── buildtags.go │ │ │ │ ├── foo.go │ │ │ │ └── constrainedfoo.go │ │ ├── lint │ │ │ └── src │ │ │ │ ├── lint │ │ │ │ ├── baz.go │ │ │ │ ├── go.mod │ │ │ │ ├── golangci-lint │ │ │ │ │ └── problems │ │ │ │ │ │ ├── importabs │ │ │ │ │ │ ├── ok.go │ │ │ │ │ │ └── problems.go │ │ │ │ │ │ ├── shadow │ │ │ │ │ │ └── problems.go │ │ │ │ │ │ └── multiple │ │ │ │ │ │ └── problems.go │ │ │ │ ├── lint.go │ │ │ │ └── quux.go │ │ │ │ ├── foo │ │ │ │ ├── go.mod │ │ │ │ └── foo.go │ │ │ │ ├── vet │ │ │ │ ├── go.mod │ │ │ │ ├── compilererror │ │ │ │ │ └── compilererror.go │ │ │ │ └── vet.go │ │ │ │ └── errcheck │ │ │ │ ├── go.mod │ │ │ │ ├── compilererror │ │ │ │ └── compilererror.go │ │ │ │ ├── errcheck.go │ │ │ │ └── errcheck_test.go │ │ ├── cmd │ │ │ └── bad.go │ │ ├── term │ │ │ └── term.go │ │ ├── def │ │ │ └── jump.go │ │ ├── fmt │ │ │ ├── hello.go │ │ │ ├── hello_golden.go │ │ │ └── src │ │ │ │ └── imports │ │ │ │ ├── goimports.go │ │ │ │ ├── vendor │ │ │ │ └── gh.com │ │ │ │ │ └── gi │ │ │ │ │ └── foo-logging │ │ │ │ │ └── logger.go │ │ │ │ └── goimports_golden.go │ │ ├── job │ │ │ └── dir has spaces │ │ │ │ └── main.go │ │ ├── lsp │ │ │ ├── fmt │ │ │ │ ├── newline.go │ │ │ │ ├── format.go │ │ │ │ ├── format_golden.go │ │ │ │ ├── multibyte_golden.go │ │ │ │ └── multibyte.go │ │ │ └── imports │ │ │ │ ├── imports.go │ │ │ │ └── imports_golden.go │ │ ├── debug │ │ │ ├── compilerror │ │ │ │ └── main.go │ │ │ └── debugmain │ │ │ │ └── debugmain.go │ │ ├── complete │ │ │ └── complete.go │ │ └── tags │ │ │ ├── add_all_input.go │ │ │ ├── remove_all_golden.go │ │ │ ├── add_all_golden.go │ │ │ ├── remove_all_input.go │ │ │ └── add_all_golden_options.go │ ├── lsp │ │ ├── filechangetype.vim │ │ ├── completionitemkind.vim │ │ ├── lsp_test.vim │ │ └── lsp.vim │ ├── extract.vim │ ├── iferr.vim │ ├── complete_test.vim │ ├── decls.vim │ ├── calls.vim │ ├── import_test.vim │ ├── tool_test.vim │ ├── alternate.vim │ ├── promise_test.vim │ ├── cmd_test.vim │ ├── extract_test.vim │ ├── implements.vim │ ├── referrers.vim │ ├── uri.vim │ ├── impl_test.vim │ ├── calls_test.vim │ ├── uri_test.vim │ ├── promise.vim │ ├── job_test.vim │ ├── template_test.vim │ ├── issue.vim │ ├── fmt_test.vim │ ├── complete.vim │ ├── tags_test.vim │ ├── asmfmt.vim │ ├── indent_test.vim │ ├── template.vim │ ├── play.vim │ ├── package_test.vim │ ├── fillstruct.vim │ ├── config_test.vim │ ├── sameids.vim │ ├── term_test.vim │ ├── lsp_test.vim │ ├── ui.vim │ ├── statusline.vim │ ├── mod.vim │ ├── tool.vim │ ├── rename.vim │ └── impl.vim ├── unite │ └── sources │ │ └── decls.vim ├── ctrlp │ └── decls.vim └── fzf │ └── decls.vim ├── gosnippets └── minisnip │ ├── _go_ff │ ├── _go_sp │ ├── _go_f │ ├── _go_err │ ├── _go_errt │ ├── _go_fori │ ├── _go_errw │ ├── _go_pkg │ ├── _go_eq │ └── _go_tt ├── .coveragerc ├── assets └── vim-go.png ├── ftplugin ├── gomod │ ├── mappings.vim │ └── commands.vim ├── gohtmltmpl.vim ├── godoc │ ├── commands.vim │ └── mappings.vim ├── godoc.vim ├── asm.vim ├── gomod.vim ├── go │ ├── tagbar.vim │ ├── snippets.vim │ └── mappings.vim └── go.vim ├── .dockerignore ├── templates ├── hello_world.go └── hello_world_test.go ├── .gitignore ├── .vintrc.yaml ├── addon-info.json ├── syntax ├── godebugstacktrace.vim ├── vimgo.vim ├── godebugoutput.vim ├── gohtmltmpl.vim ├── godebugvariables.vim ├── godefstack.vim ├── gosum.vim ├── gotexttmpl.vim └── gowork.vim ├── .codecov.yml ├── .editorconfig ├── scripts ├── docker-test ├── runbench.vim ├── bench-syntax ├── install-tools ├── run-vim ├── lint ├── test ├── install-vim └── runtest.vim ├── Makefile ├── Dockerfile ├── indent ├── gohtmltmpl.vim └── go.vim ├── ftdetect └── gofiletype.vim ├── compiler └── go.vim ├── LICENSE ├── rplugin └── python3 │ └── denite │ └── source │ └── decls.py └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: bhcleek 2 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/package/src/package/bar/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/package/src/package/baz/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_ff: -------------------------------------------------------------------------------- 1 | fmt.Printf("%#v\n", {{++}}) 2 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/package/src/package/vendor/foo/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_sp: -------------------------------------------------------------------------------- 1 | fmt.Sprintf("{{++}}", {{++}}) 2 | 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | blank_issues_enabled: false 3 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_f: -------------------------------------------------------------------------------- 1 | // {{++}} 2 | func {{+~\~1+}}() { 3 | } 4 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_err: -------------------------------------------------------------------------------- 1 | if err != nil { 2 | return {{+err+}} 3 | } 4 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | plugins = covimerage 3 | data_file = .coverage_covimerage 4 | -------------------------------------------------------------------------------- /assets/vim-go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fatih/vim-go/HEAD/assets/vim-go.png -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_errt: -------------------------------------------------------------------------------- 1 | if err != nil { 2 | t.Fatal(err) 3 | } 4 | {{++}} 5 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_fori: -------------------------------------------------------------------------------- 1 | for i := 0; i < {{++}}; i++ { 2 | {{++}} 3 | } 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/config/buildtags/go.mod: -------------------------------------------------------------------------------- 1 | module config 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/lint/baz.go: -------------------------------------------------------------------------------- 1 | package lint 2 | 3 | func baz() {} 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/package/src/package/go.mod: -------------------------------------------------------------------------------- 1 | module package 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/foo/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/foo 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/lint/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/lint 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/vet/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/vet 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/play/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/play 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_errw: -------------------------------------------------------------------------------- 1 | if err != nil { 2 | return errors.Wrap(err, "{{++}}") 3 | } 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/cmd/bad.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | notafunc() 5 | } 6 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/example/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/example 2 | 3 | go 1.24 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/timeout/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/timeout 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_pkg: -------------------------------------------------------------------------------- 1 | // Package {{+~expand('%:p:h:t')+}} {{++}} 2 | package {{+~\~2+}} 3 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/errcheck/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/errcheck 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/showname/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/showname 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/veterror/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/veterror 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /ftplugin/gomod/mappings.vim: -------------------------------------------------------------------------------- 1 | nnoremap (go-mod-fmt) :call go#mod#Format() 2 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/compilerror/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/compilerror 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/term/term.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | println("hello, world") 5 | } 6 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/testcompilerror/go.mod: -------------------------------------------------------------------------------- 1 | module vim-go.test/testcompilerror 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/config/buildtags/buildtags.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | func Example() { 4 | foo() 5 | } 6 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .local/ 2 | .config/ 3 | .cache/ 4 | .dlv/ 5 | .git/ 6 | .viminfo 7 | issues/ 8 | autoload/go/**/pkg/ 9 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/lint/golangci-lint/problems/importabs/ok.go: -------------------------------------------------------------------------------- 1 | package problems 2 | 3 | func bar() {} 4 | -------------------------------------------------------------------------------- /templates/hello_world.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/def/jump.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/fmt/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/job/dir has spaces/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | notafunc() 5 | println("vim-go") 6 | } 7 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lsp/fmt/newline.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | func main() { 5 | fmt.Println("vim-go") 6 | } 7 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/fmt/hello_golden.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lsp/fmt/format.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /ftplugin/gohtmltmpl.vim: -------------------------------------------------------------------------------- 1 | if exists("b:did_ftplugin") 2 | finish 3 | endif 4 | 5 | runtime! ftplugin/html.vim 6 | 7 | " vim: sw=2 ts=2 et 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/config/buildtags/foo.go: -------------------------------------------------------------------------------- 1 | // +build !constrained 2 | 3 | package config 4 | 5 | func foo() { 6 | println("foo") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/debug/compilerror/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go" 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lsp/fmt/format_golden.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/veterror/veterror.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Errorf("%v") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/debug/debugmain/debugmain.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/foo/foo.go: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | import "fmt" 4 | 5 | func MissingFooDoc() { 6 | fmt.Println("missing doc") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/lint/golangci-lint/problems/importabs/problems.go: -------------------------------------------------------------------------------- 1 | package problems 2 | 3 | import "/quux" 4 | 5 | func baz() {} 6 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/lint/lint.go: -------------------------------------------------------------------------------- 1 | package lint 2 | 3 | import "fmt" 4 | 5 | func MissingDoc() { 6 | fmt.Println("missing doc") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/package/src/package/package.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_eq: -------------------------------------------------------------------------------- 1 | if !reflect.DeepEqual({{+got+}}, {{+want+}}) { 2 | t.Errorf("\ngot: %#v\nwant: %#v\n", {{+~\~2+}}, {{+~\~2+}}) 3 | } 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/lint/quux.go: -------------------------------------------------------------------------------- 1 | package lint 2 | 3 | import "fmt" 4 | 5 | func AlsoMissingDoc() { 6 | fmt.Println("missing doc") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/compilerror/compilerror.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go" 7 | } 8 | -------------------------------------------------------------------------------- /templates/hello_world_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestHelloWorld(t *testing.T) { 6 | // t.Fatal("not implemented") 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/vet/compilererror/compilererror.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go" 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/example/example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func HelloWorld() string { 4 | return "not the hello you're looking for" 5 | } 6 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/errcheck/compilererror/compilererror.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go" 7 | } 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/vet/vet.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | str := "hello world!" 7 | fmt.Printf("%d\n", str) 8 | } 9 | -------------------------------------------------------------------------------- /ftplugin/gomod/commands.vim: -------------------------------------------------------------------------------- 1 | command! -nargs=0 -range GoModFmt call go#mod#Format() 2 | 3 | command! -nargs=0 GoModFmtAutoSaveToggle call go#mod#ToggleModFmtAutoSave() 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/complete/complete.go: -------------------------------------------------------------------------------- 1 | package complete 2 | 3 | type T struct { 4 | V string 5 | } 6 | 7 | func Example(s string) { 8 | Example("") 9 | } 10 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/lint/golangci-lint/problems/shadow/problems.go: -------------------------------------------------------------------------------- 1 | package problems 2 | 3 | func mySleep(time int) { 4 | time.Sleep(500 * time.Millisecond) 5 | } 6 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/play/mock/controller.go: -------------------------------------------------------------------------------- 1 | package mock 2 | 3 | import "testing" 4 | 5 | func Fail(t *testing.T) { 6 | t.Fatal("another package badness") 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | /.bash_history 4 | /.cache 5 | /.config 6 | /.coverage.covimerage 7 | /.local 8 | /.viminfo 9 | /coverage.xml 10 | /doc/tags 11 | /issues 12 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/errcheck/errcheck.go: -------------------------------------------------------------------------------- 1 | package errcheck 2 | 3 | import ( 4 | "io" 5 | "os" 6 | ) 7 | 8 | func foo() { 9 | io.Copy(os.Stdout, os.Stdin) 10 | } 11 | -------------------------------------------------------------------------------- /.vintrc.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | ProhibitUnnecessaryDoubleQuote: 3 | enabled: false 4 | ProhibitEqualTildeOperator: 5 | enabled: false 6 | ProhibitNoAbortFunction: 7 | enabled: false 8 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/fmt/src/imports/goimports.go: -------------------------------------------------------------------------------- 1 | package main 2 | func Foo(log *logging.TestLogger) { 3 | log.Debug("vim-go") 4 | } 5 | 6 | func main() { 7 | fmt.Println("vim-go") 8 | } 9 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lsp/imports/imports.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | io.Copy(ioutil.Discard, os.Stdin) 9 | fmt.Println("vim-go") 10 | } 11 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/example/example_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func ExampleHelloWorld() { 8 | fmt.Println("Hello, World") 9 | // Output: What's shakin 10 | } 11 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/errcheck/errcheck_test.go: -------------------------------------------------------------------------------- 1 | package errcheck 2 | 3 | import ( 4 | "io" 5 | "os" 6 | "testing" 7 | ) 8 | 9 | func TestFoo(t *testing.T) { 10 | io.Copy(os.Stdout, os.Stdin) 11 | } 12 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lint/src/lint/golangci-lint/problems/multiple/problems.go: -------------------------------------------------------------------------------- 1 | package problems 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | func mySleep(time int) { 8 | time.Sleep(500 * time.Millisecond) 9 | } 10 | -------------------------------------------------------------------------------- /addon-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vim-go", 3 | "description": "Full featured Go (golang) support for Vim.", 4 | "author": "Fatih Arslan ", 5 | "repository" : {"type": "git", "url": "https://github.com/fatih/vim-go.git"} 6 | } 7 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lsp/imports/imports_golden.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | io.Copy(ioutil.Discard, os.Stdin) 12 | fmt.Println("vim-go") 13 | } 14 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/testcompilerror/testcompilerror_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io/ioutil" 5 | "testing" 6 | ) 7 | 8 | func TestSomething(t *testing.T) { 9 | r := struct{}{} 10 | ioutil.ReadAll(r) 11 | } 12 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/config/buildtags/constrainedfoo.go: -------------------------------------------------------------------------------- 1 | // +build constrained 2 | 3 | package config 4 | 5 | // foo is constrained and this comment exists to make the line numbers different than foo.go 6 | func foo() { 7 | println("foo") 8 | } 9 | -------------------------------------------------------------------------------- /syntax/godebugstacktrace.vim: -------------------------------------------------------------------------------- 1 | if exists("b:current_syntax") 2 | finish 3 | endif 4 | 5 | syn match godebugStacktrace '^\S\+' 6 | 7 | let b:current_syntax = "godebugoutput" 8 | 9 | hi def link godebugStacktrace Function 10 | 11 | " vim: sw=2 ts=2 et 12 | -------------------------------------------------------------------------------- /ftplugin/godoc/commands.vim: -------------------------------------------------------------------------------- 1 | " -- doc 2 | command! -nargs=* -range -complete=customlist,go#package#Complete GoDoc call go#doc#Open('new', 'split', ) 3 | command! -nargs=* -range -complete=customlist,go#package#Complete GoDocBrowser call go#doc#OpenBrowser() 4 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/showname/showname_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestHelloWorld(t *testing.T) { 6 | t.Error("so long") 7 | 8 | t.Run("sub", func(t *testing.T) { 9 | t.Error("thanks for all the fish") 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | --- 2 | coverage: 3 | status: 4 | project: 5 | default: 6 | target: auto 7 | threshold: 1 8 | base: auto 9 | patch: off 10 | comment: false 11 | ignore: 12 | - "!autoload/go/*.vim$" 13 | - "autoload/go/*_test.vim$" 14 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/fmt/src/imports/vendor/gh.com/gi/foo-logging/logger.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import "fmt" 4 | 5 | type TestLogger struct { 6 | Value string 7 | } 8 | 9 | func (l *TestLogger) Debug(msg string) { 10 | fmt.Println(msg) 11 | fmt.Println(l.Value) 12 | } 13 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/fmt/src/imports/goimports_golden.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | logging "gh.com/gi/foo-logging" 7 | ) 8 | 9 | func Foo(log *logging.TestLogger) { 10 | log.Debug("vim-go") 11 | } 12 | 13 | func main() { 14 | fmt.Println("vim-go") 15 | } 16 | -------------------------------------------------------------------------------- /syntax/vimgo.vim: -------------------------------------------------------------------------------- 1 | if exists("b:current_syntax") 2 | finish 3 | endif 4 | 5 | let b:current_syntax = "vimgo" 6 | 7 | syn match goInterface /^\S*/ 8 | syn region goTitle start="\%1l" end=":" 9 | 10 | hi def link goInterface Type 11 | hi def link goTitle Label 12 | 13 | " vim: sw=2 ts=2 et 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | trim_trailing_whitespace = true 10 | 11 | [*.go] 12 | indent_style = tab 13 | indent_size = 4 14 | 15 | [Makefile] 16 | indent_style = tab 17 | indent_size = 8 18 | -------------------------------------------------------------------------------- /.github/workflows/git.yml: -------------------------------------------------------------------------------- 1 | name: git checks 2 | on: [pull_request] 3 | 4 | jobs: 5 | autosquash-commits-integrated: 6 | runs-on: ubuntu-22.04 7 | 8 | steps: 9 | - uses: actions/checkout@v2.0.0 10 | - name: Block Fixup Commit Merge 11 | uses: 13rac1/block-fixup-merge-action@v2.0.0 12 | -------------------------------------------------------------------------------- /syntax/godebugoutput.vim: -------------------------------------------------------------------------------- 1 | if exists("b:current_syntax") 2 | finish 3 | endif 4 | 5 | syn match godebugOutputErr '^ERR:.*' 6 | syn match godebugOutputOut '^OUT:.*' 7 | 8 | let b:current_syntax = "godebugoutput" 9 | 10 | hi def link godebugOutputErr Comment 11 | hi def link godebugOutputOut Normal 12 | 13 | " vim: sw=2 ts=2 et 14 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/tags/add_all_input.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Server struct { 4 | Name string 5 | ID int 6 | MyHomeAddress string 7 | SubDomains []string 8 | Empty string 9 | Example int64 10 | Example2 string 11 | Bar struct { 12 | Four string 13 | Five string 14 | } 15 | Lala interface{} 16 | } 17 | -------------------------------------------------------------------------------- /syntax/gohtmltmpl.vim: -------------------------------------------------------------------------------- 1 | if exists("b:current_syntax") 2 | finish 3 | endif 4 | 5 | if !exists("g:main_syntax") 6 | let g:main_syntax = 'html' 7 | endif 8 | 9 | runtime! syntax/gotexttmpl.vim 10 | runtime! syntax/html.vim 11 | unlet b:current_syntax 12 | 13 | syn cluster htmlPreproc add=gotplAction,goTplComment 14 | 15 | let b:current_syntax = "gohtmltmpl" 16 | 17 | " vim: sw=2 ts=2 et 18 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/tags/remove_all_golden.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Server struct { 4 | Name string 5 | ID int 6 | MyHomeAddress string 7 | SubDomains []string 8 | Empty string 9 | Example int64 10 | Example2 string 11 | Bar struct { 12 | Four string 13 | Five string 14 | } 15 | Lala interface{} 16 | } 17 | -------------------------------------------------------------------------------- /gosnippets/minisnip/_go_tt: -------------------------------------------------------------------------------- 1 | var tests = []struct { 2 | name string 3 | expected string 4 | given string 5 | }{ 6 | {"", "", "",}, 7 | } 8 | for _, tt := range tests { 9 | tt := tt 10 | t.Run(tt.name, func(t *testing.T){ 11 | actual := {{++}}(tt.given) 12 | if actual != tt.expected { 13 | t.Errorf("{{+~\~1+}}(%s): expected %s, actual %s", tt.given, tt.expected, actual) 14 | } 15 | 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /ftplugin/godoc/mappings.vim: -------------------------------------------------------------------------------- 1 | nnoremap (go-doc) :call go#doc#Open("new", "split") 2 | nnoremap (go-doc-tab) :call go#doc#Open("tabnew", "tabe") 3 | nnoremap (go-doc-vertical) :call go#doc#Open("vnew", "vsplit") 4 | nnoremap (go-doc-split) :call go#doc#Open("new", "split") 5 | nnoremap (go-doc-browser) :call go#doc#OpenBrowser() 6 | 7 | " vim: sw=2 ts=2 et 8 | -------------------------------------------------------------------------------- /autoload/go/lsp/filechangetype.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | let s:fct = { 6 | \ 'Created': 1, 7 | \ 'Changed': 2, 8 | \ 'Deleted': 3, 9 | \ } 10 | 11 | function! go#lsp#filechangetype#FileChangeType(name) 12 | return s:fct[a:name] 13 | endfunction 14 | 15 | " restore Vi compatibility settings 16 | let &cpo = s:cpo_save 17 | unlet s:cpo_save 18 | 19 | " vim: sw=2 ts=2 et 20 | -------------------------------------------------------------------------------- /scripts/docker-test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run all tests inside a Docker container 4 | # 5 | 6 | set -euC 7 | vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) 8 | cd "$vimgodir" 9 | 10 | docker build --platform=linux/amd64 --tag vim-go-test . 11 | # seccomp=confined is required for dlv to run in a container, hence it's 12 | # required for vim-go's debug tests. 13 | docker run -e VIMS --rm --security-opt="seccomp=unconfined" vim-go-test 14 | 15 | # vim:ts=2:sts=2:sw=2:et 16 | -------------------------------------------------------------------------------- /autoload/go/extract.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#extract#Extract(line1, line2) abort 6 | if !go#config#GoplsEnabled() 7 | call go#util#EchoError('GoExtract requires gopls, but gopls is disabled') 8 | return 9 | endif 10 | 11 | call go#lsp#Extract(a:line1, a:line2) 12 | return 13 | endfunction 14 | 15 | " restore Vi compatibility settings 16 | let &cpo = s:cpo_save 17 | unlet s:cpo_save 18 | 19 | " vim: sw=2 ts=2 et 20 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/tags/add_all_golden.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Server struct { 4 | Name string `json:"name"` 5 | ID int `json:"id"` 6 | MyHomeAddress string `json:"my_home_address"` 7 | SubDomains []string `json:"sub_domains"` 8 | Empty string `json:"empty"` 9 | Example int64 `json:"example"` 10 | Example2 string `json:"example_2"` 11 | Bar struct { 12 | Four string `json:"four"` 13 | Five string `json:"five"` 14 | } `json:"bar"` 15 | Lala interface{} `json:"lala"` 16 | } 17 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/tags/remove_all_input.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Server struct { 4 | Name string `json:"name"` 5 | ID int `json:"id"` 6 | MyHomeAddress string `json:"my_home_address"` 7 | SubDomains []string `json:"sub_domains"` 8 | Empty string `json:"empty"` 9 | Example int64 `json:"example"` 10 | Example2 string `json:"example_2"` 11 | Bar struct { 12 | Four string `json:"four"` 13 | Five string `json:"five"` 14 | } `json:"bar"` 15 | Lala interface{} `json:"lala"` 16 | } 17 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lsp/fmt/multibyte_golden.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") // 中 asdfasdf 7 | fmt.Println("vim-go") // 中 8 | fmt.Println("vim-go") // 中a 9 | fmt.Println("vim-go") // 中 a 10 | fmt.Println("vim-go") // 中 11 | 12 | fmt.Println("vim-go") // ⌘ asdfasdf 13 | fmt.Println("vim-go") // ⌘ 14 | fmt.Println("vim-go") // ⌘ a 15 | fmt.Println("vim-go") // ⌘ a 16 | fmt.Println("vim-go") // ⌘ 17 | 18 | fmt.Println("vim-go") // é asdfasdf 19 | fmt.Println("vim-go") // é 20 | fmt.Println("vim-go") // é a 21 | fmt.Println("vim-go") // é a 22 | fmt.Println("vim-go") // é 23 | 24 | } 25 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/tags/add_all_golden_options.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Server struct { 4 | Name string `json:"name,omitempty"` 5 | ID int `json:"id,omitempty"` 6 | MyHomeAddress string `json:"my_home_address,omitempty"` 7 | SubDomains []string `json:"sub_domains,omitempty"` 8 | Empty string `json:"empty,omitempty"` 9 | Example int64 `json:"example,omitempty"` 10 | Example2 string `json:"example_2,omitempty"` 11 | Bar struct { 12 | Four string `json:"four,omitempty"` 13 | Five string `json:"five,omitempty"` 14 | } `json:"bar,omitempty"` 15 | Lala interface{} `json:"lala,omitempty"` 16 | } 17 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/lsp/fmt/multibyte.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") // 中 asdfasdf 7 | fmt.Println("vim-go") // 中 8 | fmt.Println("vim-go") // 中a 9 | fmt.Println("vim-go") // 中 a 10 | fmt.Println("vim-go") // 中 11 | 12 | fmt.Println("vim-go") // ⌘ asdfasdf 13 | fmt.Println("vim-go") // ⌘ 14 | fmt.Println("vim-go") // ⌘ a 15 | fmt.Println("vim-go") // ⌘ a 16 | fmt.Println("vim-go") // ⌘ 17 | 18 | fmt.Println("vim-go") // é asdfasdf 19 | fmt.Println("vim-go") // é 20 | fmt.Println("vim-go") // é a 21 | fmt.Println("vim-go") // é a 22 | fmt.Println("vim-go") // é 23 | 24 | 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Thanks for improving vim-go! Before you dive in please read the following: 2 | 3 | 1. Please read our 4 | [Documentation](https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt), 5 | it might have a solution to your problem. 6 | 2. If you add a new feature then please don't forget to update the documentation: 7 | [doc/vim-go.txt](https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt). 8 | 3. If it's a breaking change or exceeds 100 lines of code then please open an 9 | issue first and describe the changes you want to make. 10 | 4. See `:help go-development` for instructions on how to run and write tests. If 11 | you add a new feature be sure you also include a test if feasible. 12 | 13 | -------------------------------------------------------------------------------- /autoload/go/iferr.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#iferr#Generate() 6 | let [l:out, l:err] = go#util#Exec(['iferr', 7 | \ '-pos=' . go#util#OffsetCursor()], go#util#GetLines()) 8 | if len(l:out) == 1 9 | return 10 | endif 11 | if getline('.') =~ '^\s*$' 12 | silent delete _ 13 | silent normal! k 14 | endif 15 | let l:pos = getcurpos() 16 | call append(l:pos[1], split(l:out, "\n")) 17 | silent normal! j=2j 18 | call setpos('.', l:pos) 19 | silent normal! 4j 20 | endfunction 21 | 22 | " restore Vi compatibility settings 23 | let &cpo = s:cpo_save 24 | unlet s:cpo_save 25 | 26 | " vim: sw=2 ts=2 et 27 | -------------------------------------------------------------------------------- /ftplugin/godoc.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2013 The Go Authors. All rights reserved. 2 | " Use of this source code is governed by a BSD-style 3 | " license that can be found in the LICENSE file. 4 | " 5 | " go.vim: Vim filetype plugin for Go. 6 | 7 | if exists("b:did_ftplugin") 8 | finish 9 | endif 10 | let b:did_ftplugin = 1 11 | 12 | " don't spam the user when Vim is started in Vi compatibility mode 13 | let s:cpo_save = &cpo 14 | set cpo&vim 15 | 16 | if get(g:, "go_doc_keywordprg_enabled", 1) 17 | " keywordprg doesn't allow to use vim commands, override it 18 | nnoremap K :GoDoc 19 | endif 20 | 21 | " restore Vi compatibility settings 22 | let &cpo = s:cpo_save 23 | unlet s:cpo_save 24 | 25 | " vim: sw=2 ts=2 et 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VIMS ?= vim-8.2 vim-9.1 nvim 2 | TEST_FLAGS ?= 3 | 4 | all: install lint test 5 | 6 | install: 7 | @echo "==> Installing Vims: $(VIMS)" 8 | @for vim in $(VIMS); do \ 9 | ./scripts/install-vim $$vim; \ 10 | ./scripts/install-tools $$vim; \ 11 | done 12 | 13 | test: 14 | @echo "==> Running tests for $(VIMS)" 15 | @for vim in $(VIMS); do \ 16 | ./scripts/test $(TEST_FLAGS) $$vim; \ 17 | done 18 | 19 | lint: 20 | @echo "==> Running linting tools" 21 | @./scripts/lint vim-9.1 22 | 23 | docker: 24 | @echo "==> Building/starting Docker container" 25 | @./scripts/docker-test 26 | 27 | clean: 28 | @echo "==> Cleaning /tmp/vim-go-test" 29 | @rm -rf /tmp/vim-go-test 30 | 31 | .PHONY: all test install clean lint docker 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM --platform=linux/amd64 golang:1.24.1 2 | 3 | RUN apt-get update -y --allow-insecure-repositories && \ 4 | apt-get install -y build-essential curl git libncurses5-dev python3-pip && \ 5 | apt-get clean && \ 6 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 7 | 8 | RUN pip3 install vim-vint --break-system-packages 9 | 10 | RUN useradd -ms /bin/bash -d /vim-go vim-go 11 | USER vim-go 12 | 13 | COPY scripts/install-vim /vim-go/scripts/install-vim 14 | WORKDIR /vim-go 15 | 16 | RUN scripts/install-vim vim-8.2 17 | RUN scripts/install-vim vim-9.1 18 | RUN scripts/install-vim nvim 19 | 20 | COPY . /vim-go/ 21 | WORKDIR /vim-go 22 | 23 | RUN scripts/install-tools vim-8.2 24 | RUN scripts/install-tools vim-9.1 25 | RUN scripts/install-tools nvim 26 | 27 | ENTRYPOINT ["make"] 28 | -------------------------------------------------------------------------------- /syntax/godebugvariables.vim: -------------------------------------------------------------------------------- 1 | if exists("b:current_syntax") 2 | finish 3 | endif 4 | 5 | syn match godebugTitle '^#.*' 6 | syn match godebugVariables '^\s*\S\+\ze:' 7 | 8 | syn keyword goType chan map bool string error 9 | syn keyword goSignedInts int int8 int16 int32 int64 rune 10 | syn keyword goUnsignedInts byte uint uint8 uint16 uint32 uint64 uintptr 11 | syn keyword goFloats float32 float64 12 | syn keyword goComplexes complex64 complex128 13 | 14 | syn keyword goBoolean true false 15 | 16 | let b:current_syntax = "godebugvariables" 17 | 18 | hi def link godebugTitle Underlined 19 | hi def link godebugVariables Statement 20 | hi def link goType Type 21 | hi def link goBoolean Boolean 22 | 23 | " vim: sw=2 ts=2 et 24 | -------------------------------------------------------------------------------- /autoload/go/complete_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_GetInfo_gopls() 6 | let g:go_info_mode = 'gopls' 7 | call s:getinfo() 8 | endfunction 9 | 10 | func! s:getinfo() 11 | let l:filename = 'complete/complete.go' 12 | let l:wd = getcwd() 13 | let l:tmp = gotest#load_fixture(l:filename) 14 | try 15 | call cursor(8, 3) 16 | 17 | let expected = 'func Example(s string)' 18 | let actual = go#complete#GetInfo() 19 | call assert_equal(expected, actual) 20 | finally 21 | call go#util#Chdir(l:wd) 22 | call delete(l:tmp, 'rf') 23 | endtry 24 | endfunction 25 | 26 | " restore Vi compatibility settings 27 | let &cpo = s:cpo_save 28 | unlet s:cpo_save 29 | 30 | " vim: sw=2 ts=2 et 31 | -------------------------------------------------------------------------------- /autoload/go/decls.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#decls#Decls(mode, ...) abort 6 | let decls_mode = go#config#DeclsMode() 7 | if decls_mode == 'ctrlp' 8 | call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000)) 9 | elseif decls_mode == 'fzf' 10 | call call("fzf#decls#cmd", [a:mode] + a:000) 11 | else 12 | if globpath(&rtp, 'plugin/ctrlp.vim') != "" 13 | call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000)) 14 | elseif globpath(&rtp, 'plugin/fzf.vim') != "" 15 | call call("fzf#decls#cmd", [a:mode] + a:000) 16 | else 17 | call go#util#EchoError("neither ctrlp.vim nor fzf.vim are installed. Please install either one") 18 | end 19 | end 20 | endfunction 21 | 22 | " restore Vi compatibility settings 23 | let &cpo = s:cpo_save 24 | unlet s:cpo_save 25 | 26 | " vim: sw=2 ts=2 et 27 | -------------------------------------------------------------------------------- /ftplugin/asm.vim: -------------------------------------------------------------------------------- 1 | " asm.vim: Vim filetype plugin for Go assembler. 2 | 3 | if exists("b:did_ftplugin") 4 | finish 5 | endif 6 | let b:did_ftplugin = 1 7 | 8 | " don't spam the user when Vim is started in Vi compatibility mode 9 | let s:cpo_save = &cpo 10 | set cpo&vim 11 | 12 | let b:undo_ftplugin = "setl fo< com< cms< 13 | \ | exe 'au! vim-go-asm-buffer * '" 14 | 15 | setlocal formatoptions-=t 16 | 17 | setlocal comments=s1:/*,mb:*,ex:*/,:// 18 | setlocal commentstring=//\ %s 19 | 20 | setlocal noexpandtab 21 | 22 | command! -nargs=0 AsmFmt call go#asmfmt#Format() 23 | 24 | " Autocommands 25 | " ============================================================================ 26 | 27 | augroup vim-go-asm-buffer 28 | autocmd! * 29 | 30 | autocmd BufWritePre call go#auto#asmfmt_autosave() 31 | augroup end 32 | 33 | " restore Vi compatibility settings 34 | let &cpo = s:cpo_save 35 | unlet s:cpo_save 36 | 37 | " vim: sw=2 ts=2 et 38 | -------------------------------------------------------------------------------- /syntax/godefstack.vim: -------------------------------------------------------------------------------- 1 | if exists("b:current_syntax") 2 | finish 3 | endif 4 | 5 | syn match godefStackComment '^".*' 6 | syn match godefLinePrefix '^[>\s]\s' nextgroup=godefStackEntryNumber contains=godefStackCurrentPosition 7 | syn match godefStackEntryNumber '\d\+' nextgroup=godefStackFilename skipwhite 8 | syn match godefStackCurrentPosition '>' contained 9 | syn match godefStackFilename '[^|]\+' contained nextgroup=godefStackEntryLocation 10 | syn region godefStackEntryLocation oneline start='|' end='|' contained contains=godefStackEntryLocationNumber 11 | syn match godefStackEntryLocationNumber '\d\+' contained display 12 | 13 | let b:current_syntax = "godefstack" 14 | 15 | hi def link godefStackComment Comment 16 | hi def link godefStackCurrentPosition Special 17 | hi def link godefStackFilename Directory 18 | hi def link godefStackEntryLocationNumber LineNr 19 | 20 | " vim: sw=2 ts=2 et 21 | -------------------------------------------------------------------------------- /ftplugin/gomod.vim: -------------------------------------------------------------------------------- 1 | " gomod.vim: Vim filetype plugin for Go assembler. 2 | 3 | if exists("b:did_ftplugin") 4 | finish 5 | endif 6 | let b:did_ftplugin = 1 7 | 8 | " don't spam the user when Vim is started in Vi compatibility mode 9 | let s:cpo_save = &cpo 10 | set cpo&vim 11 | 12 | let b:undo_ftplugin = "setl fo< com< cms< 13 | \ | exe 'au! vim-go-gomod-buffer * '" 14 | 15 | setlocal formatoptions-=t 16 | 17 | setlocal comments=:// 18 | setlocal commentstring=//\ %s 19 | 20 | " Autocommands 21 | " ============================================================================ 22 | 23 | augroup vim-go-gomod-buffer 24 | autocmd! * 25 | 26 | autocmd BufWritePre call go#auto#modfmt_autosave() 27 | if go#util#has_job() 28 | autocmd BufWritePost,FileChangedShellPost call go#lsp#ModReload(resolve(expand(':p'))) 29 | endif 30 | augroup end 31 | 32 | " restore Vi compatibility settings 33 | let &cpo = s:cpo_save 34 | unlet s:cpo_save 35 | 36 | " vim: sw=2 ts=2 et 37 | -------------------------------------------------------------------------------- /autoload/go/calls.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#calls#Callers() abort 6 | if !go#config#GoplsEnabled() 7 | call go#util#EchoError("gopls is disabled") 8 | return 9 | endif 10 | let [l:line, l:col] = getpos('.')[1:2] 11 | let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col) 12 | let l:fname = expand('%:p') 13 | call go#lsp#Callers(l:fname, l:line, l:col, funcref('s:parse_output', ['callers'])) 14 | return 15 | endfunction 16 | 17 | " This uses Vim's errorformat to parse the output and put it into a quickfix 18 | " or locationlist. 19 | function! s:parse_output(mode, output) abort 20 | let errformat = ",%f:%l:%c:\ %m" 21 | let l:listtype = go#list#Type("GoCallers") 22 | call go#list#ParseFormat(l:listtype, errformat, a:output, a:mode, 0) 23 | 24 | let errors = go#list#Get(l:listtype) 25 | call go#list#Window(l:listtype, len(errors)) 26 | endfunction 27 | 28 | " restore Vi compatibility settings 29 | let &cpo = s:cpo_save 30 | unlet s:cpo_save 31 | 32 | " vim: sw=2 ts=2 et 33 | -------------------------------------------------------------------------------- /autoload/go/import_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_SwitchImportAddIgnoresCommented() 6 | let l:wd = getcwd() 7 | try 8 | let g:go_gopls_enabled = 0 9 | let l:tmp = gotest#write_file('import/import.go', [ 10 | \ 'package import', 11 | \ '', 12 | \ 'import (', 13 | \ "\t" . '// "fmt"', 14 | \ "\t" . '"io"', 15 | \ "\t" . '"ioutil"', 16 | \ "\t" . '"os"', 17 | \ ')', 18 | \ '', 19 | \ 'func main() {', 20 | \ ' io.Copy(ioutil.Discard, os.Stdin)', 21 | \ ' fmt.Println("import the package")', 22 | \ '}', 23 | \ ]) 24 | call go#import#SwitchImport(1, '', 'fmt', 0) 25 | 26 | let l:actual = getline(4) 27 | call assert_equal("\t" . '"fmt"', l:actual) 28 | finally 29 | call go#util#Chdir(l:wd) 30 | call delete(l:tmp, 'rf') 31 | endtry 32 | endfunc 33 | 34 | " restore Vi compatibility settings 35 | let &cpo = s:cpo_save 36 | unlet s:cpo_save 37 | 38 | " vim: sw=2 ts=2 et 39 | -------------------------------------------------------------------------------- /autoload/go/tool_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_ExecuteInDir() abort 6 | let g:go_gopls_enabled = 0 7 | let l:wd = getcwd() 8 | let l:tmp = gotest#write_file('a/a.go', ['package a']) 9 | try 10 | let l:cwd = go#util#Exec(['pwd']) 11 | let l:out = go#util#ExecInDir(['pwd']) 12 | call assert_notequal(l:cwd, l:out) 13 | call assert_equal([l:tmp . "/src/a\n", 0], l:out) 14 | finally 15 | call go#util#Chdir(l:wd) 16 | call delete(l:tmp, 'rf') 17 | endtry 18 | endfunc 19 | 20 | func! Test_ExecuteInDir_nodir() abort 21 | let g:go_gopls_enabled = 0 22 | let l:wd = getcwd() 23 | let l:tmp = go#util#tempdir("executeindir") 24 | exe ':e ' . l:tmp . '/new-dir/a' 25 | 26 | try 27 | let l:out = go#util#ExecInDir(['pwd']) 28 | call assert_equal(['', 1], l:out) 29 | finally 30 | call go#util#Chdir(l:wd) 31 | call delete(l:tmp, 'rf') 32 | endtry 33 | endfunc 34 | 35 | " restore Vi compatibility settings 36 | let &cpo = s:cpo_save 37 | unlet s:cpo_save 38 | 39 | " vim: sw=2 ts=2 et 40 | -------------------------------------------------------------------------------- /autoload/go/alternate.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | " Test alternates between the implementation of code and the test code. 6 | function! go#alternate#Switch(bang, cmd) abort 7 | let file = expand('%') 8 | if empty(file) 9 | call go#util#EchoError("no buffer name") 10 | return 11 | elseif file =~# '^\f\+_test\.go$' 12 | let l:root = split(file, '_test.go$')[0] 13 | let l:alt_file = l:root . ".go" 14 | elseif file =~# '^\f\+\.go$' 15 | let l:root = split(file, ".go$")[0] 16 | let l:alt_file = l:root . '_test.go' 17 | else 18 | call go#util#EchoError("not a go file") 19 | return 20 | endif 21 | if !filereadable(alt_file) && !bufexists(alt_file) && !a:bang 22 | call go#util#EchoError("couldn't find ".alt_file) 23 | return 24 | elseif empty(a:cmd) 25 | execute ":" . go#config#AlternateMode() . " " . alt_file 26 | else 27 | execute ":" . a:cmd . " " . alt_file 28 | endif 29 | endfunction 30 | 31 | " restore Vi compatibility settings 32 | let &cpo = s:cpo_save 33 | unlet s:cpo_save 34 | 35 | " vim: sw=2 ts=2 et 36 | -------------------------------------------------------------------------------- /autoload/go/promise_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_PromiseNew() abort 6 | let l:sut = go#promise#New(function('s:work', []), 100, -1) 7 | call assert_true(has_key(l:sut, 'wrapper')) 8 | call assert_true(has_key(l:sut, 'await')) 9 | endfunc 10 | 11 | func! Test_PromiseAwait() abort 12 | let l:expected = 1 13 | let l:default = -1 14 | let l:sut = go#promise#New(function('s:work', [l:expected]), 100, l:default) 15 | 16 | call timer_start(10, l:sut.wrapper) 17 | 18 | let l:actual = call(l:sut.await, []) 19 | call assert_equal(l:expected, l:actual) 20 | endfunc 21 | 22 | func! Test_PromiseAwait_Timeout() abort 23 | let l:desired = 1 24 | let l:expected = -1 25 | let l:sut = go#promise#New(function('s:work', [l:desired]), 10, l:expected) 26 | 27 | call timer_start(100, l:sut.wrapper) 28 | 29 | let l:actual = call(l:sut.await, []) 30 | call assert_equal(l:expected, l:actual) 31 | endfunc 32 | 33 | func! s:work(val, timer) 34 | return a:val 35 | endfunc 36 | 37 | " restore Vi compatibility settings 38 | let &cpo = s:cpo_save 39 | unlet s:cpo_save 40 | 41 | " vim: sw=2 ts=2 et 42 | -------------------------------------------------------------------------------- /autoload/go/cmd_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_GoBuildErrors() 6 | let l:wd = getcwd() 7 | try 8 | let g:go_gopls_enabled = 0 9 | let l:filename = 'cmd/bad.go' 10 | let l:tmp = gotest#load_fixture(l:filename) 11 | 12 | " set the compiler type so that the errorformat option will be set 13 | " correctly. 14 | compiler go 15 | 16 | let expected = [{'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'undefined: notafunc'}] 17 | " clear the quickfix lists 18 | call setqflist([], 'r') 19 | 20 | call go#cmd#Build(1) 21 | 22 | let actual = getqflist() 23 | let start = reltime() 24 | while len(actual) == 0 && reltimefloat(reltime(start)) < 10 25 | sleep 100m 26 | let actual = getqflist() 27 | endwhile 28 | 29 | call gotest#assert_quickfix(actual, l:expected) 30 | finally 31 | call go#util#Chdir(l:wd) 32 | call delete(l:tmp, 'rf') 33 | endtry 34 | endfunc 35 | 36 | " restore Vi compatibility settings 37 | let &cpo = s:cpo_save 38 | unlet s:cpo_save 39 | 40 | " vim: sw=2 ts=2 et 41 | -------------------------------------------------------------------------------- /scripts/runbench.vim: -------------------------------------------------------------------------------- 1 | " vint: -ProhibitSetNoCompatible 2 | 3 | " don't spam the user when Vim is started in Vi compatibility mode 4 | let s:cpo_save = &cpo 5 | set cpo&vim 6 | 7 | set nocompatible nomore shellslash encoding=utf-8 shortmess+=WIF 8 | lang mess C 9 | 10 | if $RUNBENCH_SETTINGS is? 'all' 11 | let $RUNBENCH_SETTINGS = join(['array_whitespace_error', 'build_constraints', 12 | \ 'chan_whitespace_error', 'extra_types', 'fields', 'format_strings', 13 | \ 'function_arguments', 'function_calls', 'functions', 'generate_tags', 14 | \ 'operators', 'space_tab_error', 'string_spellcheck', 15 | \ 'trailing_whitespace_error', 'types', 'variable_assignments', 16 | \ 'variable_declarations'], ' ') 17 | endif 18 | 19 | for s:s in split($RUNBENCH_SETTINGS, ' ') 20 | call execute('let g:go_highlight_' . s:s . ' = 1') 21 | endfor 22 | 23 | filetype plugin indent on 24 | syntax on 25 | 26 | syntime on 27 | redraw! 28 | let s:report = execute('syntime report') 29 | execute ':e ' . fnameescape($RUNBENCH_OUT) 30 | call setline('.', split(s:report, '\n')) 31 | wq 32 | 33 | " restore Vi compatibility settings 34 | let &cpo = s:cpo_save 35 | unlet s:cpo_save 36 | 37 | " vim: sw=2 ts=2 et 38 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/timeout/timeout_test.go: -------------------------------------------------------------------------------- 1 | // Run a few parallel tests, all in parallel, using multiple techniques for 2 | // causing the test to take a while so that the stacktraces resulting from a 3 | // test timeout will contain several goroutines to avoid giving a false sense 4 | // of confidence or creating error formats that don't account for the more 5 | // complex scenarios that can occur with timeouts. 6 | 7 | package main 8 | 9 | import ( 10 | "runtime" 11 | "testing" 12 | "time" 13 | ) 14 | 15 | func init() { 16 | runtime.GOMAXPROCS(3) 17 | } 18 | 19 | func TestSleep(t *testing.T) { 20 | t.Parallel() 21 | time.Sleep(15 * time.Second) 22 | t.Log("expected panic if run with timeout < 15s") 23 | } 24 | 25 | func TestRunning(t *testing.T) { 26 | t.Parallel() 27 | c := time.After(15 * time.Second) 28 | Loop: 29 | for { 30 | select { 31 | case <-c: 32 | break Loop 33 | default: 34 | } 35 | } 36 | 37 | t.Log("expected panic if run with timeout < 15s") 38 | } 39 | 40 | func TestRunningAlso(t *testing.T) { 41 | t.Parallel() 42 | c := time.After(15 * time.Second) 43 | Loop: 44 | for { 45 | select { 46 | case <-c: 47 | break Loop 48 | default: 49 | } 50 | } 51 | t.Log("expected panic if run with timeout < 15s") 52 | } 53 | -------------------------------------------------------------------------------- /scripts/bench-syntax: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Benchmark the syntax/go.vim file. 4 | # 5 | # The first argument is the Vim version to test (as in run-vim), the rest of the 6 | # agument are g:go_highlight_* settings (without that prefix). You can use "ALL" 7 | # to set all the options. 8 | # 9 | 10 | set -euC 11 | vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) 12 | cd "$vimgodir" 13 | 14 | if [ -z "${1:-}" ]; then 15 | echo "unknown version: '${1:-}'" 16 | echo "First argument must be 'vim-8.2', 'vim-9.1', or 'nvim'." 17 | exit 1 18 | fi 19 | 20 | if [ -z "${2:-}" ]; then 21 | echo "file not set" 22 | echo "Second argument must be a Go file to benchmark, as 'filename:linenr'" 23 | exit 1 24 | fi 25 | 26 | vim=$1 27 | file="$(echo "$2" | cut -d : -f 1)" 28 | line="$(echo "$2" | cut -d : -f 2)" 29 | if [ -z "$line" -o "$line" = "$file" ]; then 30 | echo "Second argument must be a Go file to benchmark, as 'filename:linenr'" 31 | exit 1 32 | fi 33 | 34 | shift; shift 35 | export RUNBENCH_SETTINGS=$@ 36 | export RUNBENCH_OUT="$(mktemp -p "${TMPDIR:-/tmp}" vimgo-bench.XXXXX)" 37 | 38 | "$vimgodir/scripts/run-vim" $vim \ 39 | +"silent e $file" \ 40 | +"normal! ${line}G" \ 41 | -S ./scripts/runbench.vim 42 | 43 | echo "Report written to:" 44 | echo "$RUNBENCH_OUT" 45 | -------------------------------------------------------------------------------- /scripts/install-tools: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Install and setup a Vim or Neovim for running tests. 4 | # This should work on both GitHub Actions and people's desktop computers, and 5 | # be 100% independent from any system installed Vim. 6 | # 7 | 8 | set -euC 9 | 10 | vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) 11 | cd "$vimgodir" 12 | 13 | vim=${1:-} 14 | 15 | installdir="/tmp/vim-go-test/$1-install" 16 | 17 | # Make sure all Go tools and other dependencies are installed. 18 | echo "Installing Go binaries" 19 | export GOPATH=$installdir 20 | export GO111MODULE=on 21 | export PATH="${GOPATH}/bin:$PATH" 22 | "$vimgodir/scripts/run-vim" $vim +':silent :GoUpdateBinaries' +':qa' 23 | 24 | echo "Installing lint tools" 25 | ( 26 | mkdir -p "$installdir/share/vim/vimgo/pack/vim-go/start/" 27 | cd "$installdir/share/vim/vimgo/pack/vim-go/start/" 28 | [ -d "vim-vimhelplint" ] || git clone --depth 1 --quiet https://github.com/machakann/vim-vimhelplint 29 | [ -d "vim-vimlparser" ] || git clone --depth 1 --quiet https://github.com/ynkdir/vim-vimlparser 30 | [ -d "vim-vimlint" ] || git clone --depth 1 --quiet https://github.com/syngan/vim-vimlint 31 | ) 32 | 33 | echo "vim-go tools installed to: $installdir/share/vim/vimgo/pack/vim-go/start" 34 | 35 | # vim:ts=2:sts=2:sw=2:et 36 | -------------------------------------------------------------------------------- /autoload/go/test-fixtures/test/src/play/play_test.go: -------------------------------------------------------------------------------- 1 | package play 2 | 3 | import ( 4 | "sync" 5 | "testing" 6 | 7 | "vim-go.test/play/mock" 8 | ) 9 | 10 | func TestTopSubHelper(t *testing.T) { 11 | t.Run("sub", func(t *testing.T) { 12 | t.Log("log message") 13 | t.Error("sub badness") 14 | }) 15 | t.Error("badness") 16 | helper(t) 17 | } 18 | 19 | func TestMultiline(t *testing.T) { 20 | t.Error("this is an error\nand a second line, too") 21 | t.Error("\nthis is another error") 22 | } 23 | 24 | func TestSub(t *testing.T) { 25 | t.Run("indented", func(t *testing.T) { 26 | t.Error("this is a sub-test error\nand a second line, too") 27 | }) 28 | } 29 | 30 | func TestOK(t *testing.T) { 31 | t.Run("log", func(t *testing.T) { 32 | t.Log("goodness") 33 | }) 34 | } 35 | 36 | // TestMocked tests behavior similar to what users may experience when using 37 | // github.com/golang/mock/gomock. 38 | func TestMocked(t *testing.T) { 39 | mock.Fail(t) 40 | } 41 | 42 | func TestPanic(t *testing.T) { 43 | panic("worst ever") 44 | } 45 | 46 | func TestConcurrentPanic(t *testing.T) { 47 | var wg sync.WaitGroup 48 | wg.Add(1) 49 | go func() { 50 | panic("concurrent fail") 51 | wg.Done() 52 | }() 53 | wg.Wait() 54 | } 55 | 56 | func helper(t *testing.T) { 57 | t.Helper() 58 | t.Fatal("helper badness") 59 | } 60 | -------------------------------------------------------------------------------- /indent/gohtmltmpl.vim: -------------------------------------------------------------------------------- 1 | if exists("b:did_indent") 2 | finish 3 | endif 4 | 5 | runtime! indent/html.vim 6 | 7 | " Indent Golang HTML templates 8 | setlocal indentexpr=GetGoHTMLTmplIndent(v:lnum) 9 | setlocal indentkeys+==else,=end 10 | 11 | " Only define the function once. 12 | if exists("*GetGoHTMLTmplIndent") 13 | finish 14 | endif 15 | 16 | " don't spam the user when Vim is started in Vi compatibility mode 17 | let s:cpo_save = &cpo 18 | set cpo&vim 19 | 20 | function! GetGoHTMLTmplIndent(lnum) 21 | " Get HTML indent 22 | if exists('*HtmlIndent') 23 | let ind = HtmlIndent() 24 | else 25 | let ind = HtmlIndentGet(a:lnum) 26 | endif 27 | 28 | " The value of a single shift-width 29 | if exists('*shiftwidth') 30 | let sw = shiftwidth() 31 | else 32 | let sw = &sw 33 | endif 34 | 35 | " If need to indent based on last line 36 | let last_line = getline(a:lnum-1) 37 | if last_line =~ '^\s*{{-\=\s*\%(if\|else\|range\|with\|define\|block\).*}}' 38 | let ind += sw 39 | endif 40 | 41 | " End of FuncMap block 42 | let current_line = getline(a:lnum) 43 | if current_line =~ '^\s*{{-\=\s*\%(else\|end\).*}}' 44 | let ind -= sw 45 | endif 46 | 47 | return ind 48 | endfunction 49 | 50 | " restore Vi compatibility settings 51 | let &cpo = s:cpo_save 52 | unlet s:cpo_save 53 | 54 | " vim: sw=2 ts=2 et 55 | -------------------------------------------------------------------------------- /scripts/run-vim: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run a "bare" Vim with just vim-go and ignoring ~/.vim 4 | # 5 | 6 | set -euC 7 | vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) 8 | cd "$vimgodir" 9 | 10 | coverage=0 11 | while getopts "c" option; do 12 | case "$option" in 13 | c) coverage=1; ;; 14 | esac 15 | done 16 | shift $((OPTIND - 1)) 17 | 18 | if [ -z "${1:-}" ]; then 19 | echo "unknown version: '${1:-}'" 20 | echo "First argument must be 'vim-8.2', 'vim-9.1', or 'nvim'." 21 | exit 1 22 | fi 23 | 24 | dir="/tmp/vim-go-test/$1-install" 25 | export GOPATH=$dir 26 | export GO111MODULE=on 27 | export PATH="${GOPATH}/bin:$PATH" 28 | shift 29 | 30 | if [ ! -f "$dir/bin/vim" ]; then 31 | echo "$dir/bin/vim doesn't exist; did you install it with the install-vim script?" 32 | exit 1 33 | fi 34 | 35 | if [ $coverage -eq 1 ]; then 36 | covimerage -q run --report-file /tmp/vim-go-test/cov-profile.txt --append \ 37 | $dir/bin/vim --noplugin -u NONE -i NONE -N -n \ 38 | +"set shm+=WAFI rtp^=$vimgodir packpath=$dir/share/vim/vimgo" \ 39 | +'filetype plugin indent on' \ 40 | +'packloadall!' \ 41 | "$@" 42 | else 43 | $dir/bin/vim --noplugin -u NONE -i NONE -N -n \ 44 | +"set shm+=WAFI rtp^=$vimgodir packpath=$dir/share/vim/vimgo" \ 45 | +'filetype plugin indent on' \ 46 | +'packloadall!' \ 47 | "$@" 48 | fi 49 | 50 | 51 | # vim:ts=2:sts=2:sw=2:et 52 | -------------------------------------------------------------------------------- /autoload/go/extract_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_Extract() abort 6 | let l:wd = getcwd() 7 | try 8 | let l:tmp = gotest#write_file('a/a.go', [ 9 | \ 'package a', 10 | \ '', 11 | \ 'func f(v int) {', 12 | \ ' for i := 0; i < v; i++ {', 13 | \ " p\x1f" . 'rintln("outputting something")', 14 | \ ' println("i is ", i+1)', 15 | \ ' }', 16 | \ '}']) 17 | 18 | silent! execute "normal vj$\" 19 | 20 | call go#extract#Extract(line("'<"), line("'>")) 21 | 22 | let start = reltime() 23 | while &modified == 0 && reltimefloat(reltime(start)) < 10 24 | sleep 100m 25 | endwhile 26 | 27 | call gotest#assert_buffer(1, [ 28 | \ 'func f(v int) {', 29 | \ ' for i := 0; i < v; i++ {', 30 | \ ' newFunction(i)', 31 | \ ' }', 32 | \ '}', 33 | \ '', 34 | \ 'func newFunction(i int) {', 35 | \ ' println("outputting something")', 36 | \ ' println("i is ", i+1)', 37 | \ '}']) 38 | 39 | finally 40 | call go#util#Chdir(l:wd) 41 | call delete(l:tmp, 'rf') 42 | endtry 43 | endfunc 44 | 45 | " restore Vi compatibility settings 46 | let &cpo = s:cpo_save 47 | unlet s:cpo_save 48 | 49 | " vim: sw=2 ts=2 et 50 | -------------------------------------------------------------------------------- /ftdetect/gofiletype.vim: -------------------------------------------------------------------------------- 1 | " vint: -ProhibitAutocmdWithNoGroup 2 | 3 | " don't spam the user when Vim is started in Vi compatibility mode 4 | let s:cpo_save = &cpo 5 | set cpo&vim 6 | 7 | " Note: should not use augroup in ftdetect (see :help ftdetect) 8 | au BufRead,BufNewFile *.go setfiletype go 9 | au BufRead,BufNewFile *.s setfiletype asm 10 | au BufRead,BufNewFile *.tmpl set filetype=gohtmltmpl 11 | au BufRead,BufNewFile go.sum set filetype=gosum 12 | au BufRead,BufNewFile go.work.sum set filetype=gosum 13 | au BufRead,BufNewFile go.work set filetype=gowork 14 | 15 | " remove the autocommands for modsim3, and lprolog files so that their 16 | " highlight groups, syntax, etc. will not be loaded. *.MOD is included, so 17 | " that on case insensitive file systems the module2 autocmds will not be 18 | " executed. 19 | au! BufRead,BufNewFile *.mod,*.MOD 20 | " Set the filetype if the first non-comment and non-blank line starts with 21 | " 'module '. 22 | au BufRead,BufNewFile go.mod call s:gomod() 23 | 24 | fun! s:gomod() 25 | for l:i in range(1, line('$')) 26 | let l:l = getline(l:i) 27 | if l:l ==# '' || l:l[:1] ==# '//' 28 | continue 29 | endif 30 | 31 | if l:l =~# '^module .\+' 32 | setfiletype gomod 33 | endif 34 | 35 | break 36 | endfor 37 | endfun 38 | 39 | " restore Vi compatibility settings 40 | let &cpo = s:cpo_save 41 | unlet s:cpo_save 42 | 43 | " vim: sw=2 ts=2 et 44 | -------------------------------------------------------------------------------- /autoload/go/implements.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#implements#Implements(selected) abort 6 | let l:mode = go#config#ImplementsMode() 7 | if l:mode == 'gopls' 8 | if !go#config#GoplsEnabled() 9 | call go#util#EchoError("go_implements_mode is 'gopls', but gopls is disabled") 10 | endif 11 | let [l:line, l:col] = getpos('.')[1:2] 12 | let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col) 13 | let l:fname = expand('%:p') 14 | call go#lsp#Implements(l:fname, l:line, l:col, funcref('s:parse_output')) 15 | return 16 | else 17 | call go#util#EchoWarning('unknown value for g:go_implements_mode') 18 | endif 19 | endfunction 20 | 21 | " This uses Vim's errorformat to parse the output and put it into a quickfix 22 | " or locationlist. 23 | function! s:parse_output(exit_val, output) abort 24 | if a:exit_val 25 | call go#util#EchoError(a:output) 26 | return 27 | endif 28 | 29 | let errformat = ",%f:%l:%c:\ %m" 30 | let l:listtype = go#list#Type("GoImplements") 31 | call go#list#ParseFormat(l:listtype, errformat, a:output, 'implements', 0) 32 | 33 | let errors = go#list#Get(l:listtype) 34 | call go#list#Window(l:listtype, len(errors)) 35 | endfunction 36 | 37 | " restore Vi compatibility settings 38 | let &cpo = s:cpo_save 39 | unlet s:cpo_save 40 | 41 | " vim: sw=2 ts=2 et 42 | -------------------------------------------------------------------------------- /autoload/go/referrers.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#referrers#Referrers(selected) abort 6 | let l:mode = go#config#ReferrersMode() 7 | if l:mode == 'gopls' 8 | if !go#config#GoplsEnabled() 9 | call go#util#EchoError("go_referrers_mode is 'gopls', but gopls is disabled") 10 | return 11 | endif 12 | let [l:line, l:col] = getpos('.')[1:2] 13 | let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col) 14 | let l:fname = expand('%:p') 15 | call go#lsp#Referrers(l:fname, l:line, l:col, funcref('s:parse_output')) 16 | return 17 | else 18 | call go#util#EchoWarning('unknown value for g:go_referrers_mode') 19 | endif 20 | endfunction 21 | 22 | " This uses Vim's errorformat to parse the output and put it into a quickfix 23 | " or locationlist. 24 | function! s:parse_output(exit_val, output) abort 25 | if a:exit_val 26 | call go#util#EchoError(a:output) 27 | return 28 | endif 29 | 30 | let errformat = ",%f:%l:%c:\ %m" 31 | let l:listtype = go#list#Type("GoReferrers") 32 | call go#list#ParseFormat(l:listtype, errformat, a:output, 'referrers', 0) 33 | 34 | let errors = go#list#Get(l:listtype) 35 | call go#list#Window(l:listtype, len(errors)) 36 | endfunction 37 | " restore Vi compatibility settings 38 | let &cpo = s:cpo_save 39 | unlet s:cpo_save 40 | 41 | " vim: sw=2 ts=2 et 42 | -------------------------------------------------------------------------------- /autoload/go/uri.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#uri#Encode(value) abort 6 | return s:encode(a:value, '[^A-Za-z0-9_.~-]') 7 | endfunction 8 | 9 | function! go#uri#EncodePath(value) abort 10 | let l:separator = '/' 11 | if go#util#IsWin() 12 | let l:separator = '\\' 13 | endif 14 | return s:encode(a:value, '[^' . l:separator . 'A-Za-z0-9_.~-]') 15 | endfunction 16 | 17 | function! s:encode(value, unreserved) 18 | return substitute( 19 | \ a:value, 20 | \ a:unreserved, 21 | \ '\=s:encodechar(submatch(0))', 22 | \ 'g' 23 | \) 24 | endfunction 25 | 26 | function! go#uri#Decode(value) abort 27 | return substitute( 28 | \ a:value, 29 | \ '%\(\x\x\)', 30 | \ '\=s:decodehex(submatch(1))', 31 | \ 'g' 32 | \) 33 | endfunction 34 | 35 | function! s:encodechar(value) 36 | let l:idx = 0 37 | let l:encoded = '' 38 | while l:idx < strlen(a:value) 39 | let l:byte = strpart(a:value, l:idx, 1) 40 | let l:encoded = printf('%s%%%02X', l:encoded, char2nr(l:byte)) 41 | let l:idx += 1 42 | endwhile 43 | 44 | return l:encoded 45 | endfunction 46 | 47 | function! s:decodehex(value) 48 | return eval(printf('"\x%s"', a:value)) 49 | endfunction 50 | 51 | " restore Vi compatibility settings 52 | let &cpo = s:cpo_save 53 | unlet s:cpo_save 54 | 55 | " vim: sw=2 ts=2 et 56 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Use this template for all issues 4 | --- 5 | 10 | ### What did you do? (required: The issue will be **closed** when not provided) 11 | 12 | 15 | 16 | ### What did you expect to happen? 17 | 18 | ### What happened instead? 19 | 20 | ### Configuration (**MUST** fill this out): 21 | 22 | #### vim-go version: 23 | 24 | #### `vimrc` you used to reproduce: 25 | 30 | 31 |
vimrc 32 | 33 | ```vim 34 | 35 | ``` 36 |
37 | 38 | #### Vim version (first three lines from `:version`): 39 | 40 | 41 | #### Go version (`go version`): 42 | 43 | 44 | #### Go environment 45 |
go env Output:
46 | 
47 | 
48 | 
49 | 50 | #### gopls version 51 |
gopls version Output:
52 | 
53 | 
54 | 
55 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Use this template for all issues 4 | --- 5 | 10 | ### What did you do? (required: The issue will be **closed** when not provided) 11 | 12 | 15 | 16 | ### What did you expect to happen? 17 | 18 | ### What happened instead? 19 | 20 | ### Configuration (**MUST** fill this out): 21 | 22 | #### vim-go version: 23 | 24 | #### `vimrc` you used to reproduce: 25 | 30 | 31 |
vimrc 32 | 33 | ```vim 34 | 35 | ``` 36 |
37 | 38 | #### Vim version (first three lines from `:version`): 39 | 40 | 41 | #### Go version (`go version`): 42 | 43 | 44 | #### Go environment 45 |
go env Output:
46 | 
47 | 
48 | 
49 | 50 | #### gopls version 51 |
gopls version Output:
52 | 
53 | 
54 | 
55 | -------------------------------------------------------------------------------- /autoload/go/impl_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_impl() abort 6 | let l:wd = getcwd() 7 | try 8 | let g:go_gopls_enabled = 0 9 | let l:tmp = gotest#write_file('a/a.go', [ 10 | \ 'package a', 11 | \ '', 12 | \ '']) 13 | 14 | call go#impl#Impl('r', 'reader', 'io.Reader') 15 | call gotest#assert_buffer(1, [ 16 | \ 'func (r reader) Read(p []byte) (n int, err error) {', 17 | \ ' panic("not implemented") // TODO: Implement', 18 | \ '}']) 19 | finally 20 | call go#util#Chdir(l:wd) 21 | call delete(l:tmp, 'rf') 22 | endtry 23 | endfunc 24 | 25 | func! Test_impl_get() abort 26 | let l:wd = getcwd() 27 | try 28 | let g:go_gopls_enabled = 0 29 | let l:tmp = gotest#write_file('a/a.go', [ 30 | \ 'package a', 31 | \ '', 32 | \ 'type reader struct {}']) 33 | 34 | call go#impl#Impl('io.Reader') 35 | call gotest#assert_buffer(0, [ 36 | \ 'package a', 37 | \ '', 38 | \ 'type reader struct {}', 39 | \ '', 40 | \ 'func (r *reader) Read(p []byte) (n int, err error) {', 41 | \ ' panic("not implemented") // TODO: Implement', 42 | \ '}']) 43 | finally 44 | call go#util#Chdir(l:wd) 45 | call delete(l:tmp, 'rf') 46 | endtry 47 | endfunc 48 | 49 | " restore Vi compatibility settings 50 | let &cpo = s:cpo_save 51 | unlet s:cpo_save 52 | 53 | " vim: sw=2 ts=2 et 54 | -------------------------------------------------------------------------------- /autoload/go/calls_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | scriptencoding utf-8 6 | 7 | func! Test_Callers() abort 8 | let l:wd = getcwd() 9 | try 10 | let l:tmp = gotest#write_file('calls/caller.go', [ 11 | \ 'package main', 12 | \ '', 13 | \ 'import "fmt"', 14 | \ '', 15 | \ 'func Quux() {}', 16 | \ '', 17 | \ 'func main() {', 18 | \ "\tQ\x1fuux()", 19 | \ "\tQuux()", 20 | \ '', 21 | \ "\tfmt.Println(\"vim-go\")", 22 | \ '}', 23 | \ ]) 24 | 25 | let l:expected = [ 26 | \ {'lnum': 8, 'bufnr': bufnr(''), 'col': 2, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'main'}, 27 | \ {'lnum': 9, 'bufnr': bufnr(''), 'col': 2, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'main'}, 28 | \ ] 29 | 30 | call go#calls#Callers() 31 | 32 | let l:actual = getloclist(0) 33 | let l:start = reltime() 34 | while len(l:actual) != len(l:expected) && reltimefloat(reltime(l:start)) < 10 35 | sleep 100m 36 | let l:actual = getloclist(0) 37 | endwhile 38 | 39 | call gotest#assert_quickfix(l:actual, l:expected) 40 | finally 41 | call go#util#Chdir(l:wd) 42 | call delete(l:tmp, 'rf') 43 | endtry 44 | endfunc 45 | 46 | " restore Vi compatibility settings 47 | let &cpo = s:cpo_save 48 | unlet s:cpo_save 49 | 50 | " vim: sw=2 ts=2 et 51 | -------------------------------------------------------------------------------- /autoload/go/lsp/completionitemkind.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | let s:Text = 1 6 | let s:Method = 2 7 | let s:Function = 3 8 | let s:Constructor = 4 9 | let s:Field = 5 10 | let s:Variable = 6 11 | let s:Class = 7 12 | let s:Interface = 8 13 | let s:Module = 9 14 | let s:Property = 10 15 | let s:Unit = 11 16 | let s:Value = 12 17 | let s:Enum = 13 18 | let s:Keyword = 14 19 | let s:Snippet = 15 20 | let s:Color = 16 21 | let s:File = 17 22 | let s:Reference = 18 23 | let s:Folder = 19 24 | let s:EnumMember = 20 25 | let s:Constant = 21 26 | let s:Struct = 22 27 | let s:Event = 23 28 | let s:Operator = 24 29 | let s:TypeParameter = 25 30 | 31 | function! go#lsp#completionitemkind#Vim(kind) abort 32 | if a:kind == s:Method || a:kind == s:Function || a:kind == s:Constructor 33 | return 'f' 34 | elseif a:kind == s:Variable || a:kind == s:Constant 35 | return 'v' 36 | elseif a:kind == s:Field || a:kind == s:Property 37 | return 'm' 38 | elseif a:kind == s:Class || a:kind == s:Interface || a:kind == s:Struct 39 | return 't' 40 | endif 41 | endfunction 42 | 43 | function! go#lsp#completionitemkind#IsFunction(kind) abort 44 | if a:kind == s:Function 45 | return 1 46 | endif 47 | 48 | return 0 49 | endfunction 50 | 51 | function! go#lsp#completionitemkind#IsMethod(kind) abort 52 | if a:kind == s:Method 53 | return 1 54 | endif 55 | 56 | return 0 57 | endfunction 58 | 59 | " restore Vi compatibility settings 60 | let &cpo = s:cpo_save 61 | unlet s:cpo_save 62 | 63 | " vim: sw=2 ts=2 et 64 | -------------------------------------------------------------------------------- /autoload/go/uri_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | scriptencoding utf-8 6 | 7 | func! Test_EncodePath_simple() abort 8 | let l:uri = '/simple/foo' 9 | let l:expected = '/simple/foo' 10 | 11 | let l:actual = go#uri#EncodePath(l:uri) 12 | call assert_equal(l:expected, l:actual) 13 | endfunc 14 | 15 | func! Test_EncodePath_multibyte() abort 16 | let l:uri = '/multi-byte/⌘⌘' 17 | let l:expected = '/multi-byte/%E2%8C%98%E2%8C%98' 18 | 19 | let l:actual = go#uri#EncodePath(l:uri) 20 | call assert_equal(l:expected, l:actual) 21 | endfunc 22 | 23 | func! Test_Decode_simple() abort 24 | let l:uri = '/simple/foo' 25 | let l:expected = '/simple/foo' 26 | 27 | let l:actual = go#uri#Decode(l:uri) 28 | call assert_equal(l:expected, l:actual) 29 | endfunc 30 | 31 | func! Test_Decode_multibyte() abort 32 | let l:uri = '/multi-byte/%E2%8C%98%E2%8C%98' 33 | let l:expected = '/multi-byte/⌘⌘' 34 | let l:actual = go#uri#Decode(l:uri) 35 | call assert_equal(l:expected, l:actual) 36 | endfunc 37 | 38 | func! Test_Roundtrip_simple() abort 39 | let l:expected = '/simple/foo' 40 | 41 | let l:actual = go#uri#Decode(go#uri#EncodePath(l:expected)) 42 | call assert_equal(l:expected, l:actual) 43 | endfunc 44 | 45 | func! Test_Roundtrip_multibyte() abort 46 | let l:expected = '/multi-byte/⌘⌘' 47 | 48 | let l:actual = go#uri#Decode(go#uri#EncodePath(l:expected)) 49 | call assert_equal(l:expected, l:actual) 50 | endfunc 51 | 52 | " restore Vi compatibility settings 53 | let &cpo = s:cpo_save 54 | unlet s:cpo_save 55 | 56 | " vim: sw=2 ts=2 et 57 | -------------------------------------------------------------------------------- /autoload/go/lsp/lsp_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | scriptencoding utf-8 6 | 7 | function! Test_PositionOf_Simple() 8 | let l:actual = go#lsp#lsp#PositionOf("just ascii", 3) 9 | call assert_equal(4, l:actual) 10 | endfunc 11 | 12 | function! Test_PositionOf_Start() 13 | let l:str = 'abcd' 14 | let l:actual = go#lsp#lsp#PositionOf(l:str, 0) 15 | call assert_equal(l:actual, 1) 16 | " subtract one, because PositionOf returns a one-based cursor position while 17 | " string indices are zero based. 18 | call assert_equal(l:str[l:actual-1], 'a') 19 | endfunc 20 | 21 | function! Test_PositionOf_End() 22 | let l:str = 'abcd' 23 | let l:actual = go#lsp#lsp#PositionOf(l:str, 3) 24 | call assert_equal(l:actual, 4) 25 | " subtract one, because PositionOf returns a one-based cursor position and 26 | " while string indices are zero based. 27 | call assert_equal(l:str[l:actual-1], 'd') 28 | endfunc 29 | 30 | function! Test_PositionOf_MultiByte() 31 | " ⌘ is U+2318, which encodes to three bytes in utf-8 and 1 code unit in 32 | " utf-16. 33 | let l:actual = go#lsp#lsp#PositionOf("⌘⌘ foo", 3) 34 | call assert_equal(8, l:actual) 35 | endfunc 36 | 37 | function! Test_PositionOf_MultipleCodeUnit() 38 | " 𐐀 is U+10400, which encodes to 4 bytes in utf-8 and 2 code units in 39 | " utf-16. 40 | let l:actual = go#lsp#lsp#PositionOf("𐐀 bar", 3) 41 | call assert_equal(6, l:actual) 42 | endfunction 43 | 44 | 45 | " restore Vi compatibility settings 46 | let &cpo = s:cpo_save 47 | unlet s:cpo_save 48 | 49 | " vim: sw=2 ts=2 et 50 | -------------------------------------------------------------------------------- /ftplugin/go/tagbar.vim: -------------------------------------------------------------------------------- 1 | " Check if tagbar is installed under plugins or is directly under rtp 2 | " this covers pathogen + Vundle/Bundle 3 | " 4 | " Also make sure the ctags command exists 5 | " 6 | if !executable('ctags') 7 | finish 8 | elseif globpath(&rtp, 'plugin/tagbar.vim') == "" 9 | finish 10 | endif 11 | 12 | " don't spam the user when Vim is started in Vi compatibility mode 13 | let s:cpo_save = &cpo 14 | set cpo&vim 15 | 16 | if !exists("g:go_gotags_bin") 17 | let g:go_gotags_bin = "gotags" 18 | endif 19 | 20 | 21 | function! s:SetTagbar() 22 | let bin_path = go#path#CheckBinPath(g:go_gotags_bin) 23 | if empty(bin_path) 24 | return 25 | endif 26 | 27 | if !exists("g:tagbar_type_go") 28 | let g:tagbar_type_go = { 29 | \ 'ctagstype' : 'go', 30 | \ 'kinds' : [ 31 | \ 'p:package', 32 | \ 'i:imports', 33 | \ 'c:constants', 34 | \ 'v:variables', 35 | \ 't:types', 36 | \ 'n:interfaces', 37 | \ 'w:fields', 38 | \ 'e:embedded', 39 | \ 'm:methods', 40 | \ 'r:constructor', 41 | \ 'f:functions' 42 | \ ], 43 | \ 'sro' : '.', 44 | \ 'kind2scope' : { 45 | \ 't' : 'ctype', 46 | \ 'n' : 'ntype' 47 | \ }, 48 | \ 'scope2kind' : { 49 | \ 'ctype' : 't', 50 | \ 'ntype' : 'n' 51 | \ }, 52 | \ 'ctagsbin' : bin_path, 53 | \ 'ctagsargs' : '-sort -silent' 54 | \ } 55 | endif 56 | endfunction 57 | 58 | 59 | call s:SetTagbar() 60 | 61 | " restore Vi compatibility settings 62 | let &cpo = s:cpo_save 63 | unlet s:cpo_save 64 | 65 | " vim: sw=2 ts=2 et 66 | -------------------------------------------------------------------------------- /autoload/go/promise.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | scriptencoding utf-8 6 | 7 | " New returns a promise. A promise's primary purpose is to make async jobs 8 | " synchronous by awaiting fn. 9 | " 10 | " A promise is a dictionary with two keys: 11 | " 'wrapper': 12 | " A function that wraps fn. It can be used in place of fn. 13 | " 'await': 14 | " A function that waits for wrapper to be called and returns the value 15 | " returned by fn. Returns default if timeout expires. 16 | function! go#promise#New(fn, timeout, default) abort 17 | let l:state = {} 18 | 19 | " explicitly bind to state so that within l:promise's methods, self will 20 | " always refer to state. See :help Partial for more information. 21 | return { 22 | \ 'wrapper': function('s:wrapper', [a:fn, a:default], l:state), 23 | \ 'await': function('s:await', [a:timeout, a:default], l:state), 24 | \ } 25 | endfunction 26 | 27 | function! s:wrapper(fn, default, ...) dict 28 | try 29 | let self.retval = call(a:fn, a:000) 30 | catch 31 | let self.retval = substitute(v:exception, '^Vim', '', '') 32 | let self.exception = 1 33 | endtry 34 | return self.retval 35 | endfunction 36 | 37 | function! s:await(timeout, default) dict 38 | let l:timer = timer_start(a:timeout, function('s:setretval', [a:default], self)) 39 | while !has_key(self, 'retval') 40 | sleep 50m 41 | endwhile 42 | call timer_stop(l:timer) 43 | 44 | if get(self, 'exception', 0) 45 | throw self.retval 46 | endif 47 | return self.retval 48 | endfunction 49 | 50 | function! s:setretval(val, timer) dict 51 | let self.retval = a:val 52 | endfunction 53 | 54 | " restore Vi compatibility settings 55 | let &cpo = s:cpo_save 56 | unlet s:cpo_save 57 | 58 | " vim: sw=2 ts=2 et 59 | -------------------------------------------------------------------------------- /autoload/go/job_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_JobDirWithSpaces() 6 | if !go#util#has_job() 7 | return 8 | endif 9 | 10 | let l:wd = getcwd() 11 | try 12 | let g:go_gopls_enabled = 0 13 | let l:filename = 'job/dir has spaces/main.go' 14 | let l:tmp = gotest#load_fixture(l:filename) 15 | call go#util#Chdir(printf('%s/src/job/dir has spaces', l:tmp)) 16 | call go#util#Exec(['go', 'mod', 'init', 'vim-go.test/job']) 17 | 18 | " set the compiler type so that the errorformat option will be set 19 | " correctly. 20 | compiler go 21 | 22 | let expected = [{'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'undefined: notafunc'}] 23 | " clear the quickfix lists 24 | call setqflist([], 'r') 25 | 26 | " go build discards any results when it compiles multiple packages. So we 27 | " pass the `errors` package just as a placeholder with the current folder 28 | " (indicated with '.'). 29 | let l:cmd = ['go', 'build', '.', 'errors'] 30 | 31 | let l:complete = go#promise#New(function('s:complete'), 10000, '') 32 | call go#job#Spawn(l:cmd, { 33 | \ 'for': 'GoBuild', 34 | \ 'complete': l:complete.wrapper, 35 | \ 'statustype': 'build' 36 | \}) 37 | 38 | let l:out = l:complete.await() 39 | 40 | let actual = getqflist() 41 | 42 | call gotest#assert_quickfix(actual, l:expected) 43 | finally 44 | call go#util#Chdir(l:wd) 45 | call delete(l:tmp, 'rf') 46 | endtry 47 | endfunc 48 | 49 | func! s:complete(job, exit_code, messages) 50 | return a:messages 51 | endfunc 52 | 53 | " restore Vi compatibility settings 54 | let &cpo = s:cpo_save 55 | unlet s:cpo_save 56 | 57 | " vim: sw=2 ts=2 et 58 | -------------------------------------------------------------------------------- /autoload/go/template_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_TemplateCreate() abort 6 | let g:go_gopls_enabled = 0 7 | let l:wd = getcwd() 8 | try 9 | let l:tmp = gotest#write_file('foo/empty.txt', ['']) 10 | 11 | edit foo/bar.go 12 | 13 | call gotest#assert_buffer(1, [ 14 | \ 'func main() {', 15 | \ '\tfmt.Println("vim-go")', 16 | \ '}']) 17 | finally 18 | call go#util#Chdir(l:wd) 19 | call delete(l:tmp, 'rf') 20 | endtry 21 | 22 | let l:wd = getcwd() 23 | try 24 | let l:tmp = gotest#write_file('foo/empty.txt', ['']) 25 | edit foo/bar_test.go 26 | 27 | call gotest#assert_buffer(1, [ 28 | \ 'func TestHelloWorld(t *testing.T) {', 29 | \ '\t// t.Fatal("not implemented")', 30 | \ '}']) 31 | finally 32 | call go#util#Chdir(l:wd) 33 | call delete(l:tmp, 'rf') 34 | endtry 35 | endfunc 36 | 37 | func! Test_TemplateCreate_UsePkg() abort 38 | let l:wd = getcwd() 39 | try 40 | let g:go_gopls_enabled = 0 41 | let l:tmp = gotest#write_file('foo/empty.txt', ['']) 42 | 43 | let g:go_template_use_pkg = 1 44 | edit foo/bar.go 45 | 46 | call gotest#assert_buffer(0, ['package foo']) 47 | finally 48 | call go#util#Chdir(l:wd) 49 | call delete(l:tmp, 'rf') 50 | endtry 51 | endfunc 52 | 53 | func! Test_TemplateCreate_PackageExists() abort 54 | let l:wd = getcwd() 55 | try 56 | let g:go_gopls_enabled = 0 57 | let l:tmp = gotest#write_file('quux/quux.go', ['package foo']) 58 | 59 | edit quux/bar.go 60 | 61 | call gotest#assert_buffer(0, ['package foo']) 62 | finally 63 | call go#util#Chdir(l:wd) 64 | call delete(l:tmp, 'rf') 65 | endtry 66 | endfunc 67 | 68 | " restore Vi compatibility settings 69 | let &cpo = s:cpo_save 70 | unlet s:cpo_save 71 | 72 | " vim: sw=2 ts=2 et 73 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: [push, pull_request] 3 | jobs: 4 | lint: 5 | name: lint 6 | runs-on: ubuntu-22.04 7 | steps: 8 | - name: set up python 9 | uses: actions/setup-python@v5.5.0 10 | with: 11 | python-version: 3.7 12 | - name: install vim-vint 13 | run: | 14 | python -m pip install --upgrade pip 15 | pip install vim-vint pathlib 16 | - name: checkout 17 | uses: actions/checkout@v2.1.0 18 | - name: install vim 19 | run: $GITHUB_WORKSPACE/scripts/install-vim vim-9.1 20 | - name: install tools 21 | run: $GITHUB_WORKSPACE/scripts/install-tools vim-9.1 22 | - name: lint 23 | run: $GITHUB_WORKSPACE/scripts/lint vim-9.1 24 | test: 25 | name: test 26 | runs-on: ubuntu-22.04 27 | strategy: 28 | fail-fast: false 29 | matrix: 30 | go: ['1.23','1.24'] 31 | vim: ['vim-8.2', 'vim-9.1', 'nvim'] 32 | steps: 33 | - name: setup Go 34 | uses: actions/setup-go@v2.1.3 35 | with: 36 | go-version: ${{ matrix.go }} 37 | - name: set up python 38 | uses: actions/setup-python@v5.5.0 39 | with: 40 | python-version: 3.7 41 | - name: install covimerage 42 | run: | 43 | python -m pip install --upgrade pip 44 | pip install click==7.1.2 covimerage==0.2.1 codecov pathlib 45 | - name: checkout 46 | uses: actions/checkout@v2.1.0 47 | - name: install vim 48 | run: $GITHUB_WORKSPACE/scripts/install-vim ${{ matrix.vim }} 49 | - name: install tools 50 | run: $GITHUB_WORKSPACE/scripts/install-tools ${{ matrix.vim }} 51 | - name: test 52 | run: $GITHUB_WORKSPACE/scripts/test -c ${{ matrix.vim }} 53 | - uses: codecov/codecov-action@v1 54 | with: 55 | # token is not required for public repos 56 | #token: ${{ secrets.CODECOV_TOKEN }} 57 | file: $GITHUB_WORKSPACE/coverage.xml 58 | flags: unittests 59 | name: vim-go 60 | fail_ci_if_error: false 61 | -------------------------------------------------------------------------------- /autoload/go/issue.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | let s:templatepath = go#util#Join(resolve(expand(':p:h:h:h')), '.github', 'issue_template.md') 6 | 7 | function! go#issue#New() abort 8 | let body = go#uri#Encode(s:issuebody()) 9 | let url = "https://github.com/fatih/vim-go/issues/new?body=" . l:body 10 | call go#util#OpenBrowser(l:url) 11 | endfunction 12 | 13 | function! s:issuebody() abort 14 | let lines = readfile(s:templatepath) 15 | 16 | let rtrimpat = '[[:space:]]\+$' 17 | let body = [] 18 | for l in lines 19 | let body = add(body, l) 20 | 21 | if l =~ '^' 25 | let [out, err] = go#util#Exec(['go', 'version']) 26 | let body = add(body, substitute(l:out, rtrimpat, '', '')) 27 | elseif l =~ '^' 28 | let [out, err] = go#util#ExecInDir(['go', 'env']) 29 | let body = add(body, substitute(l:out, rtrimpat, '', '')) 30 | elseif l=~ '^' 31 | let [out, err] = go#util#Exec(['gopls', 'version']) 32 | let body = add(body, substitute(l:out, rtrimpat, '', '')) 33 | endif 34 | endfor 35 | 36 | let body = add(body, "\n#### vim-go configuration:\n
vim-go configuration
")
37 | 
38 |   for k in keys(g:)
39 |     if k =~ '^go_'
40 |       let body = add(body, 'g:' . k . ' = ' . string(get(g:, k)))
41 |     endif
42 |   endfor
43 | 
44 |   let body = add(body, '
') 45 | 46 | let body = add(body, printf("\n#### filetype detection configuration:\n
filetype detection
%s", execute('filetype')))
47 |   let body = add(body, '
') 48 | 49 | return join(body, "\n") 50 | endfunction 51 | 52 | " restore Vi compatibility settings 53 | let &cpo = s:cpo_save 54 | unlet s:cpo_save 55 | 56 | " vim: sw=2 ts=2 et 57 | -------------------------------------------------------------------------------- /ftplugin/go/snippets.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | if exists("g:go_loaded_gosnippets") 6 | finish 7 | endif 8 | let g:go_loaded_gosnippets = 1 9 | 10 | function! s:GoUltiSnips() abort 11 | if get(g:, 'did_plugin_ultisnips') isnot 1 12 | return 13 | endif 14 | 15 | if !exists("g:UltiSnipsSnippetDirectories") 16 | let g:UltiSnipsSnippetDirectories = ["gosnippets/UltiSnips"] 17 | else 18 | let g:UltiSnipsSnippetDirectories += ["gosnippets/UltiSnips"] 19 | endif 20 | endfunction 21 | 22 | function! s:GoNeosnippet() abort 23 | if get(g:, 'loaded_neosnippet') isnot 1 24 | return 25 | endif 26 | 27 | let g:neosnippet#enable_snipmate_compatibility = 1 28 | 29 | let l:gosnippets_dir = globpath(&rtp, 'gosnippets/snippets') 30 | if type(g:neosnippet#snippets_directory) == type([]) 31 | let g:neosnippet#snippets_directory += [l:gosnippets_dir] 32 | elseif type(g:neosnippet#snippets_directory) == type("") 33 | if strlen(g:neosnippet#snippets_directory) > 0 34 | let g:neosnippet#snippets_directory = g:neosnippet#snippets_directory . "," . l:gosnippets_dir 35 | else 36 | let g:neosnippet#snippets_directory = l:gosnippets_dir 37 | endif 38 | endif 39 | endfunction 40 | 41 | function! s:GoMinisnip() abort 42 | if get(g:, 'loaded_minisnip') isnot 1 43 | return 44 | endif 45 | 46 | if exists('g:minisnip_dir') 47 | let g:minisnip_dir .= go#util#PathListSep() . globpath(&rtp, 'gosnippets/minisnip') 48 | else 49 | let g:minisnip_dir = globpath(&rtp, 'gosnippets/minisnip') 50 | endif 51 | endfunction 52 | 53 | 54 | let s:engine = go#config#SnippetEngine() 55 | if s:engine is? 'ultisnips' 56 | call s:GoUltiSnips() 57 | elseif s:engine is? 'neosnippet' 58 | call s:GoNeosnippet() 59 | elseif s:engine is? 'minisnip' 60 | call s:GoMinisnip() 61 | endif 62 | 63 | " restore Vi compatibility settings 64 | let &cpo = s:cpo_save 65 | unlet s:cpo_save 66 | 67 | " vim: sw=2 ts=2 et 68 | -------------------------------------------------------------------------------- /autoload/go/lsp/lsp.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | " go#lsp#lsp#Position returns the LSP text position. If no arguments are 6 | " provided, the cursor position is assumed. Otherwise, there should be two 7 | " arguments: the line and the column. 8 | function! go#lsp#lsp#Position(...) 9 | if a:0 < 2 10 | let [l:line, l:col] = getpos('.')[1:2] 11 | else 12 | let l:line = a:1 13 | let l:col = a:2 14 | endif 15 | 16 | " LSP uses 0-based lines. 17 | return [l:line - 1, s:character(l:line, l:col)] 18 | endfunction 19 | 20 | function! s:strlen(str) abort 21 | let l:runes = split(a:str, '\zs') 22 | return len(l:runes) + len(filter(l:runes, 'char2nr(v:val)>=0x10000')) 23 | endfunction 24 | 25 | function! s:character(line, col) abort 26 | return s:strlen(getline(a:line)[:col([a:line, a:col - 1])]) 27 | endfunction 28 | 29 | " go#lsp#PositionOf returns len(content[0:units]) where units is utf-16 code 30 | " units. This is mostly useful for converting zero-based LSP text position to 31 | " vim one-based position. 32 | function! go#lsp#lsp#PositionOf(content, units, ...) abort 33 | if len(a:content) is 0 34 | return 0 35 | endif 36 | 37 | let l:remaining = a:units 38 | let l:str = '' 39 | for l:rune in split(a:content, '\zs') 40 | if l:remaining <= 0 41 | break 42 | endif 43 | let l:remaining -= 1 44 | if char2nr(l:rune) >= 0x10000 45 | let l:remaining -= 1 46 | endif 47 | let l:str = l:str . l:rune 48 | endfor 49 | 50 | return len(l:str) + 1 51 | endfunction 52 | 53 | function! go#lsp#lsp#SeverityToErrorType(severity) abort 54 | if a:severity == 1 55 | return 'E' 56 | elseif a:severity == 2 57 | return 'W' 58 | elseif a:severity == 3 59 | return 'I' 60 | elseif a:severity == 4 61 | return 'I' 62 | endif 63 | 64 | return '' 65 | endfunction 66 | 67 | " restore Vi compatibility settings 68 | let &cpo = s:cpo_save 69 | unlet s:cpo_save 70 | 71 | " vim: sw=2 ts=2 et 72 | -------------------------------------------------------------------------------- /autoload/go/fmt_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_run_fmt() abort 6 | let g:go_gopls_enabled = 0 7 | let actual_file = tempname() 8 | call writefile(readfile("test-fixtures/fmt/hello.go"), actual_file) 9 | 10 | let expected = join(readfile("test-fixtures/fmt/hello_golden.go"), "\n") 11 | 12 | " run our code 13 | call go#fmt#run("gofmt", actual_file, "test-fixtures/fmt/hello.go") 14 | 15 | " this should now contain the formatted code 16 | let actual = join(readfile(actual_file), "\n") 17 | 18 | call assert_equal(expected, actual) 19 | endfunc 20 | 21 | func! Test_update_file() abort 22 | let g:go_gopls_enabled = 0 23 | let expected = join(readfile("test-fixtures/fmt/hello_golden.go"), "\n") 24 | let source_file = tempname() 25 | call writefile(readfile("test-fixtures/fmt/hello_golden.go"), source_file) 26 | 27 | let target_file = tempname() 28 | call writefile([""], target_file) 29 | 30 | " update_file now 31 | call go#fmt#update_file(source_file, target_file) 32 | 33 | " this should now contain the formatted code 34 | let actual = join(readfile(target_file), "\n") 35 | 36 | call assert_equal(expected, actual) 37 | endfunc 38 | 39 | func! Test_goimports() abort 40 | let g:go_gopls_enabled = 0 41 | let $GOPATH = printf('%s/%s', fnamemodify(getcwd(), ':p'), 'test-fixtures/fmt') 42 | let actual_file = tempname() 43 | call writefile(readfile("test-fixtures/fmt/src/imports/goimports.go"), actual_file) 44 | 45 | let expected = join(readfile("test-fixtures/fmt/src/imports/goimports_golden.go"), "\n") 46 | 47 | " run our code 48 | call go#fmt#run("goimports", actual_file, "test-fixtures/fmt/src/imports/goimports.go") 49 | 50 | " this should now contain the formatted code 51 | let actual = join(readfile(actual_file), "\n") 52 | 53 | call assert_equal(expected, actual) 54 | endfunc 55 | 56 | " restore Vi compatibility settings 57 | let &cpo = s:cpo_save 58 | unlet s:cpo_save 59 | 60 | " vim: sw=2 ts=2 et 61 | -------------------------------------------------------------------------------- /autoload/go/complete.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | " go#complete#GoInfo returns the description of the identifier under the 6 | " cursor. 7 | function! go#complete#GetInfo() abort 8 | return go#lsp#GetInfo() 9 | endfunction 10 | 11 | function! go#complete#Complete(findstart, base) abort 12 | if !go#config#GoplsEnabled() 13 | return -3 14 | endif 15 | 16 | let l:state = {'done': 0, 'matches': [], 'start': -1} 17 | 18 | function! s:handler(state, start, matches) abort dict 19 | let a:state.start = a:start 20 | let a:state.matches = a:matches 21 | let a:state.done = 1 22 | endfunction 23 | 24 | "findstart = 1 when we need to get the start of the match 25 | if a:findstart == 1 26 | let [l:line, l:col] = getpos('.')[1:2] 27 | let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col-1) 28 | let l:completion = go#lsp#Completion(expand('%:p'), l:line, l:col, funcref('s:handler', [l:state])) 29 | if l:completion 30 | return -3 31 | endif 32 | 33 | while !l:state.done 34 | sleep 10m 35 | endwhile 36 | 37 | if len(l:state.matches) == 0 38 | " no matches. cancel and leave completion mode. 39 | call go#util#EchoInfo("no matches") 40 | return -3 41 | endif 42 | 43 | let s:completions = l:state.matches 44 | 45 | return go#lsp#lsp#PositionOf(getline(l:line+1), l:state.start-1) 46 | else "findstart = 0 when we need to return the list of completions 47 | return s:completions 48 | endif 49 | endfunction 50 | 51 | function! go#complete#ToggleAutoTypeInfo() abort 52 | if go#config#AutoTypeInfo() 53 | call go#config#SetAutoTypeInfo(0) 54 | call go#util#EchoProgress("auto type info disabled") 55 | else 56 | call go#config#SetAutoTypeInfo(1) 57 | call go#util#EchoProgress("auto type info enabled") 58 | endif 59 | call go#auto#update_autocmd() 60 | endfunction 61 | 62 | " restore Vi compatibility settings 63 | let &cpo = s:cpo_save 64 | unlet s:cpo_save 65 | 66 | " vim: sw=2 ts=2 et 67 | -------------------------------------------------------------------------------- /autoload/go/tags_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! TestAddTags() abort 6 | let l:wd = getcwd() 7 | try 8 | let g:go_gopls_enabled = 0 9 | let l:tmp = gotest#load_fixture('tags/add_all_input.go') 10 | silent call go#tags#run(0, 0, 40, "add", bufname(''), 1) 11 | call gotest#assert_fixture('tags/add_all_golden.go') 12 | finally 13 | call go#util#Chdir(l:wd) 14 | call delete(l:tmp, 'rf') 15 | endtry 16 | endfunc 17 | 18 | 19 | func! TestAddTags_WithOptions() abort 20 | let l:wd = getcwd() 21 | try 22 | let g:go_gopls_enabled = 0 23 | let l:tmp = gotest#load_fixture('tags/add_all_input.go') 24 | silent call go#tags#run(0, 0, 40, "add", bufname(''), 1, 'json,omitempty') 25 | call gotest#assert_fixture('tags/add_all_golden_options.go') 26 | finally 27 | call go#util#Chdir(l:wd) 28 | call delete(l:tmp, 'rf') 29 | endtry 30 | endfunc 31 | 32 | func! TestAddTags_AddOptions() abort 33 | let l:wd = getcwd() 34 | try 35 | let g:go_gopls_enabled = 0 36 | let l:tmp = gotest#load_fixture('tags/add_all_input.go') 37 | silent call go#tags#run(0, 0, 40, "add", bufname(''), 1, 'json') 38 | call gotest#assert_fixture('tags/add_all_golden.go') 39 | silent call go#tags#run(0, 0, 40, "add", bufname(''), 1, 'json,omitempty') 40 | call gotest#assert_fixture('tags/add_all_golden_options.go') 41 | finally 42 | call go#util#Chdir(l:wd) 43 | call delete(l:tmp, 'rf') 44 | endtry 45 | endfunc 46 | 47 | func! Test_remove_tags() abort 48 | let l:wd = getcwd() 49 | try 50 | let g:go_gopls_enabled = 0 51 | let l:tmp = gotest#load_fixture('tags/remove_all_input.go') 52 | silent call go#tags#run(0, 0, 40, "remove", bufname(''), 1) 53 | call gotest#assert_fixture('tags/remove_all_golden.go') 54 | finally 55 | call go#util#Chdir(l:wd) 56 | call delete(l:tmp, 'rf') 57 | endtry 58 | endfunc 59 | 60 | " restore Vi compatibility settings 61 | let &cpo = s:cpo_save 62 | unlet s:cpo_save 63 | 64 | " vim:ts=2:sts=2:sw=2:et 65 | -------------------------------------------------------------------------------- /autoload/go/asmfmt.vim: -------------------------------------------------------------------------------- 1 | " asmfmt.vim: Vim command to format Go asm files with asmfmt 2 | " (github.com/klauspost/asmfmt). 3 | " 4 | " This filetype plugin adds new commands for asm buffers: 5 | " 6 | " :Fmt 7 | " 8 | " Filter the current asm buffer through asmfmt. 9 | " It tries to preserve cursor position and avoids 10 | " replacing the buffer with stderr output. 11 | " 12 | " Options: 13 | " 14 | " g:go_asmfmt_autosave [default=0] 15 | " 16 | " Flag to automatically call :Fmt when file is saved. 17 | 18 | " don't spam the user when Vim is started in Vi compatibility mode 19 | let s:cpo_save = &cpo 20 | set cpo&vim 21 | 22 | let s:got_fmt_error = 0 23 | 24 | " This is a trimmed-down version of the logic in fmt.vim. 25 | 26 | function! go#asmfmt#Format() abort 27 | " Save state. 28 | let l:curw = winsaveview() 29 | 30 | " Write the current buffer to a tempfile. 31 | let l:tmpname = tempname() 32 | call writefile(go#util#GetLines(), l:tmpname) 33 | 34 | " Run asmfmt. 35 | let [l:out, l:err] = go#util#Exec(['asmfmt', '-w', l:tmpname]) 36 | if l:err 37 | call go#util#EchoError(l:out) 38 | return 39 | endif 40 | 41 | " Remove undo point caused by BufWritePre. 42 | try | silent undojoin | catch | endtry 43 | 44 | " Replace the current file with the temp file; then reload the buffer. 45 | let old_fileformat = &fileformat 46 | 47 | " save old file permissions 48 | let original_fperm = getfperm(expand('%')) 49 | call rename(l:tmpname, expand('%')) 50 | 51 | " restore old file permissions 52 | call setfperm(expand('%'), original_fperm) 53 | silent edit! 54 | let &fileformat = old_fileformat 55 | let &syntax = &syntax 56 | 57 | " Restore the cursor/window positions. 58 | call winrestview(l:curw) 59 | endfunction 60 | 61 | function! go#asmfmt#ToggleAsmFmtAutoSave() abort 62 | if go#config#AsmfmtAutosave() 63 | call go#config#SetAsmfmtAutosave(1) 64 | call go#util#EchoProgress("auto asmfmt enabled") 65 | return 66 | end 67 | 68 | call go#config#SetAsmfmtAutosave(0) 69 | call go#util#EchoProgress("auto asmfmt disabled") 70 | endfunction 71 | 72 | " restore Vi compatibility settings 73 | let &cpo = s:cpo_save 74 | unlet s:cpo_save 75 | 76 | " vim: sw=2 ts=2 et 77 | -------------------------------------------------------------------------------- /autoload/go/indent_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_indent_raw_string() abort 6 | " The goRawString discovery requires that syntax be enabled. 7 | syntax on 8 | let g:go_gopls_enabled = 0 9 | 10 | let l:wd = getcwd() 11 | try 12 | let l:dir= gotest#write_file('indent/indent.go', [ 13 | \ 'package main', 14 | \ '', 15 | \ 'import "fmt"', 16 | \ '', 17 | \ 'func main() {', 18 | \ "\t\x1fconst msg = `", 19 | \ '`', 20 | \ '\tfmt.Println(msg)', 21 | \ '}']) 22 | 23 | silent execute "normal o" . "not indented\" 24 | let l:indent = indent(line('.')) 25 | call assert_equal(0, l:indent) 26 | finally 27 | call go#util#Chdir(l:wd) 28 | call delete(l:dir, 'rf') 29 | endtry 30 | 31 | let l:wd = getcwd() 32 | try 33 | let l:dir= gotest#write_file('indent/indent.go', [ 34 | \ 'package main', 35 | \ '', 36 | \ 'import "fmt"', 37 | \ '', 38 | \ 'func main() {', 39 | \ "\t\x1fmsg := `", 40 | \ '`', 41 | \ '\tfmt.Println(msg)', 42 | \ '}']) 43 | 44 | silent execute "normal o" . "not indented\" 45 | let l:indent = indent(line('.')) 46 | call assert_equal(0, l:indent) 47 | finally 48 | call delete(l:dir, 'rf') 49 | call go#util#Chdir(l:wd) 50 | endtry 51 | 52 | let l:wd = getcwd() 53 | try 54 | let l:dir= gotest#write_file('indent/indent.go', [ 55 | \ 'package main', 56 | \ '', 57 | \ 'import "fmt"', 58 | \ '', 59 | \ 'func main() {', 60 | \ "\tconst msg = `", 61 | \ "\t\x1findented", 62 | \ '`', 63 | \ '\tfmt.Println(msg)', 64 | \ '}']) 65 | 66 | silent execute "normal o" . "indented\" 67 | let l:indent = indent(line('.')) 68 | call assert_equal(shiftwidth(), l:indent) 69 | finally 70 | call go#util#Chdir(l:wd) 71 | call delete(l:dir, 'rf') 72 | endtry 73 | endfunc 74 | 75 | " restore Vi compatibility settings 76 | let &cpo = s:cpo_save 77 | unlet s:cpo_save 78 | 79 | " vim: sw=2 ts=2 et 80 | -------------------------------------------------------------------------------- /compiler/go.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2013 The Go Authors. All rights reserved. 2 | " Use of this source code is governed by a BSD-style 3 | " license that can be found in the LICENSE file. 4 | " 5 | " compiler/go.vim: Vim compiler file for Go. 6 | 7 | if exists("g:current_compiler") 8 | finish 9 | endif 10 | let g:current_compiler = "go" 11 | 12 | " don't spam the user when Vim is started in Vi compatibility mode 13 | let s:cpo_save = &cpo 14 | set cpo&vim 15 | 16 | if exists(":CompilerSet") != 2 17 | command -nargs=* CompilerSet setlocal 18 | endif 19 | 20 | let s:save_cpo = &cpo 21 | set cpo-=C 22 | if filereadable("makefile") || filereadable("Makefile") 23 | CompilerSet makeprg=make 24 | else 25 | CompilerSet makeprg=go\ build 26 | endif 27 | 28 | " Define the patterns that will be recognized by QuickFix when parsing the 29 | " output of Go command that use this errorforamt (when called make, cexpr or 30 | " lmake, lexpr). This is the global errorformat, however some command might 31 | " use a different output, for those we define them directly and modify the 32 | " errorformat ourselves. More information at: 33 | " http://vimdoc.sourceforge.net/htmldoc/quickfix.html#errorformat 34 | CompilerSet errorformat =%-G#\ %.%# " Ignore lines beginning with '#' ('# command-line-arguments' line sometimes appears?) 35 | CompilerSet errorformat+=%-G%.%#panic:\ %m " Ignore lines containing 'panic: message' 36 | CompilerSet errorformat+=%Ecan\'t\ load\ package:\ %m " Start of multiline error string is 'can\'t load package' 37 | CompilerSet errorformat+=%A%\\%%(%[%^:]%\\+:\ %\\)%\\?%f:%l:%c:\ %m " Start of multiline unspecified string is 'filename:linenumber:columnnumber:' 38 | CompilerSet errorformat+=%A%\\%%(%[%^:]%\\+:\ %\\)%\\?%f:%l:\ %m " Start of multiline unspecified string is 'filename:linenumber:' 39 | CompilerSet errorformat+=%C%*\\s%m " Continuation of multiline error message is indented 40 | CompilerSet errorformat+=%-G%.%# " All lines not matching any of the above patterns are ignored 41 | let &cpo = s:save_cpo 42 | unlet s:save_cpo 43 | 44 | " restore Vi compatibility settings 45 | let &cpo = s:cpo_save 46 | unlet s:cpo_save 47 | 48 | " vim: sw=2 ts=2 et 49 | -------------------------------------------------------------------------------- /autoload/go/template.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | let s:current_file = resolve(expand("")) 6 | 7 | function! go#template#create() abort 8 | let l:go_template_use_pkg = go#config#TemplateUsePkg() 9 | let l:root_dir = fnamemodify(s:current_file, ':h:h:h') 10 | 11 | let l:package_name = go#tool#PackageName() 12 | 13 | " if we can't figure out any package name (i.e. no Go files in the directory) 14 | " from the directory create the template or use the directory as the name. 15 | if l:package_name == -1 16 | if l:go_template_use_pkg == 1 17 | let l:path = fnamemodify(expand('%:p:h'), ':t') 18 | let l:content = printf("package %s", l:path) 19 | call append(0, l:content) 20 | else 21 | let l:filename = expand('%:t') 22 | if l:filename =~ "_test.go$" 23 | let l:template_file = go#config#TemplateTestFile() 24 | else 25 | let l:template_file = go#config#TemplateFile() 26 | endif 27 | " If template_file is an absolute path, use it as-is. This is to support 28 | " overrides pointing to templates outside of the vim-go plugin dir 29 | if fnamemodify(l:template_file, ':p') != l:template_file 30 | let l:template_file = go#util#Join(l:root_dir, "templates", l:template_file) 31 | endif 32 | 33 | silent exe 'keepalt 0r ' . fnameescape(l:template_file) 34 | endif 35 | else 36 | let l:content = printf("package %s", l:package_name) 37 | call append(0, l:content) 38 | endif 39 | " checking that the last line is empty shouldn't be necessary, but for some 40 | " reason the last line isn't the expected empty line when run via tests. 41 | if getline('$') is '' 42 | $delete _ 43 | endif 44 | endfunction 45 | 46 | function! go#template#ToggleAutoCreate() abort 47 | if go#config#TemplateAutocreate() 48 | call go#config#SetTemplateAutocreate(0) 49 | call go#util#EchoProgress("auto template create disabled") 50 | return 51 | end 52 | 53 | call go#config#SetTemplateAutocreate(1) 54 | call go#util#EchoProgress("auto template create enabled") 55 | endfunction 56 | 57 | " restore Vi compatibility settings 58 | let &cpo = s:cpo_save 59 | unlet s:cpo_save 60 | 61 | " vim: sw=2 ts=2 et 62 | -------------------------------------------------------------------------------- /scripts/lint: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run all linting tools. 4 | # 5 | 6 | set -euC 7 | vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) 8 | cd "$vimgodir" 9 | 10 | ### Setup Vim and other dependencies. 11 | ##################################### 12 | if [ -z "${1:-}" ]; then 13 | echo "unknown version: '${1:-}'" 14 | echo "First argument must be 'vim-8.2', 'vim-9.1' or 'nvim'." 15 | exit 1 16 | fi 17 | 18 | vim=$1 19 | vimdir="/tmp/vim-go-test/$vim-install" 20 | export GOPATH=$vimdir 21 | export PATH="${GOPATH}/bin:$PATH" 22 | 23 | if [ ! -f "$vimdir/bin/vim" ]; then 24 | echo "$vimdir/bin/vim doesn't exist; did you install it with the install-vim script?" 25 | exit 1 26 | fi 27 | 28 | ### Run vint 29 | ############ 30 | failed=0 31 | printf "Running vint ... " 32 | if [ -x "$(command -v vint)" ]; then 33 | lint=$(vint "$vimgodir" 2>&1 ||:) 34 | if [ -n "$lint" ]; then 35 | echo "FAILED" 36 | echo "$lint" 37 | echo 38 | failed=6 39 | else 40 | echo "PASSED" 41 | fi 42 | else 43 | echo "SKIPPED" 44 | echo "'vint' binary not found; use 'pip install vim-vint' to install it." 45 | fi 46 | 47 | ### Run vim-vimlint 48 | ################### 49 | printf "Running vim-vimlint ... " 50 | lint=$(sh "$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlint/bin/vimlint.sh" \ 51 | -p "$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlparser" \ 52 | -l "$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlint" \ 53 | -u \ 54 | -c func_abort=1 \ 55 | -e EVL110=1 -e EVL103=1 -e EVL104=1 -e EVL102=1 \ 56 | "$vimgodir" \ 57 | 2>&1) 58 | result="$?" 59 | if [ "$result" -eq "2" ]; then 60 | echo "$lint" 61 | echo 62 | failed=6 63 | else 64 | echo "PASSED" 65 | fi 66 | 67 | ### Run vimhelplint. 68 | #################### 69 | printf "Running vimhelplint ... " 70 | 71 | # set modeline explicitly so that the modeline will be respected when run as root. 72 | lint=$($vimdir/bin/vim -esNR \ 73 | --cmd "set rtp+=$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimhelplint/" \ 74 | --cmd 'set modeline' \ 75 | +'filetype plugin on' \ 76 | +"e $vimgodir/doc/vim-go.txt" \ 77 | +'verbose VimhelpLintEcho' \ 78 | +q \ 79 | 2>&1 ||:) 80 | if [ "$lint" ]; then 81 | echo "FAILED" 82 | echo "$lint" 83 | failed=6 84 | else 85 | echo "PASSED" 86 | fi 87 | 88 | exit "$failed" 89 | -------------------------------------------------------------------------------- /autoload/go/play.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#play#Share(count, line1, line2) abort 6 | if !executable('curl') 7 | call go#util#EchoError('cannot share: curl cannot be found') 8 | return 9 | endif 10 | 11 | let content = join(getline(a:line1, a:line2), "\n") 12 | let share_file = tempname() 13 | call writefile(split(content, "\n"), share_file, "b") 14 | 15 | let l:cmd = ['curl', '-s', 16 | \ '-H', 'Content-Type: text/plain; charset=utf-8', 17 | \ '-X', 'POST', 'https://go.dev/_/share', 18 | \ '--data-binary', '@' . l:share_file] 19 | let [l:snippet_id, l:err] = go#util#Exec(l:cmd) 20 | 21 | " we can remove the temp file because it's now posted. 22 | call delete(share_file) 23 | 24 | if l:err != 0 25 | call go#util#EchoError(['A error has occurred. Run this command to see what the problem is:', go#util#Shelljoin(l:cmd)]) 26 | return 27 | endif 28 | 29 | let url = printf("https://go.dev/play/p/%s", snippet_id) 30 | 31 | " copy to clipboard 32 | if has('unix') && !has('xterm_clipboard') && !has('clipboard') 33 | let @" = url 34 | else 35 | let @+ = url 36 | endif 37 | 38 | if go#config#PlayOpenBrowser() 39 | call go#util#OpenBrowser(url) 40 | endif 41 | 42 | call go#util#EchoInfo('snippet uploaded: ' . url) 43 | endfunction 44 | 45 | 46 | function! s:get_visual_content() abort 47 | let save_regcont = @" 48 | let save_regtype = getregtype('"') 49 | silent! normal! gvy 50 | let content = @" 51 | call setreg('"', save_regcont, save_regtype) 52 | return content 53 | endfunction 54 | 55 | " modified version of 56 | " http://stackoverflow.com/questions/1533565/how-to-get-visually-selected-text-in-vimscript 57 | " another function that returns the content of visual selection, it's not used 58 | " but might be useful in the future 59 | function! s:get_visual_selection() abort 60 | let [lnum1, col1] = getpos("'<")[1:2] 61 | let [lnum2, col2] = getpos("'>")[1:2] 62 | 63 | " check if the the visual mode is used before 64 | if lnum1 == 0 || lnum2 == 0 || col1 == 0 || col2 == 0 65 | return 66 | endif 67 | 68 | let lines = getline(lnum1, lnum2) 69 | let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)] 70 | let lines[0] = lines[0][col1 - 1:] 71 | return join(lines, "\n") 72 | endfunction 73 | 74 | " restore Vi compatibility settings 75 | let &cpo = s:cpo_save 76 | unlet s:cpo_save 77 | 78 | " vim: sw=2 ts=2 et 79 | -------------------------------------------------------------------------------- /indent/go.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2011 The Go Authors. All rights reserved. 2 | " Use of this source code is governed by a BSD-style 3 | " license that can be found in the LICENSE file. 4 | " 5 | " indent/go.vim: Vim indent file for Go. 6 | " 7 | " TODO: 8 | " - function invocations split across lines 9 | " - general line splits (line ends in an operator) 10 | 11 | if exists("b:did_indent") 12 | finish 13 | endif 14 | let b:did_indent = 1 15 | 16 | " C indentation is too far off useful, mainly due to Go's := operator. 17 | " Let's just define our own. 18 | setlocal nolisp 19 | setlocal autoindent 20 | setlocal indentexpr=GoIndent(v:lnum) 21 | setlocal indentkeys+=<:>,0=},0=) 22 | 23 | if exists("*GoIndent") 24 | finish 25 | endif 26 | 27 | " don't spam the user when Vim is started in Vi compatibility mode 28 | let s:cpo_save = &cpo 29 | set cpo&vim 30 | 31 | function! GoIndent(lnum) abort 32 | let prevlnum = prevnonblank(a:lnum-1) 33 | if prevlnum == 0 34 | " top of file 35 | return 0 36 | endif 37 | 38 | " grab the previous and current line, stripping comments. 39 | let prevl = substitute(getline(prevlnum), '//.*$', '', '') 40 | let thisl = substitute(getline(a:lnum), '//.*$', '', '') 41 | let previ = indent(prevlnum) 42 | 43 | let ind = previ 44 | 45 | for synid in synstack(a:lnum, 1) 46 | if synIDattr(synid, 'name') == 'goRawString' 47 | if prevl =~ '\%(\%(:\?=\)\|(\|,\)\s*`[^`]*$' 48 | " previous line started a multi-line raw string 49 | return 0 50 | endif 51 | " return -1 to keep the current indent. 52 | return -1 53 | endif 54 | endfor 55 | 56 | if prevl =~ '[({]\s*$' 57 | " previous line opened a block 58 | let ind += shiftwidth() 59 | endif 60 | if prevl =~# '^\s*\(case .*\|default\):$' 61 | " previous line is part of a switch statement 62 | let ind += shiftwidth() 63 | endif 64 | " TODO: handle if the previous line is a label. 65 | 66 | if thisl =~ '^\s*[)}]' 67 | " this line closed a block 68 | let ind -= shiftwidth() 69 | endif 70 | 71 | " Colons are tricky. 72 | " We want to outdent if it's part of a switch ("case foo:" or "default:"). 73 | " We ignore trying to deal with jump labels because (a) they're rare, and 74 | " (b) they're hard to disambiguate from a composite literal key. 75 | if thisl =~# '^\s*\(case .*\|default\):$' 76 | let ind -= shiftwidth() 77 | endif 78 | 79 | return ind 80 | endfunction 81 | 82 | " restore Vi compatibility settings 83 | let &cpo = s:cpo_save 84 | unlet s:cpo_save 85 | 86 | " vim: sw=2 ts=2 et 87 | -------------------------------------------------------------------------------- /autoload/go/package_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_Complete_GOPATH_simple() abort 6 | let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package' 7 | silent exe 'edit ' . $GOPATH . '/src/package/package.go' 8 | call s:complete('package', ['package']) 9 | call delete(printf('%s/pkg', $GOPATH), 'rf') 10 | endfunc 11 | 12 | func! Test_Complete_Module_simple() abort 13 | silent exe 'edit ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package/src/package/package.go' 14 | call s:complete('package', ['package']) 15 | endfunc 16 | 17 | func! Test_Complete_GOPATH_subdirs() abort 18 | let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package' 19 | silent exe 'edit ' . $GOPATH . '/src/package/package.go' 20 | call s:complete('package/', ['package/bar', 'package/baz']) 21 | call delete(printf('%s/pkg', $GOPATH), 'rf') 22 | endfunc 23 | 24 | func! Test_Complete_Module_subdirs() abort 25 | silent exe 'edit ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package/src/package/package.go' 26 | call s:complete('package/', ['package/bar', 'package/baz']) 27 | endfunc 28 | 29 | func! Test_Complete_GOPATH_baronly() abort 30 | let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package' 31 | silent exe 'edit ' . $GOPATH . '/src/package/package.go' 32 | call s:complete('package/bar', ['package/bar']) 33 | call delete(printf('%s/pkg', $GOPATH), 'rf') 34 | endfunc 35 | 36 | func! Test_Complete_Module_baronly() abort 37 | silent exe 'edit ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package/src/package/package.go' 38 | call s:complete('package/bar', ['package/bar']) 39 | endfunc 40 | 41 | func! Test_Complete_GOPATH_vendor() abort 42 | let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package' 43 | silent exe 'edit ' . $GOPATH . '/src/package/package.go' 44 | call s:complete('foo', ['foo']) 45 | call delete(printf('%s/pkg', $GOPATH), 'rf') 46 | endfunc 47 | 48 | func! Test_Complete_Module_vendor() abort 49 | silent exe 'edit ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package/src/package/package.go' 50 | call s:complete('foo', ['foo']) 51 | endfunc 52 | 53 | func! s:complete(arglead, expected) abort 54 | let l:candidates = go#package#Complete(a:arglead, '', 1) 55 | call assert_equal(a:expected, l:candidates) 56 | endfunc 57 | 58 | " restore Vi compatibility settings 59 | let &cpo = s:cpo_save 60 | unlet s:cpo_save 61 | 62 | " vim: sw=2 ts=2 et 63 | -------------------------------------------------------------------------------- /autoload/go/fillstruct.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#fillstruct#FillStruct() abort 6 | let l:mode = go#config#FillStructMode() 7 | if l:mode is 'gopls' 8 | if !go#config#GoplsEnabled() 9 | call go#util#EchoError("go_fillstruct_mode is 'gopls', but gopls is disabled") 10 | return 11 | endif 12 | 13 | call go#lsp#FillStruct() 14 | return 15 | endif 16 | 17 | let l:cmd = ['fillstruct', 18 | \ '-file', bufname(''), 19 | \ '-offset', go#util#OffsetCursor(), 20 | \ '-line', line('.')] 21 | " Needs: https://github.com/davidrjenni/reftools/pull/14 22 | "\ '-tags', go#config#BuildTags()] 23 | 24 | let l:buildtags = go#config#BuildTags() 25 | if l:buildtags isnot '' 26 | let l:cmd += ['-tags', l:buildtags] 27 | endif 28 | 29 | " Read from stdin if modified. 30 | if &modified 31 | call add(l:cmd, '-modified') 32 | let [l:out, l:err] = go#util#Exec(l:cmd, go#util#archive()) 33 | else 34 | let [l:out, l:err] = go#util#Exec(l:cmd) 35 | endif 36 | 37 | if l:err 38 | call go#util#EchoError(l:out) 39 | return 40 | endif 41 | 42 | try 43 | let l:json = json_decode(l:out) 44 | catch 45 | call go#util#EchoError(l:out) 46 | return 47 | endtry 48 | 49 | " Output is array: 50 | "[ 51 | " {"start": 92, "end": 106, "code": "mail.Address{\n\tName: \"\",\n\tAddress: \"\",\n}"}, 52 | " {...second struct...} 53 | " ] 54 | 55 | let l:pos = getpos('.') 56 | 57 | try 58 | for l:struct in l:json 59 | let l:code = split(l:struct['code'], "\n") 60 | 61 | " Add any code before/after the struct. 62 | exe l:struct['start'] . 'go' 63 | let l:code[0] = getline('.')[:col('.')-1] . l:code[0] 64 | exe l:struct['end'] . 'go' 65 | let l:code[len(l:code)-1] .= getline('.')[col('.'):] 66 | 67 | " Indent every line except the first one; makes it look nice. 68 | let l:indent = repeat("\t", indent('.') / &tabstop) 69 | for l:i in range(1, len(l:code)-1) 70 | let l:code[l:i] = l:indent . l:code[l:i] 71 | endfor 72 | 73 | " Out with the old ... 74 | exe 'normal! ' . l:struct['start'] . 'gov' . l:struct['end'] . 'gox' 75 | " ... in with the new. 76 | call setline('.', l:code[0]) 77 | call append('.', l:code[1:]) 78 | endfor 79 | finally 80 | call setpos('.', l:pos) 81 | endtry 82 | endfunction 83 | 84 | " restore Vi compatibility settings 85 | let &cpo = s:cpo_save 86 | unlet s:cpo_save 87 | 88 | " vim: sw=2 ts=2 et 89 | -------------------------------------------------------------------------------- /autoload/unite/sources/decls.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpoptions 2 | set cpoptions&vim 3 | 4 | let s:source = { 5 | \ 'name': 'decls', 6 | \ 'description': 'GoDecls implementation for unite', 7 | \ 'syntax': 'uniteSource__Decls', 8 | \ 'action_table': {}, 9 | \ 'hooks': {}, 10 | \ } 11 | 12 | function! unite#sources#decls#define() 13 | return s:source 14 | endfunction 15 | 16 | function! s:source.gather_candidates(args, context) abort 17 | let l:bin_path = go#path#CheckBinPath('motion') 18 | if empty(l:bin_path) 19 | return [] 20 | endif 21 | 22 | let l:path = expand(get(a:args, 0, '%:p:h')) 23 | if isdirectory(l:path) 24 | let l:mode = 'dir' 25 | elseif filereadable(l:path) 26 | let l:mode = 'file' 27 | else 28 | return [] 29 | endif 30 | 31 | let l:include = go#config#DeclsIncludes() 32 | let l:command = printf('%s -format vim -mode decls -include %s -%s %s', l:bin_path, l:include, l:mode, shellescape(l:path)) 33 | let l:candidates = [] 34 | try 35 | let l:result = eval(unite#util#system(l:command)) 36 | let l:candidates = get(l:result, 'decls', []) 37 | catch 38 | call unite#print_source_error(['command returned invalid response.', v:exception], s:source.name) 39 | endtry 40 | 41 | return map(l:candidates, "{ 42 | \ 'word': printf('%s :%d :%s', fnamemodify(v:val.filename, ':~:.'), v:val.line, v:val.full), 43 | \ 'kind': 'jump_list', 44 | \ 'action__path': v:val.filename, 45 | \ 'action__line': v:val.line, 46 | \ 'action__col': v:val.col, 47 | \ }") 48 | endfunction 49 | 50 | function! s:source.hooks.on_syntax(args, context) abort 51 | syntax match uniteSource__Decls_Filepath /[^:]*\ze:/ contained containedin=uniteSource__Decls 52 | syntax match uniteSource__Decls_Line /\d\+\ze :/ contained containedin=uniteSource__Decls 53 | syntax match uniteSource__Decls_WholeFunction /\vfunc %(\([^)]+\) )?[^(]+/ contained containedin=uniteSource__Decls 54 | syntax match uniteSource__Decls_Function /\S\+\ze(/ contained containedin=uniteSource__Decls_WholeFunction 55 | syntax match uniteSource__Decls_WholeType /type \S\+/ contained containedin=uniteSource__Decls 56 | syntax match uniteSource__Decls_Type /\v( )@<=\S+/ contained containedin=uniteSource__Decls_WholeType 57 | highlight default link uniteSource__Decls_Filepath Comment 58 | highlight default link uniteSource__Decls_Line LineNr 59 | highlight default link uniteSource__Decls_Function Function 60 | highlight default link uniteSource__Decls_Type Type 61 | 62 | syntax match uniteSource__Decls_Separator /:/ contained containedin=uniteSource__Decls conceal 63 | syntax match uniteSource__Decls_SeparatorFunction /func / contained containedin=uniteSource__Decls_WholeFunction conceal 64 | syntax match uniteSource__Decls_SeparatorType /type / contained containedin=uniteSource__Decls_WholeType conceal 65 | endfunction 66 | 67 | let &cpoptions = s:save_cpo 68 | unlet s:save_cpo 69 | 70 | " vim: sw=2 ts=2 et 71 | -------------------------------------------------------------------------------- /autoload/go/config_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | scriptencoding utf-8 6 | 7 | func! Test_SetBuildTags() abort 8 | if !go#util#has_job() 9 | return 10 | endif 11 | 12 | try 13 | let g:go_def_mode = 'gopls' 14 | let l:dir = 'test-fixtures/config/buildtags' 15 | let l:jumpstart = [0, 4, 2, 0] 16 | 17 | execute 'e ' . printf('%s/buildtags.go', l:dir) 18 | let l:jumpstartbuf = bufnr('') 19 | 20 | call setpos('.', [l:jumpstartbuf, l:jumpstart[1], l:jumpstart[2], 0]) 21 | 22 | let l:expectedfilename = printf('%s/foo.go', l:dir) 23 | 24 | let l:expected = [0, 5, 6, 0] 25 | call assert_notequal(l:expected, l:jumpstart) 26 | 27 | call go#def#Jump('', 0) 28 | 29 | let l:start = reltime() 30 | while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10 31 | sleep 100m 32 | endwhile 33 | 34 | call assert_equal(l:expectedfilename, bufname("%")) 35 | call assert_equal(l:expected, getpos('.')) 36 | 37 | execute 'e ' . printf('%s/buildtags.go', l:dir) 38 | 39 | " prepare to wait for the workspace/configuration request 40 | let g:go_debug=['lsp'] 41 | 42 | " set the build constraint 43 | call go#config#SetBuildTags('constrained') 44 | 45 | " wait for the workspace/configuration request 46 | let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$') 47 | let l:start = reltime() 48 | while match(l:lsplog, 'workspace/configuration') == -1 && reltimefloat(reltime(l:start)) < 10 49 | sleep 50m 50 | let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$') 51 | endwhile 52 | " close the __GOLSP_LOG__ window 53 | only 54 | 55 | " verify the cursor position within buildtags.go 56 | call setpos('.', [l:jumpstartbuf, l:jumpstart[1], l:jumpstart[2], 0]) 57 | call assert_equal(l:jumpstart, getpos('.')) 58 | 59 | let l:expectedfilename = printf('%s/constrainedfoo.go', l:dir) 60 | let l:expected = [0, 6, 6, 0] 61 | call assert_notequal(l:expected, l:jumpstart) 62 | 63 | call go#def#Jump('', 0) 64 | 65 | let l:start = reltime() 66 | while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10 67 | sleep 100m 68 | endwhile 69 | 70 | call assert_equal(l:expectedfilename, bufname("%")) 71 | call assert_equal(l:expected, getpos('.')) 72 | 73 | let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$') 74 | 75 | finally 76 | call go#config#SetBuildTags('') 77 | endtry 78 | endfunc 79 | 80 | func! Test_GoplsEnabled_Clear() abort 81 | if !go#util#has_job() 82 | return 83 | endif 84 | 85 | let l:wd = getcwd() 86 | try 87 | let g:go_gopls_enabled = 0 88 | 89 | let l:tmp = gotest#write_file('gopls_disabled.go', [ 90 | \ 'package example', 91 | \ '', 92 | \ 'func Example() {', 93 | \ "\tprintln(" . '"hello, world!")', 94 | \ '}', 95 | \ ] ) 96 | 97 | finally 98 | call go#util#Chdir(l:wd) 99 | call delete(l:tmp, 'rf') 100 | endtry 101 | endfunc 102 | 103 | " restore Vi compatibility settings 104 | let &cpo = s:cpo_save 105 | unlet s:cpo_save 106 | 107 | " vim: sw=2 ts=2 et 108 | -------------------------------------------------------------------------------- /scripts/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run all tests. 4 | # 5 | 6 | set -euC 7 | vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) 8 | cd "$vimgodir" 9 | 10 | _usage() { 11 | echo "Usage: ${0##*/} [-hvc] [-r file] vim_version" 12 | echo 13 | echo "Options:" 14 | echo " -h Show this help" 15 | echo " -v Enable verbose output" 16 | echo " -r Run only the tests from this file" 17 | echo " -c Generate code coverage reports" 18 | echo " -u Submit code coverage reports" 19 | echo 20 | } 21 | 22 | verbose=0 23 | run="" 24 | coverage="" 25 | uploadcoverage="" 26 | while getopts "hvcur:" option; do 27 | case "$option" in 28 | h) _usage; exit 0 ;; 29 | v) verbose=1; ;; 30 | r) run=$OPTARG ;; 31 | c) coverage="-c" ;; 32 | u) uploadcoverage=1 ;; 33 | *) 34 | echo "error: unknown option '$option'" 35 | _usage 36 | exit 1 37 | ;; 38 | esac 39 | done 40 | shift $((OPTIND - 1)) 41 | 42 | ### Setup Vim and other dependencies. 43 | ##################################### 44 | if [ -z "${1:-}" ]; then 45 | echo "unknown version: '${1:-}'" 46 | echo "First argument must be 'vim-8.2', 'vim-9.1', or 'nvim'." 47 | exit 1 48 | fi 49 | 50 | vim=$1 51 | vimdir="/tmp/vim-go-test/$vim-install" 52 | export GOPATH=$vimdir 53 | export PATH="${GOPATH}/bin:$PATH" 54 | 55 | if [ ! -f "$vimdir/bin/vim" ]; then 56 | echo "$vimdir/bin/vim doesn't exist; did you install it with the install-vim script?" 57 | exit 1 58 | fi 59 | 60 | ### Run tests. 61 | ############## 62 | # Clean stale log file. 63 | [ -f '/tmp/vim-go-test/test.log' ] && rm '/tmp/vim-go-test/test.log' 64 | [ -f '/tmp/vim-go-test/FAILED' ] && rm '/tmp/vim-go-test/FAILED' 65 | [ -f '/tmp/vim-go-test/cov-profile.txt' ] && rm '/tmp/vim-go-test/cov-profile.txt' 66 | [ -f '/tmp/vim-go-test/cov-report.txt' ] && rm '/tmp/vim-go-test/cov-report.txt' 67 | 68 | # Run the actual tests. 69 | find "$vimgodir" -name '*_test.vim' | sort | while read test_file; do 70 | [ -n "$run" -a "$(basename "$test_file")" != "$run" ] && continue 71 | 72 | "$vimgodir/scripts/run-vim" $coverage $vim -e \ 73 | +"silent e $test_file" \ 74 | +"let g:test_verbose=$verbose" \ 75 | +"let g:go_echo_command_info=0" \ 76 | -S ./scripts/runtest.vim < /dev/null || ( 77 | # If Vim exits with non-0 it's almost certainly a bug in the test runner; 78 | # should very rarely happen in normal usage. 79 | echo 'test runner failure' 80 | cat '/tmp/vim-go-test/test.tmp' 81 | rm '/tmp/vim-go-test/test.tmp' 82 | exit 5 83 | ) 84 | 85 | # Append logs 86 | cat '/tmp/vim-go-test/test.tmp' | tee '/tmp/vim-go-test/test.log' 87 | rm '/tmp/vim-go-test/test.tmp' 88 | done 89 | 90 | echo 91 | if [ -f "/tmp/vim-go-test/FAILED" ]; then 92 | echo 2>&1 "Some ($vim) tests FAILED" 93 | exit 1 94 | fi 95 | echo 2>&1 "All ($vim) tests PASSED" 96 | 97 | # Generate coverage reports 98 | if [ -n "$coverage" ]; then 99 | coverage xml --omit '*_test.vim' 100 | 101 | if [ -n "$uploadcoverage" ]; then 102 | codecov -X search gcov pycov -f coverage.xml --required \ 103 | --flags "$(echo "$vim" | sed -s 's/[-.]//g')" 104 | rm coverage.xml 105 | fi 106 | fi 107 | 108 | # vim:ts=2:sts=2:sw=2:et 109 | -------------------------------------------------------------------------------- /scripts/install-vim: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Install and setup a Vim or Neovim for running tests. 4 | # This should work on both GitHub Actions and people's desktop computers, and 5 | # be 100% independent from any system installed Vim. 6 | # 7 | # It will echo the full path to a Vim binary, e.g.: 8 | # /some/path/src/vim 9 | 10 | set -euC 11 | 12 | vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) 13 | cd "$vimgodir" 14 | 15 | vim=${1:-} 16 | 17 | case "$vim" in 18 | "vim-8.2") 19 | # This follows the version in Ubuntu LTS. Vim's master branch isn't always 20 | # stable, and we don't want to have the build fail because Vim introduced a 21 | # bug. 22 | tag="v8.2.5072" 23 | giturl="https://github.com/vim/vim" 24 | 25 | ;; 26 | 27 | "vim-9.1") 28 | # This is the version that's installed by homebrew currently. It doesn't 29 | # have to stay up to date with homebrew, and is only chosen here because 30 | # that's what homebrew was using at the the time and we need a version to 31 | # vimlint with. 32 | tag="v9.1.1300" 33 | giturl="https://github.com/vim/vim" 34 | ;; 35 | 36 | "nvim") 37 | # Use latest stable version. 38 | tag="v0.9.1" 39 | giturl="https://github.com/neovim/neovim" 40 | ;; 41 | 42 | *) 43 | echo "unknown version: '${1:-}'" 44 | echo "First argument must be 'vim-8.1', vim-8.2, or 'nvim'." 45 | exit 1 46 | ;; 47 | esac 48 | 49 | srcdir="/tmp/vim-go-test/$1-src" 50 | installdir="/tmp/vim-go-test/$1-install" 51 | 52 | # Use cached installdir. 53 | if [ -d "$installdir" ]; then 54 | echo "$installdir exists; skipping build." 55 | 56 | # The ./scripts/test script relies on this. 57 | echo "installed to: $installdir" 58 | exit 0 59 | fi 60 | 61 | mkdir -p "$srcdir" 62 | cd "$srcdir" 63 | 64 | # Neovim build requires more deps than Vim and is annoying, so we use the 65 | # binary. 66 | # 0.2.0 doesn't have a binary build for Linux, so we use 0.2.1-dev for now. 67 | if [ "$1" = "nvim" ]; then 68 | 69 | # TODO: Use macOS binaries on macOS 70 | curl -Ls https://github.com/neovim/neovim/releases/download/$tag/nvim-linux64.tar.gz | 71 | tar xzf - -C /tmp/vim-go-test/ 72 | mv /tmp/vim-go-test/nvim-linux64 /tmp/vim-go-test/nvim-install 73 | mkdir -p "$installdir/share/nvim/runtime/pack/vim-go/start" 74 | ln -s "$vimgodir" "$installdir/share/nvim/runtime/pack/vim-go/start/vim-go" 75 | 76 | # Consistent paths makes calling things easier. 77 | mv "$installdir/bin/nvim" "$installdir/bin/vim" 78 | mkdir -p "$installdir/share/vim/vimgo/pack" 79 | ln -s "$installdir/share/nvim/runtime/pack/vim-go" "$installdir/share/vim/vimgo/pack/vim-go" 80 | 81 | # Build Vim from source. 82 | else 83 | if [ -d "$srcdir/.git" ]; then 84 | echo "Skipping clone as $srcdir/.git exists" 85 | else 86 | echo "Cloning $tag from $giturl" 87 | git clone --branch "$tag" --depth 1 "$giturl" "$srcdir" 88 | fi 89 | 90 | ./configure --prefix="$installdir" --with-features=huge --disable-gui 91 | make install 92 | mkdir -p "$installdir/share/vim/vimgo/pack/vim-go/start" 93 | ln -s "$vimgodir" "$installdir/share/vim/vimgo/pack/vim-go/start/vim-go" 94 | fi 95 | 96 | # Don't really need source after successful install. 97 | rm -rf "$srcdir" 98 | 99 | echo "installed to: $installdir" 100 | 101 | # vim:ts=2:sts=2:sw=2:et 102 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Fatih Arslan 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of vim-go nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | This software includes some portions from Go. Go is used under the terms of the 30 | BSD like license. 31 | 32 | Copyright (c) 2012 The Go Authors. All rights reserved. 33 | 34 | Redistribution and use in source and binary forms, with or without 35 | modification, are permitted provided that the following conditions are 36 | met: 37 | 38 | * Redistributions of source code must retain the above copyright 39 | notice, this list of conditions and the following disclaimer. 40 | * Redistributions in binary form must reproduce the above 41 | copyright notice, this list of conditions and the following disclaimer 42 | in the documentation and/or other materials provided with the 43 | distribution. 44 | * Neither the name of Google Inc. nor the names of its 45 | contributors may be used to endorse or promote products derived from 46 | this software without specific prior written permission. 47 | 48 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 49 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 50 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 51 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 52 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 53 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 54 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 55 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 56 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 57 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 58 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 | 60 | The Go gopher was designed by Renee French. http://reneefrench.blogspot.com/ The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: https://blog.golang.org/gopher 61 | -------------------------------------------------------------------------------- /autoload/go/sameids.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#sameids#SameIds(showstatus) abort 6 | if !go#config#GoplsEnabled() 7 | call go#util#EchoError("GoSameIds requires gopls, but gopls is disabled") 8 | return 9 | endif 10 | 11 | " check if the version of Vim being tested supports matchaddpos() 12 | if !exists("*matchaddpos") 13 | call go#util#EchoError("GoSameIds requires 'matchaddpos'. Update your Vim/Neovim version.") 14 | return 15 | endif 16 | 17 | " check if the version of Vim being tested supports json_decode() 18 | if !exists("*json_decode") 19 | call go#util#EchoError("GoSameIds requires 'json_decode'. Update your Vim/Neovim version.") 20 | return 21 | endif 22 | 23 | let [l:line, l:col] = getpos('.')[1:2] 24 | let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col) 25 | call go#lsp#SameIDs(0, expand('%:p'), l:line, l:col, funcref('s:same_ids_highlight')) 26 | endfunction 27 | 28 | function! s:same_ids_highlight(exit_val, result) abort 29 | call go#sameids#ClearSameIds() " clear at the start to reduce flicker 30 | 31 | if type(a:result) != type({}) && !go#config#AutoSameids() 32 | call go#util#EchoError("malformed same id result") 33 | return 34 | endif 35 | 36 | if !has_key(a:result, 'sameids') || len(a:result.sameids) == 0 37 | if !go#config#AutoSameids() 38 | call go#util#EchoError("no references found for the given identifier") 39 | endif 40 | return 41 | endif 42 | 43 | let same_ids = a:result['sameids'] 44 | 45 | " highlight the lines 46 | let l:matches = [] 47 | for pos in same_ids 48 | let poslen = pos[2] - pos[1] 49 | let l:matches = add(l:matches, [pos[0], pos[1], poslen]) 50 | endfor 51 | 52 | call go#util#HighlightPositions('goSameId', l:matches) 53 | 54 | if go#config#AutoSameids() 55 | " re-apply SameIds at the current cursor position at the time the buffer 56 | " is redisplayed: e.g. :edit, :GoRename, etc. 57 | augroup vim-go-sameids 58 | autocmd! * 59 | if has('textprop') 60 | autocmd BufReadPost nested call go#sameids#SameIds(0) 61 | else 62 | autocmd BufWinEnter nested call go#sameids#SameIds(0) 63 | endif 64 | augroup end 65 | endif 66 | endfunction 67 | 68 | " ClearSameIds returns 0 when it removes goSameId groups and non-zero if no 69 | " goSameId groups are found. 70 | function! go#sameids#ClearSameIds() abort 71 | let l:cleared = go#util#ClearHighlights('goSameId') 72 | 73 | if !l:cleared 74 | return 1 75 | endif 76 | 77 | " remove the autocmds we defined 78 | augroup vim-go-sameids 79 | autocmd! * 80 | augroup end 81 | 82 | return 0 83 | endfunction 84 | 85 | function! go#sameids#ToggleSameIds() abort 86 | if go#sameids#ClearSameIds() != 0 87 | call go#sameids#SameIds(1) 88 | endif 89 | endfunction 90 | 91 | function! go#sameids#AutoToggleSameIds() abort 92 | if go#config#AutoSameids() 93 | call go#util#EchoProgress("sameids auto highlighting disabled") 94 | call go#sameids#ClearSameIds() 95 | call go#config#SetAutoSameids(0) 96 | else 97 | call go#util#EchoSuccess("sameids auto highlighting enabled") 98 | call go#config#SetAutoSameids(1) 99 | endif 100 | call go#auto#update_autocmd() 101 | endfunction 102 | 103 | " restore Vi compatibility settings 104 | let &cpo = s:cpo_save 105 | unlet s:cpo_save 106 | 107 | " vim: sw=2 ts=2 et 108 | -------------------------------------------------------------------------------- /rplugin/python3/denite/source/decls.py: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # FILE: decls.py 3 | # AUTHOR: delphinus 4 | # License: MIT license 5 | # ============================================================================ 6 | 7 | import os 8 | import subprocess 9 | import json 10 | import denite.util 11 | from .base import Base 12 | 13 | DECLS_SYNTAX_HIGHLIGHT = [ 14 | {'name': 'FilePath', 're': r'[^:]*\ze:', 'link': 'Comment'}, 15 | {'name': 'Line', 're': r'\d\+\ze :', 'link': 'LineNr'}, 16 | {'name': 'WholeFunction', 're': r'\vfunc %(\([^)]+\) )?[^(]+'}, 17 | {'name': 'Function', 'parent': 'WholeFunction', 18 | 're': r'\S\+\ze(', 'link': 'Function'}, 19 | {'name': 'WholeType', 're': r'type \S\+'}, 20 | {'name': 'Type', 'parent': 'WholeType', 21 | 're': r'\v( )@<=\S+', 'link': 'Type'}, 22 | {'name': 'Separator', 're': r':', 'conceal': True}, 23 | {'name': 'SeparatorFunction', 'parent': 'WholeFunction', 24 | 're': r'func ', 'conceal': True}, 25 | {'name': 'SeparatorType', 'parent': 'WholeType', 26 | 're': r'type ', 'conceal': True}, 27 | ] 28 | 29 | 30 | class Source(Base): 31 | 32 | def __init__(self, vim): 33 | super().__init__(vim) 34 | 35 | self.name = 'decls' 36 | self.kind = 'file' 37 | 38 | def gather_candidates(self, context): 39 | bin_path = self.vim.call('go#path#CheckBinPath', 'motion') 40 | if bin_path == '': 41 | return [] 42 | 43 | expand = context['args'][0] if context['args'] else '%:p:h' 44 | target = self.vim.funcs.expand(expand) 45 | 46 | if os.path.isdir(target): 47 | mode = 'dir' 48 | elif os.path.isfile(target): 49 | mode = 'file' 50 | else: 51 | return [] 52 | 53 | if self.vim.funcs.exists('g:go_decls_includes'): 54 | include = self.vim.eval('g:go_decls_includes') 55 | else: 56 | include = 'func,type' 57 | 58 | command = [bin_path, '-mode', 'decls', '-include', include, 59 | '-' + mode, target] 60 | 61 | try: 62 | cmd = subprocess.run(command, stdout=subprocess.PIPE, check=True) 63 | except subprocess.CalledProcessError as err: 64 | denite.util.error(self.vim, 65 | 'command returned invalid response: ' + str(err)) 66 | return [] 67 | 68 | txt = cmd.stdout.decode('utf-8') 69 | output = json.loads(txt) 70 | 71 | def make_candidates(row): 72 | name = self.vim.funcs.fnamemodify(row['filename'], ':~:.') 73 | return { 74 | 'word': '{0} :{1} :{2}'.format(name, row['line'], row['full']), 75 | 'action__path': row['filename'], 76 | 'action__line': row['line'], 77 | 'action__col': row['col'], 78 | } 79 | return list(map(make_candidates, output['decls'])) 80 | 81 | def highlight(self): 82 | for syn in DECLS_SYNTAX_HIGHLIGHT: 83 | containedin = self.syntax_name 84 | containedin += '_' + syn['parent'] if 'parent' in syn else '' 85 | conceal = ' conceal' if 'conceal' in syn else '' 86 | 87 | self.vim.command( 88 | 'syntax match {0}_{1} /{2}/ contained containedin={3}{4}' 89 | .format(self.syntax_name, syn['name'], syn['re'], 90 | containedin, conceal)) 91 | 92 | if 'link' in syn: 93 | self.vim.command('highlight default link {0}_{1} {2}'.format( 94 | self.syntax_name, syn['name'], syn['link'])) 95 | -------------------------------------------------------------------------------- /syntax/gosum.vim: -------------------------------------------------------------------------------- 1 | " gosum.vim: Vim syntax file for go.sum file 2 | " 3 | " Quit when a (custom) syntax file was already loaded 4 | if exists("b:current_syntax") 5 | finish 6 | endif 7 | 8 | syntax case match 9 | 10 | " highlight versions: 11 | " * vX.Y.Z-pre 12 | " * vX.Y.Z 13 | " * vX.0.0-yyyyymmddhhmmss-abcdefabcdef 14 | " * vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef 15 | " * vX.Y.(Z+1)-0.yyyymmddhhss-abcdefabcdef 16 | " see https://godoc.org/golang.org/x/tools/internal/semver for more 17 | " information about how semantic versions are parsed and 18 | " https://golang.org/cmd/go/ for how pseudo-versions and +incompatible 19 | " are applied. 20 | 21 | 22 | " match vX.Y.Z and their prereleases 23 | syntax match gomodVersion "v\d\+\.\d\+\.\d\+\%(-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?" 24 | " ^--- version ---^^------------ pre-release ---------------------^^--------------- metadata ---------------------^ 25 | " ^--------------------------------------- semantic version -------------------------------------------------------^ 26 | 27 | " match pseudo versions 28 | " without a major version before the commit (e.g. vX.0.0-yyyymmddhhmmss-abcdefabcdef) 29 | syntax match gomodVersion "v\d\+\.0\.0-\d\{14\}-\x\+" 30 | " when most recent version before target is a pre-release 31 | syntax match gomodVersion "v\d\+\.\d\+\.\d\+-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?\.0\.\d\{14}-\x\+" 32 | " ^--- version ---^^--- ------ pre-release -----------------^^--------------- metadata ---------------------^ 33 | " ^------------------------------------- semantic version --------------------------------------------------^ 34 | " most recent version before the target is X.Y.Z 35 | syntax match gomodVersion "v\d\+\.\d\+\.\d\+\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?-0\.\d\{14}-\x\+" 36 | " ^--- version ---^^--------------- metadata ---------------------^ 37 | 38 | " match incompatible vX.Y.Z and their prereleases 39 | syntax match gomodVersion "v[2-9]\{1}\d*\.\d\+\.\d\+\%(-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?+incompatible" 40 | " ^------- version -------^^------------- pre-release ---------------------^^--------------- metadata ---------------------^ 41 | " ^------------------------------------------- semantic version -----------------------------------------------------------^ 42 | 43 | " match incompatible pseudo versions 44 | " incompatible without a major version before the commit (e.g. vX.0.0-yyyymmddhhmmss-abcdefabcdef) 45 | syntax match gomodVersion "v[2-9]\{1}\d*\.0\.0-\d\{14\}-\x\++incompatible" 46 | " when most recent version before target is a pre-release 47 | syntax match gomodVersion "v[2-9]\{1}\d*\.\d\+\.\d\+-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?\.0\.\d\{14}-\x\++incompatible" 48 | " ^------- version -------^^---------- pre-release -----------------^^--------------- metadata ---------------------^ 49 | " ^---------------------------------------- semantic version ------------------------------------------------------^ 50 | " most recent version before the target is X.Y.Z 51 | syntax match gomodVersion "v[2-9]\{1}\d*\.\d\+\.\d\+\%(+\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?-0\.\d\{14}-\x\++incompatible" 52 | " ^------- version -------^^---------------- metadata ---------------------^ 53 | highlight default link gomodVersion Identifier 54 | 55 | let b:current_syntax = "gomod" 56 | -------------------------------------------------------------------------------- /autoload/go/term_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | func! Test_GoTermNewMode() 6 | if !(has('nvim') || has('terminal')) 7 | return 8 | endif 9 | 10 | let l:wd = getcwd() 11 | try 12 | let g:go_gopls_enabled = 0 13 | let l:filename = 'term/term.go' 14 | let l:tmp = gotest#load_fixture(l:filename) 15 | call go#util#Chdir(l:tmp . '/src/term') 16 | 17 | let expected = expand('%:p') 18 | let l:winid = win_getid() 19 | 20 | let l:expectedwindows = len(getwininfo()) + 1 21 | 22 | let cmd = "go run ". go#util#Shelljoin(go#tool#Files()) 23 | 24 | set nosplitright 25 | 26 | let l:jobid = go#term#new(0, cmd, &errorformat) 27 | 28 | call go#job#Wait(l:jobid) 29 | 30 | let actual = expand('%:p') 31 | call assert_equal(actual, l:expected) 32 | call assert_equal(l:expectedwindows, len(getwininfo())) 33 | 34 | finally 35 | call win_gotoid(l:winid) 36 | only! 37 | call go#util#Chdir(l:wd) 38 | call delete(l:tmp, 'rf') 39 | endtry 40 | endfunc 41 | 42 | func! Test_GoTermNewMode_SplitRight() 43 | if !(has('nvim') || has('terminal')) 44 | return 45 | endif 46 | 47 | let l:wd = getcwd() 48 | try 49 | let g:go_gopls_enabled = 0 50 | let l:filename = 'term/term.go' 51 | let l:tmp = gotest#load_fixture(l:filename) 52 | call go#util#Chdir(l:tmp . '/src/term') 53 | 54 | let expected = expand('%:p') 55 | let l:winid = win_getid() 56 | 57 | let l:expectedwindows = len(getwininfo()) + 1 58 | 59 | let cmd = "go run ". go#util#Shelljoin(go#tool#Files()) 60 | 61 | set splitright 62 | 63 | let l:jobid = go#term#new(0, cmd, &errorformat) 64 | 65 | call go#job#Wait(l:jobid) 66 | 67 | let actual = expand('%:p') 68 | call assert_equal(actual, l:expected) 69 | call assert_equal(l:expectedwindows, len(getwininfo())) 70 | 71 | finally 72 | call win_gotoid(l:winid) 73 | only! 74 | call go#util#Chdir(l:wd) 75 | call delete(l:tmp, 'rf') 76 | set nosplitright 77 | endtry 78 | endfunc 79 | 80 | func! Test_GoTermReuse() 81 | if !(has('nvim') || has('terminal')) 82 | return 83 | endif 84 | 85 | let l:wd = getcwd() 86 | try 87 | let g:go_gopls_enabled = 0 88 | let l:filename = 'term/term.go' 89 | let l:tmp = gotest#load_fixture(l:filename) 90 | 91 | call go#util#Chdir(l:tmp . '/src/term') 92 | 93 | let l:winid = win_getid() 94 | let expected = expand('%:p') 95 | 96 | let l:expectedwindows = len(getwininfo())+1 97 | 98 | let cmd = "go run ". go#util#Shelljoin(go#tool#Files()) 99 | 100 | set nosplitright 101 | 102 | " prime the terminal window 103 | let l:jobid = go#term#new(0, cmd, &errorformat) 104 | 105 | call go#job#Wait(l:jobid) 106 | 107 | let g:go_term_reuse = 1 108 | 109 | let l:jobid = go#term#new(0, cmd, &errorformat) 110 | 111 | call go#job#Wait(l:jobid) 112 | 113 | let actual = expand('%:p') 114 | call assert_equal(actual, l:expected) 115 | call assert_equal(l:expectedwindows, len(getwininfo())) 116 | 117 | let l:jobid = go#term#new(0, cmd, &errorformat) 118 | 119 | call go#job#Wait(l:jobid) 120 | 121 | let actual = expand('%:p') 122 | call assert_equal(actual, l:expected) 123 | 124 | call assert_equal(l:expectedwindows, len(getwininfo())) 125 | 126 | finally 127 | call win_gotoid(l:winid) 128 | only! 129 | call go#util#Chdir(l:wd) 130 | call delete(l:tmp, 'rf') 131 | endtry 132 | endfunc 133 | 134 | " restore Vi compatibility settings 135 | let &cpo = s:cpo_save 136 | unlet s:cpo_save 137 | 138 | " vim: sw=2 ts=2 et 139 | -------------------------------------------------------------------------------- /autoload/go/lsp_test.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | scriptencoding utf-8 6 | 7 | function! Test_GetSimpleTextPosition() 8 | call s:getinfo('lsp text position should align with cursor position after ascii only', 'ascii') 9 | endfunction 10 | 11 | function! Test_GetMultiByteTextPosition() 12 | call s:getinfo('lsp text position should align with cursor position after two place of interest symbols ⌘⌘', 'multi-byte') 13 | endfunction 14 | 15 | function! Test_GetMultipleCodeUnitTextPosition() 16 | call s:getinfo('lsp text position should align with cursor position after Deseret Capital Letter Long I 𐐀', 'multi-code-units') 17 | endfunction 18 | 19 | function! s:getinfo(str, name) 20 | if !go#util#has_job() 21 | return 22 | endif 23 | 24 | let l:wd = getcwd() 25 | try 26 | let g:go_info_mode = 'gopls' 27 | 28 | let l:tmp = gotest#write_file(a:name . '/position/position.go', [ 29 | \ 'package position', 30 | \ '', 31 | \ 'func Example() {', 32 | \ "\tid := " . '"foo"', 33 | \ "\tprintln(" .'"' . a:str . '", id)', 34 | \ '}', 35 | \ ] ) 36 | 37 | let l:expected = 'var id string' 38 | let l:actual = go#lsp#GetInfo() 39 | call assert_equal(l:expected, l:actual) 40 | finally 41 | call go#util#Chdir(l:wd) 42 | call delete(l:tmp, 'rf') 43 | endtry 44 | endfunction 45 | 46 | func! Test_Format() abort 47 | let l:wd = getcwd() 48 | try 49 | let expected = join(readfile("test-fixtures/lsp/fmt/format_golden.go"), "\n") 50 | let l:tmp = gotest#load_fixture('lsp/fmt/format.go') 51 | 52 | call go#lsp#Format() 53 | 54 | " this should now contain the formatted code 55 | let actual = join(go#util#GetLines(), "\n") 56 | 57 | call assert_equal(expected, actual) 58 | finally 59 | call go#util#Chdir(l:wd) 60 | call delete(l:tmp, 'rf') 61 | endtry 62 | endfunc 63 | 64 | func! Test_Format_SingleNewline() abort 65 | let l:wd = getcwd() 66 | try 67 | let expected = join(readfile("test-fixtures/lsp/fmt/format_golden.go"), "\n") 68 | let l:tmp = gotest#load_fixture('lsp/fmt/newline.go') 69 | 70 | call go#lsp#Format() 71 | 72 | " this should now contain the formatted code 73 | let actual = join(go#util#GetLines(), "\n") 74 | 75 | call assert_equal(expected, actual) 76 | finally 77 | call go#util#Chdir(l:wd) 78 | call delete(l:tmp, 'rf') 79 | endtry 80 | endfunc 81 | 82 | func! Test_Format_Multibyte() abort 83 | let l:wd = getcwd() 84 | try 85 | let expected = join(readfile("test-fixtures/lsp/fmt/multibyte_golden.go"), "\n") 86 | let l:tmp = gotest#load_fixture('lsp/fmt/multibyte.go') 87 | 88 | call go#lsp#Format() 89 | 90 | " this should now contain the formatted code 91 | let actual = join(go#util#GetLines(), "\n") 92 | 93 | call assert_equal(expected, actual) 94 | finally 95 | call go#util#Chdir(l:wd) 96 | call delete(l:tmp, 'rf') 97 | endtry 98 | endfunc 99 | 100 | func! Test_Imports() abort 101 | let l:wd = getcwd() 102 | try 103 | let expected = join(readfile("test-fixtures/lsp/imports/imports_golden.go"), "\n") 104 | let l:tmp = gotest#load_fixture('lsp/imports/imports.go') 105 | 106 | call go#lsp#Imports() 107 | 108 | " this should now contain the expected imports code 109 | let actual = join(go#util#GetLines(), "\n") 110 | 111 | call assert_equal(expected, actual) 112 | finally 113 | call go#util#Chdir(l:wd) 114 | call delete(l:tmp, 'rf') 115 | endtry 116 | endfunc 117 | 118 | " restore Vi compatibility settings 119 | let &cpo = s:cpo_save 120 | unlet s:cpo_save 121 | 122 | " vim: sw=2 ts=2 et 123 | -------------------------------------------------------------------------------- /autoload/go/ui.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | let s:buf_nr = -1 6 | 7 | "OpenWindow opens a new scratch window and put's the content into the window 8 | function! go#ui#OpenWindow(title, content, filetype) abort 9 | " Ensure there's only one return window in this session/tabpage 10 | call go#util#Windo("unlet! w:vim_go_return_window") 11 | " Mark the window we're leaving as such 12 | let w:vim_go_return_window = 1 13 | 14 | " reuse existing buffer window if it exists otherwise create a new one 15 | if !bufexists(s:buf_nr) 16 | execute 'botright new' 17 | file `="[" . a:title . "]"` 18 | let s:buf_nr = bufnr('%') 19 | elseif bufwinnr(s:buf_nr) == -1 20 | execute 'botright new' 21 | execute s:buf_nr . 'buffer' 22 | elseif bufwinnr(s:buf_nr) != bufwinnr('%') 23 | execute bufwinnr(s:buf_nr) . 'wincmd w' 24 | endif 25 | 26 | " Resize window to content length 27 | exe 'resize' . len(a:content) 28 | 29 | execute "setlocal filetype=".a:filetype 30 | 31 | " some sane default values for a readonly buffer 32 | setlocal bufhidden=delete 33 | setlocal buftype=nofile 34 | setlocal noswapfile 35 | setlocal nobuflisted 36 | setlocal winfixheight 37 | setlocal cursorline " make it easy to distinguish 38 | setlocal nonumber 39 | setlocal norelativenumber 40 | setlocal showbreak="" 41 | 42 | " we need this to purge the buffer content 43 | setlocal modifiable 44 | 45 | "delete everything first from the buffer 46 | %delete _ 47 | 48 | " add the content 49 | call append(0, a:content) 50 | 51 | " delete last line that comes from the append call 52 | $delete _ 53 | 54 | " set it back to non modifiable 55 | setlocal nomodifiable 56 | 57 | " Remove the '... [New File]' message line from the command line 58 | echon 59 | endfunction 60 | 61 | function! go#ui#GetReturnWindow() abort 62 | for l:wn in range(1, winnr("$")) 63 | if !empty(getwinvar(l:wn, "vim_go_return_window")) 64 | return l:wn 65 | endif 66 | endfor 67 | endfunction 68 | 69 | " CloseWindow closes the current window 70 | function! go#ui#CloseWindow() abort 71 | " Close any window associated with the ui buffer, if it's there 72 | if bufexists(s:buf_nr) 73 | let ui_window_number = bufwinnr(s:buf_nr) 74 | if ui_window_number != -1 75 | execute ui_window_number . 'close' 76 | endif 77 | endif 78 | 79 | "return to original window, if it's there 80 | let l:rw = go#ui#GetReturnWindow() 81 | if !empty(l:rw) 82 | execute l:rw . 'wincmd w' 83 | unlet! w:vim_go_return_window 84 | endif 85 | endfunction 86 | 87 | " OpenDefinition parses the current line and jumps to it by openening a new 88 | " tab 89 | function! go#ui#OpenDefinition(filter) abort 90 | let curline = getline('.') 91 | 92 | " don't touch our first line or any blank line 93 | if curline =~ a:filter || curline =~ "^$" 94 | " suppress information about calling this function 95 | echo "" 96 | return 97 | endif 98 | 99 | " format: 'interface file:lnum:coln' 100 | let mx = '^\(^\S*\)\s*\(.\{-}\):\(\d\+\):\(\d\+\)' 101 | 102 | " parse it now into the list 103 | let tokens = matchlist(curline, mx) 104 | 105 | " convert to: 'file:lnum:coln' 106 | let expr = tokens[2] . ":" . tokens[3] . ":" . tokens[4] 107 | 108 | " jump to it in a new tab, we use explicit lgetexpr so we can later change 109 | " the behaviour via settings (like opening in vsplit instead of tab) 110 | lgetexpr expr 111 | tab split 112 | ll 1 113 | 114 | " center the word 115 | norm! zz 116 | endfunction 117 | 118 | " restore Vi compatibility settings 119 | let &cpo = s:cpo_save 120 | unlet s:cpo_save 121 | 122 | " vim: sw=2 ts=2 et 123 | -------------------------------------------------------------------------------- /syntax/gotexttmpl.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2011 The Go Authors. All rights reserved. 2 | " Use of this source code is governed by a BSD-style 3 | " license that can be found in the LICENSE file. 4 | " 5 | " gotexttmpl.vim: Vim syntax file for Go templates. 6 | 7 | " Quit when a (custom) syntax file was already loaded 8 | if exists("b:current_syntax") 9 | finish 10 | endif 11 | 12 | syn case match 13 | 14 | " Go escapes 15 | syn match goEscapeOctal display contained "\\[0-7]\{3}" 16 | syn match goEscapeC display contained +\\[abfnrtv\\'"]+ 17 | syn match goEscapeX display contained "\\x\x\{2}" 18 | syn match goEscapeU display contained "\\u\x\{4}" 19 | syn match goEscapeBigU display contained "\\U\x\{8}" 20 | syn match goEscapeError display contained +\\[^0-7xuUabfnrtv\\'"]+ 21 | 22 | hi def link goEscapeOctal goSpecialString 23 | hi def link goEscapeC goSpecialString 24 | hi def link goEscapeX goSpecialString 25 | hi def link goEscapeU goSpecialString 26 | hi def link goEscapeBigU goSpecialString 27 | hi def link goSpecialString Special 28 | hi def link goEscapeError Error 29 | 30 | " Strings and their contents 31 | syn cluster goStringGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU,goEscapeError 32 | syn region goString contained start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@goStringGroup 33 | syn region goRawString contained start=+`+ end=+`+ 34 | 35 | hi def link goString String 36 | hi def link goRawString String 37 | 38 | " Characters; their contents 39 | syn cluster goCharacterGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU 40 | syn region goCharacter contained start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@goCharacterGroup 41 | 42 | hi def link goCharacter Character 43 | 44 | " Integers 45 | syn match goDecimalInt contained "\<\d\+\([Ee]\d\+\)\?\>" 46 | syn match goHexadecimalInt contained "\<0x\x\+\>" 47 | syn match goOctalInt contained "\<0\o\+\>" 48 | syn match goOctalError contained "\<0\o*[89]\d*\>" 49 | syn cluster goInt contains=goDecimalInt,goHexadecimalInt,goOctalInt 50 | " Floating point 51 | syn match goFloat contained "\<\d\+\.\d*\([Ee][-+]\d\+\)\?\>" 52 | syn match goFloat contained "\<\.\d\+\([Ee][-+]\d\+\)\?\>" 53 | syn match goFloat contained "\<\d\+[Ee][-+]\d\+\>" 54 | " Imaginary literals 55 | syn match goImaginary contained "\<\d\+i\>" 56 | syn match goImaginary contained "\<\d\+\.\d*\([Ee][-+]\d\+\)\?i\>" 57 | syn match goImaginary contained "\<\.\d\+\([Ee][-+]\d\+\)\?i\>" 58 | syn match goImaginary contained "\<\d\+[Ee][-+]\d\+i\>" 59 | 60 | hi def link goInt Number 61 | hi def link goFloat Number 62 | hi def link goImaginary Number 63 | 64 | " Token groups 65 | syn cluster gotplLiteral contains=goString,goRawString,goCharacter,@goInt,goFloat,goImaginary 66 | syn keyword gotplControl contained if else end range with template 67 | syn keyword gotplFunctions contained and html index js len not or print printf println urlquery eq ne lt le gt ge 68 | syn match gotplVariable contained /\$[a-zA-Z0-9_]*\>/ 69 | syn match goTplIdentifier contained /\.[^[:blank:]}]\+\>/ 70 | 71 | hi def link gotplControl Keyword 72 | hi def link gotplFunctions Function 73 | hi def link goTplVariable Special 74 | 75 | syn region gotplAction start="{{" end="}}" contains=@gotplLiteral,gotplControl,gotplFunctions,gotplVariable,goTplIdentifier display 76 | syn region goTplComment start="{{\(- \)\?/\*" end="\*/\( -\)\?}}" display 77 | 78 | hi def link gotplAction PreProc 79 | hi def link goTplComment Comment 80 | 81 | let b:current_syntax = "gotexttmpl" 82 | 83 | " vim: sw=2 ts=2 et 84 | -------------------------------------------------------------------------------- /autoload/ctrlp/decls.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | let s:go_decls_var = { 6 | \ 'init': 'ctrlp#decls#init()', 7 | \ 'exit': 'ctrlp#decls#exit()', 8 | \ 'enter': 'ctrlp#decls#enter()', 9 | \ 'accept': 'ctrlp#decls#accept', 10 | \ 'lname': 'declarations', 11 | \ 'sname': 'decls', 12 | \ 'type': 'tabs', 13 | \} 14 | 15 | if exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars) 16 | let g:ctrlp_ext_vars = add(g:ctrlp_ext_vars, s:go_decls_var) 17 | else 18 | let g:ctrlp_ext_vars = [s:go_decls_var] 19 | endif 20 | 21 | function! ctrlp#decls#init() abort 22 | cal s:enable_syntax() 23 | return s:decls 24 | endfunction 25 | 26 | function! ctrlp#decls#exit() abort 27 | unlet! s:decls s:target 28 | endfunction 29 | 30 | " The action to perform on the selected string 31 | " Arguments: 32 | " a:mode the mode that has been chosen by pressing or 33 | " the values are 'e', 'v', 't' and 'h', respectively 34 | " a:str the selected string 35 | function! ctrlp#decls#accept(mode, str) abort 36 | try 37 | let vals = matchlist(a:str, '|\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)|') 38 | 39 | " i.e: main.go 40 | let filename = vals[1] 41 | let line = vals[2] 42 | let col = vals[3] 43 | 44 | " i.e: /Users/fatih/vim-go/main.go 45 | let filepath = fnamemodify(filename, ":p") 46 | 47 | " acceptile is a very versatile method, 48 | call ctrlp#acceptfile(a:mode, filepath) 49 | call cursor(line, col) 50 | silent! norm! zvzz 51 | endtry 52 | endfunction 53 | 54 | function! ctrlp#decls#enter() abort 55 | let s:decls = [] 56 | 57 | let l:cmd = ['motion', 58 | \ '-format', 'vim', 59 | \ '-mode', 'decls', 60 | \ '-include', go#config#DeclsIncludes(), 61 | \ ] 62 | 63 | call go#cmd#autowrite() 64 | 65 | if s:mode == 0 66 | " current file mode 67 | let l:fname = expand("%:p") 68 | if exists('s:target') 69 | let l:fname = s:target 70 | endif 71 | 72 | let cmd += ['-file', l:fname] 73 | else 74 | " all functions mode 75 | let l:dir = expand("%:p:h") 76 | if exists('s:target') 77 | let l:dir = s:target 78 | endif 79 | 80 | let cmd += ['-dir', l:dir] 81 | endif 82 | 83 | let [l:out, l:err] = go#util#Exec(l:cmd) 84 | if l:err 85 | call go#util#EchoError(l:out) 86 | return 87 | endif 88 | 89 | let result = eval(out) 90 | if type(result) != 4 || !has_key(result, 'decls') 91 | return 92 | endif 93 | 94 | let decls = result.decls 95 | 96 | " find the maximum function name 97 | let max_len = 0 98 | for decl in decls 99 | if len(decl.ident)> max_len 100 | let max_len = len(decl.ident) 101 | endif 102 | endfor 103 | 104 | for decl in decls 105 | " paddings 106 | let space = " " 107 | for i in range(max_len - len(decl.ident)) 108 | let space .= " " 109 | endfor 110 | 111 | call add(s:decls, printf("%s\t%s |%s:%s:%s|\t%s", 112 | \ decl.ident . space, 113 | \ decl.keyword, 114 | \ fnamemodify(decl.filename, ":p"), 115 | \ decl.line, 116 | \ decl.col, 117 | \ decl.full, 118 | \)) 119 | endfor 120 | endfunc 121 | 122 | function! s:enable_syntax() abort 123 | if !(has('syntax') && exists('g:syntax_on')) 124 | return 125 | endif 126 | 127 | syntax match CtrlPIdent '\zs\h\+\ze\s' 128 | syntax match CtrlPKeyword '\zs[^\t|]\+\ze|[^|]\+:\d\+:\d\+|' 129 | syntax match CtrlPFilename '|\zs[^|]\+:\d\+:\d\+\ze|' 130 | syntax match CtrlPSignature '\zs\t.*\ze$' contains=CtrlPKeyWord,CtrlPFilename 131 | 132 | highlight link CtrlPIdent Function 133 | highlight link CtrlPKeyword Keyword 134 | highlight link CtrlPFilename SpecialComment 135 | highlight link CtrlPSignature Comment 136 | endfunction 137 | 138 | let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars) 139 | 140 | function! ctrlp#decls#cmd(mode, ...) abort 141 | let s:mode = a:mode 142 | if a:0 && !empty(a:1) 143 | let s:target = a:1 144 | endif 145 | return s:id 146 | endfunction 147 | 148 | " restore Vi compatibility settings 149 | let &cpo = s:cpo_save 150 | unlet s:cpo_save 151 | 152 | " vim: sw=2 ts=2 et 153 | -------------------------------------------------------------------------------- /autoload/go/statusline.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | " Statusline 6 | """""""""""""""""""""""""""""""" 7 | 8 | " s:statuses is a global reference to all statuses. It stores the statuses per 9 | " import paths (map[string]status), where each status is unique per its 10 | " type. Current status dict is in form: 11 | " { 12 | " 'desc' : 'Job description', 13 | " 'state' : 'Job state, such as success, failure, etc..', 14 | " 'type' : 'Job type, such as build, test, etc..' 15 | " 'created_at' : 'Time it was created as seconds since 1st Jan 1970' 16 | " } 17 | let s:statuses = {} 18 | 19 | " timer_id for cleaner 20 | let s:timer_id = 0 21 | 22 | " last_status stores the last generated text per status 23 | let s:last_status = "" 24 | 25 | " Show returns the current status of the job for 20 seconds (configurable). It 26 | " displays it in form of 'desc: [type|state]' if there is any state available, 27 | " if not it returns an empty string. This function should be plugged directly 28 | " into the statusline. 29 | function! go#statusline#Show() abort 30 | " lazy initialization of the cleaner 31 | if !s:timer_id 32 | let interval = go#config#StatuslineDuration() 33 | let s:timer_id = timer_start(interval, function('go#statusline#Clear'), {'repeat': -1}) 34 | endif 35 | 36 | " nothing to show 37 | if empty(s:statuses) 38 | return '' 39 | endif 40 | 41 | let status_dir = expand('%:p:h') 42 | 43 | if !has_key(s:statuses, status_dir) 44 | return '' 45 | endif 46 | 47 | let status = s:statuses[status_dir] 48 | if !has_key(status, 'desc') || !has_key(status, 'state') || !has_key(status, 'type') 49 | return '' 50 | endif 51 | 52 | let status_text = printf("[%s|%s]", status.type, status.state) 53 | if empty(status_text) 54 | return '' 55 | endif 56 | 57 | " only update highlight if status has changed. 58 | if status_text != s:last_status 59 | if status.state =~ "success" || status.state =~ "finished" || status.state =~ "pass" || status.state =~ 'initialized' 60 | hi goStatusLineColor cterm=bold ctermbg=76 ctermfg=22 guibg=#5fd700 guifg=#005f00 61 | elseif status.state =~ "started" || status.state =~ "analysing" || status.state =~ "compiling" || status.state =~ 'initializing' 62 | hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88 guibg=#ff8700 guifg=#870000 63 | elseif status.state =~ "failed" 64 | hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52 guibg=#ff0000 guifg=#5f0000 65 | endif 66 | endif 67 | 68 | let s:last_status = status_text 69 | return status_text 70 | endfunction 71 | 72 | " Update updates (adds) the statusline for the given status_dir with the 73 | " given status dict. It overrides any previously set status. 74 | function! go#statusline#Update(status_dir, status) abort 75 | let a:status.created_at = reltime() 76 | let s:statuses[a:status_dir] = a:status 77 | 78 | " force to update the statusline, otherwise the user needs to move the 79 | " cursor 80 | exe 'let &ro = &ro' 81 | 82 | " before we stop the timer, check if we have any previous jobs to be cleaned 83 | " up. Otherwise every job will reset the timer when this function is called 84 | " and thus old jobs will never be cleaned 85 | call s:clear() 86 | 87 | " also reset the timer, so the user has time to see it in the statusline. 88 | " Setting the timer_id to 0 will cause a new timer to be created the next 89 | " time the go#statusline#Show() is called. 90 | call timer_stop(s:timer_id) 91 | let s:timer_id = 0 92 | endfunction 93 | 94 | " Clear clears all currently stored statusline data. The timer_id argument is 95 | " just a placeholder so we can pass it to a timer_start() function if needed. 96 | function! go#statusline#Clear(timer_id) abort 97 | call s:clear() 98 | endfunction 99 | 100 | function! s:clear() 101 | for [status_dir, status] in items(s:statuses) 102 | let elapsed_time = reltimestr(reltime(status.created_at)) 103 | " strip whitespace 104 | let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') 105 | 106 | if str2nr(elapsed_time) > 10 107 | call remove(s:statuses, status_dir) 108 | endif 109 | endfor 110 | 111 | if len(s:statuses) == 0 112 | let s:statuses = {} 113 | endif 114 | 115 | " force to update the statusline, otherwise the user needs to move the 116 | " cursor 117 | exe 'let &ro = &ro' 118 | endfunction 119 | 120 | " restore Vi compatibility settings 121 | let &cpo = s:cpo_save 122 | unlet s:cpo_save 123 | 124 | " vim: sw=2 ts=2 et 125 | -------------------------------------------------------------------------------- /autoload/go/mod.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | let s:go_major_version = "" 6 | 7 | function! go#mod#Format() abort 8 | " go mod only exists in `v1.11` 9 | if empty(s:go_major_version) 10 | let tokens = matchlist(go#util#Exec(['go', 'version']), '\d\+.\(\d\+\)\(\.\d\+\)\? ') 11 | if len(tokens) > 0 12 | let s:go_major_version = str2nr(tokens[1]) 13 | else 14 | let s:go_major_version = "" 15 | endif 16 | endif 17 | 18 | if !empty(s:go_major_version) && s:go_major_version < "11" 19 | call go#util#EchoError("Go v1.11 is required to format go.mod file") 20 | return 21 | endif 22 | 23 | let fname = fnamemodify(expand("%"), ':p:gs?\\?/?') 24 | 25 | " Save cursor position and many other things. 26 | let l:curw = winsaveview() 27 | 28 | " Write current unsaved buffer to a temp file 29 | let l:tmpname = tempname() . '.mod' 30 | call writefile(go#util#GetLines(), l:tmpname) 31 | if go#util#IsWin() 32 | let l:tmpname = tr(l:tmpname, '\', '/') 33 | endif 34 | 35 | let current_col = col('.') 36 | let l:args = ['go', 'mod', 'edit', '--fmt', l:tmpname] 37 | let [l:out, l:err] = go#util#Exec(l:args) 38 | let diff_offset = len(readfile(l:tmpname)) - line('$') 39 | 40 | if l:err == 0 41 | call go#mod#update_file(l:tmpname, fname) 42 | else 43 | let errors = s:parse_errors(fname, l:out) 44 | call s:show_errors(errors) 45 | endif 46 | 47 | " We didn't use the temp file, so clean up 48 | call delete(l:tmpname) 49 | 50 | " Restore our cursor/windows positions. 51 | call winrestview(l:curw) 52 | 53 | " be smart and jump to the line the new statement was added/removed 54 | call cursor(line('.') + diff_offset, current_col) 55 | 56 | " Syntax highlighting breaks less often. 57 | syntax sync fromstart 58 | endfunction 59 | 60 | " update_file updates the target file with the given formatted source 61 | function! go#mod#update_file(source, target) 62 | " remove undo point caused via BufWritePre 63 | try | silent undojoin | catch | endtry 64 | 65 | let old_fileformat = &fileformat 66 | if exists("*getfperm") 67 | " save file permissions 68 | let original_fperm = getfperm(a:target) 69 | endif 70 | 71 | call rename(a:source, a:target) 72 | 73 | " restore file permissions 74 | if exists("*setfperm") && original_fperm != '' 75 | call setfperm(a:target , original_fperm) 76 | endif 77 | 78 | " reload buffer to reflect latest changes 79 | silent edit! 80 | 81 | let &fileformat = old_fileformat 82 | let &syntax = &syntax 83 | 84 | let l:listtype = go#list#Type("GoModFmt") 85 | 86 | " clean up previous list 87 | if l:listtype == "quickfix" 88 | let l:list_title = getqflist({'title': 1}) 89 | else 90 | let l:list_title = getloclist(0, {'title': 1}) 91 | endif 92 | 93 | if has_key(l:list_title, "title") && l:list_title['title'] == "Format" 94 | call go#list#Clean(l:listtype) 95 | endif 96 | endfunction 97 | 98 | " parse_errors parses the given errors and returns a list of parsed errors 99 | function! s:parse_errors(filename, content) abort 100 | let splitted = split(a:content, '\n') 101 | 102 | " list of errors to be put into location list 103 | let errors = [] 104 | for line in splitted 105 | let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\s*\(.*\)') 106 | if !empty(tokens) 107 | call add(errors,{ 108 | \"filename": a:filename, 109 | \"lnum": tokens[2], 110 | \"text": tokens[3], 111 | \ }) 112 | endif 113 | endfor 114 | 115 | return errors 116 | endfunction 117 | 118 | " show_errors opens a location list and shows the given errors. If the given 119 | " errors is empty, it closes the the location list 120 | function! s:show_errors(errors) abort 121 | let l:listtype = go#list#Type("GoModFmt") 122 | if !empty(a:errors) 123 | call go#list#Populate(l:listtype, a:errors, 'Format') 124 | call go#util#EchoError("GoModFmt returned error") 125 | endif 126 | 127 | " this closes the window if there are no errors or it opens 128 | " it if there is any 129 | call go#list#Window(l:listtype, len(a:errors)) 130 | endfunction 131 | 132 | function! go#mod#ToggleModFmtAutoSave() abort 133 | if go#config#ModFmtAutosave() 134 | call go#config#SetModFmtAutosave(0) 135 | call go#util#EchoProgress("auto mod fmt disabled") 136 | return 137 | end 138 | 139 | call go#config#SetModFmtAutosave(1) 140 | call go#util#EchoProgress("auto mod fmt enabled") 141 | endfunction 142 | 143 | " restore Vi compatibility settings 144 | let &cpo = s:cpo_save 145 | unlet s:cpo_save 146 | 147 | " vim: sw=2 ts=2 et 148 | -------------------------------------------------------------------------------- /autoload/go/tool.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | " From "go list -h". 6 | function! go#tool#ValidFiles(...) 7 | let l:list = ["GoFiles", "CgoFiles", "IgnoredGoFiles", "CFiles", "CXXFiles", 8 | \ "MFiles", "HFiles", "FFiles", "SFiles", "SwigFiles", "SwigCXXFiles", 9 | \ "SysoFiles", "TestGoFiles", "XTestGoFiles"] 10 | 11 | " Used as completion 12 | if len(a:000) > 0 13 | let l:list = filter(l:list, 'strpart(v:val, 0, len(a:1)) == a:1') 14 | endif 15 | 16 | return l:list 17 | endfunction 18 | 19 | function! go#tool#Files(...) abort 20 | if len(a:000) > 0 21 | let source_files = a:000 22 | else 23 | let source_files = ['GoFiles'] 24 | endif 25 | 26 | let combined = '' 27 | for sf in source_files 28 | " Strip dot in case people used ":GoFiles .GoFiles". 29 | let sf = substitute(sf, '^\.', '', '') 30 | 31 | " Make sure the passed options are valid. 32 | if index(go#tool#ValidFiles(), sf) == -1 33 | echoerr "unknown source file variable: " . sf 34 | endif 35 | 36 | if go#util#IsWin() 37 | let combined .= '{{range $f := .' . sf . '}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}' 38 | else 39 | let combined .= "{{range $f := ." . sf . "}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}" 40 | endif 41 | endfor 42 | 43 | let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:combined]) 44 | return split(l:out, '\n') 45 | endfunction 46 | 47 | function! go#tool#Deps() abort 48 | if go#util#IsWin() 49 | let format = '{{range $f := .Deps}}{{$f}}{{printf \"\n\"}}{{end}}' 50 | else 51 | let format = "{{range $f := .Deps}}{{$f}}\n{{end}}" 52 | endif 53 | let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:format]) 54 | return split(l:out, '\n') 55 | endfunction 56 | 57 | function! go#tool#Imports() abort 58 | let imports = {} 59 | if go#util#IsWin() 60 | let format = '{{range $f := .Imports}}{{$f}}{{printf \"\n\"}}{{end}}' 61 | else 62 | let format = "{{range $f := .Imports}}{{$f}}{{printf \"\\n\"}}{{end}}" 63 | endif 64 | let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:format]) 65 | if l:err != 0 66 | echo out 67 | return imports 68 | endif 69 | 70 | for package_path in split(out, '\n') 71 | let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.Name}}', l:package_path]) 72 | if l:err != 0 73 | echo out 74 | return imports 75 | endif 76 | let package_name = substitute(l:out, '\n$', '', '') 77 | let imports[package_name] = package_path 78 | endfor 79 | 80 | return imports 81 | endfunction 82 | 83 | function! go#tool#Info(showstatus) abort 84 | if !go#config#GoplsEnabled() 85 | call go#util#EchoError("gopls is disabled") 86 | return 87 | endif 88 | call go#lsp#Info(a:showstatus) 89 | endfunction 90 | 91 | function! go#tool#PackageName() abort 92 | let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.Name}}']) 93 | if l:err != 0 94 | return -1 95 | endif 96 | 97 | return split(out, '\n')[0] 98 | endfunction 99 | 100 | " Exists checks whether the given importpath exists or not. It returns 0 if 101 | " the importpath exists under GOPATH. 102 | function! go#tool#Exists(importpath) abort 103 | let [l:out, l:err] = go#util#ExecInDir(['go', 'list', a:importpath]) 104 | if l:err != 0 105 | return -1 106 | endif 107 | 108 | return 0 109 | endfunction 110 | 111 | function! go#tool#List(package_path) abort 112 | let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.ImportPath}}', a:package_path]) 113 | if l:err != 0 114 | return -1 115 | endif 116 | 117 | return split(out, '\n') 118 | endfunction 119 | 120 | function! go#tool#DescribeBalloon() 121 | let l:fname = fnamemodify(bufname(v:beval_bufnr), ':p') 122 | 123 | let l:winid = win_getid() 124 | 125 | call win_gotoid(bufwinid(v:beval_bufnr)) 126 | 127 | let [l:line, l:col] = go#lsp#lsp#Position(v:beval_lnum, v:beval_col) 128 | call go#lsp#Hover(l:fname, l:line, l:col, funcref('s:balloon', [])) 129 | 130 | call win_gotoid(l:winid) 131 | return '' 132 | endfunction 133 | 134 | function! s:balloon(msg) 135 | let l:msg = a:msg 136 | if has('balloon_eval') 137 | if has('balloon_multiline') 138 | let l:msg = join(a:msg, "\n") 139 | endif 140 | endif 141 | 142 | call balloon_show(l:msg) 143 | endfunction 144 | 145 | " restore Vi compatibility settings 146 | let &cpo = s:cpo_save 147 | unlet s:cpo_save 148 | 149 | " vim: sw=2 ts=2 et 150 | -------------------------------------------------------------------------------- /autoload/fzf/decls.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! s:code(group, attr) abort 6 | let code = synIDattr(synIDtrans(hlID(a:group)), a:attr, "cterm") 7 | if code =~ '^[0-9]\+$' 8 | return code 9 | endif 10 | endfunction 11 | 12 | function! s:color(str, group) abort 13 | let fg = s:code(a:group, "fg") 14 | let bg = s:code(a:group, "bg") 15 | let bold = s:code(a:group, "bold") 16 | let italic = s:code(a:group, "italic") 17 | let reverse = s:code(a:group, "reverse") 18 | let underline = s:code(a:group, "underline") 19 | let color = (empty(fg) ? "" : ("38;5;".fg)) . 20 | \ (empty(bg) ? "" : (";48;5;".bg)) . 21 | \ (empty(bold) ? "" : ";1") . 22 | \ (empty(italic) ? "" : ";3") . 23 | \ (empty(reverse) ? "" : ";7") . 24 | \ (empty(underline) ? "" : ";4") 25 | return printf("\x1b[%sm%s\x1b[m", color, a:str) 26 | endfunction 27 | 28 | function! s:sink(str) abort 29 | if len(a:str) < 2 30 | return 31 | endif 32 | try 33 | " we jump to the file directory so we can get the fullpath via fnamemodify 34 | " below 35 | let l:dir = go#util#Chdir(s:current_dir) 36 | 37 | let vals = matchlist(a:str[1], '|\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)|') 38 | 39 | " i.e: main.go 40 | let filename = vals[1] 41 | let line = vals[2] 42 | let col = vals[3] 43 | 44 | " i.e: /Users/fatih/vim-go/main.go 45 | let filepath = fnamemodify(filename, ":p") 46 | 47 | let cmd = get({'ctrl-x': 'split', 48 | \ 'ctrl-v': 'vertical split', 49 | \ 'ctrl-t': 'tabe'}, a:str[0], 'e') 50 | execute cmd fnameescape(filepath) 51 | call cursor(line, col) 52 | silent! norm! zvzz 53 | finally 54 | "jump back to old dir 55 | call go#util#Chdir(l:dir) 56 | endtry 57 | endfunction 58 | 59 | function! s:source(mode,...) abort 60 | let s:current_dir = expand('%:p:h') 61 | let ret_decls = [] 62 | 63 | let l:cmd = ['motion', 64 | \ '-format', 'vim', 65 | \ '-mode', 'decls', 66 | \ '-include', go#config#DeclsIncludes(), 67 | \ ] 68 | 69 | call go#cmd#autowrite() 70 | 71 | if a:mode == 0 72 | " current file mode 73 | let l:fname = expand("%:p") 74 | if a:0 && !empty(a:1) 75 | let l:fname = a:1 76 | endif 77 | 78 | let cmd += ['-file', l:fname] 79 | else 80 | " all functions mode 81 | if a:0 && !empty(a:1) 82 | let s:current_dir = a:1 83 | endif 84 | 85 | let l:cmd += ['-dir', s:current_dir] 86 | endif 87 | 88 | let [l:out, l:err] = go#util#Exec(l:cmd) 89 | if l:err 90 | call go#util#EchoError(l:out) 91 | return 92 | endif 93 | 94 | let result = eval(out) 95 | if type(result) != 4 || !has_key(result, 'decls') 96 | return ret_decls 97 | endif 98 | 99 | let decls = result.decls 100 | 101 | " find the maximum function name 102 | let max_len = 0 103 | for decl in decls 104 | if len(decl.ident)> max_len 105 | let max_len = len(decl.ident) 106 | endif 107 | endfor 108 | 109 | for decl in decls 110 | " paddings 111 | let space = " " 112 | for i in range(max_len - len(decl.ident)) 113 | let space .= " " 114 | endfor 115 | 116 | let pos = printf("|%s:%s:%s|", 117 | \ fnamemodify(decl.filename, ":t"), 118 | \ decl.line, 119 | \ decl.col 120 | \) 121 | call add(ret_decls, printf("%s\t%s\t%s\t%s", 122 | \ s:color(decl.ident . space, "goDeclsFzfFunction"), 123 | \ s:color(decl.keyword, "goDeclsFzfKeyword"), 124 | \ s:color(decl.full, "goDeclsFzfComment"), 125 | \ s:color(pos, "goDeclsFzfSpecialComment"), 126 | \)) 127 | endfor 128 | 129 | return sort(ret_decls) 130 | endfunc 131 | 132 | function! fzf#decls#cmd(...) abort 133 | let normal_fg = s:code("Normal", "fg") 134 | let normal_bg = s:code("Normal", "bg") 135 | let cursor_fg = s:code("CursorLine", "fg") 136 | let cursor_bg = s:code("CursorLine", "bg") 137 | let colors = printf(" --color %s%s%s%s%s", 138 | \ &background, 139 | \ empty(normal_fg) ? "" : (",fg:".normal_fg), 140 | \ empty(normal_bg) ? "" : (",bg:".normal_bg), 141 | \ empty(cursor_fg) ? "" : (",fg+:".cursor_fg), 142 | \ empty(cursor_bg) ? "" : (",bg+:".cursor_bg), 143 | \) 144 | call fzf#run(fzf#wrap('GoDecls', { 145 | \ 'source': call('source', a:000), 146 | \ 'options': printf('-n 1 --with-nth 1,2 --delimiter=$''\t'' --preview "echo {3}" --preview-window "wrap" --ansi --prompt "GoDecls> " --expect=ctrl-t,ctrl-v,ctrl-x%s', colors), 147 | \ 'sink*': function('s:sink') 148 | \ })) 149 | endfunction 150 | 151 | " restore Vi compatibility settings 152 | let &cpo = s:cpo_save 153 | unlet s:cpo_save 154 | 155 | " vim: sw=2 ts=2 et 156 | -------------------------------------------------------------------------------- /autoload/go/rename.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#rename#Rename(bang, ...) abort 6 | let to_identifier = "" 7 | if a:0 == 0 8 | let ask = printf("vim-go: rename '%s' to: ", expand("")) 9 | let prefill = go#config#GorenamePrefill() 10 | if prefill != '' 11 | let to_identifier = input(ask, eval(prefill)) 12 | else 13 | let to_identifier = input(ask) 14 | endif 15 | redraw! 16 | if empty(to_identifier) 17 | return 18 | endif 19 | else 20 | let to_identifier = a:1 21 | endif 22 | 23 | let l:bin = go#config#RenameCommand() 24 | 25 | " return with a warning if the bin doesn't exist 26 | let bin_path = go#path#CheckBinPath(substitute(l:bin, 'gopls rename$', 'gopls', '')) 27 | if empty(bin_path) 28 | return 29 | endif 30 | 31 | if l:bin == 'gopls' 32 | call go#lsp#Rename(to_identifier) 33 | return 34 | endif 35 | 36 | let fname = expand('%:p') 37 | let pos = go#util#OffsetCursor() 38 | 39 | let args = [] 40 | if l:bin == 'gorename' 41 | let offset = printf('%s:#%d', fname, pos) 42 | let l:args = extend(l:args, ['-tags', go#config#BuildTags(), '-offset', offset, '-to', to_identifier]) 43 | elseif l:bin == 'gopls rename' 44 | let offset = printf('%s:#%d', fname, pos) 45 | let l:args = extend(l:args, ['rename', '-write', offset, to_identifier]) 46 | else 47 | call go#util#EchoWarning('unexpected rename command') 48 | endif 49 | 50 | let l:cmd = extend([l:bin_path], l:args) 51 | 52 | if go#util#has_job() 53 | call s:rename_job({ 54 | \ 'cmd': cmd, 55 | \ 'bang': a:bang, 56 | \}) 57 | return 58 | endif 59 | 60 | let l:wd = go#util#ModuleRoot() 61 | if l:wd == -1 62 | let l:wd = expand("%:p:h") 63 | endif 64 | 65 | let [l:out, l:err] = go#util#ExecInWorkDir(l:cmd, l:wd) 66 | call s:parse_errors(l:err, a:bang, split(l:out, '\n')) 67 | endfunction 68 | 69 | function s:rename_job(args) 70 | let l:job_opts = { 71 | \ 'bang': a:args.bang, 72 | \ 'for': 'GoRename', 73 | \ 'statustype': 'gorename', 74 | \ } 75 | 76 | " autowrite is not enabled for jobs 77 | call go#cmd#autowrite() 78 | let l:cbs = go#job#Options(l:job_opts) 79 | 80 | let l:wd = go#util#ModuleRoot() 81 | if l:wd != -1 82 | let l:cbs.cwd = l:wd 83 | endif 84 | 85 | " wrap l:cbs.exit_cb in s:exit_cb. 86 | let l:cbs.exit_cb = funcref('s:exit_cb', [l:cbs.exit_cb]) 87 | 88 | call go#job#Start(a:args.cmd, l:cbs) 89 | endfunction 90 | 91 | function! s:reload_changed() abort 92 | " reload all files to reflect the new changes. We explicitly call 93 | " checktime to trigger a reload of all files. See 94 | " http://www.mail-archive.com/vim@vim.org/msg05900.html for more info 95 | " about the autoread bug 96 | let current_autoread = &autoread 97 | set autoread 98 | silent! checktime 99 | let &autoread = current_autoread 100 | endfunction 101 | 102 | " s:exit_cb reloads any changed buffers and then calls next. 103 | function! s:exit_cb(next, job, exitval) abort 104 | call s:reload_changed() 105 | call call(a:next, [a:job, a:exitval]) 106 | endfunction 107 | 108 | function s:parse_errors(exit_val, bang, out) 109 | " reload all files to reflect the new changes. We explicitly call 110 | " checktime to trigger a reload of all files. See 111 | " http://www.mail-archive.com/vim@vim.org/msg05900.html for more info 112 | " about the autoread bug 113 | let current_autoread = &autoread 114 | set autoread 115 | silent! checktime 116 | let &autoread = current_autoread 117 | 118 | let l:listtype = go#list#Type("GoRename") 119 | if a:exit_val != 0 120 | let errors = go#util#ParseErrors(a:out) 121 | call go#list#Populate(l:listtype, errors, 'Rename') 122 | call go#list#Window(l:listtype, len(errors)) 123 | if !empty(errors) && !a:bang 124 | call go#list#JumpToFirst(l:listtype) 125 | elseif empty(errors) 126 | " failed to parse errors, output the original content 127 | call go#util#EchoError(a:out) 128 | endif 129 | 130 | return 131 | endif 132 | 133 | " strip out newline on the end that gorename puts. If we don't remove, it 134 | " will trigger the 'Hit ENTER to continue' prompt 135 | call go#list#Clean(l:listtype) 136 | call go#util#EchoSuccess(a:out[0]) 137 | 138 | " refresh the buffer so we can see the new content 139 | silent execute ":e" 140 | endfunction 141 | 142 | " Commandline completion: original, unexported camelCase, and exported 143 | " CamelCase. 144 | function! go#rename#Complete(lead, cmdline, cursor) 145 | let l:word = expand('') 146 | return filter(uniq(sort( 147 | \ [l:word, go#util#camelcase(l:word), go#util#pascalcase(l:word)])), 148 | \ 'strpart(v:val, 0, len(a:lead)) == a:lead') 149 | endfunction 150 | 151 | " restore Vi compatibility settings 152 | let &cpo = s:cpo_save 153 | unlet s:cpo_save 154 | 155 | " vim: sw=2 ts=2 et 156 | -------------------------------------------------------------------------------- /syntax/gowork.vim: -------------------------------------------------------------------------------- 1 | " gowork.vim: Vim syntax file for go.work file 2 | " 3 | " Quit when a (custom) syntax file was already loaded 4 | if exists("b:current_syntax") 5 | finish 6 | endif 7 | 8 | syntax case match 9 | 10 | " Reference documentation: 11 | " https://go.dev/ref/mod#workspaces 12 | 13 | " match keywords 14 | syntax keyword goworkGo go contained 15 | syntax keyword goworkUse use 16 | syntax keyword goworkReplace replace 17 | 18 | " use, exclude, replace, and go can be also grouped into block 19 | syntax region goworkUse start='use (' end=')' transparent contains=goworkUse 20 | syntax region goworkReplace start='replace (' end=')' transparent contains=goworkReplace,goworkVersion 21 | syntax match goworkGo '^go .*$' transparent contains=goworkGo,goworkGoVersion 22 | 23 | " set highlights 24 | highlight default link goworkGo Keyword 25 | highlight default link goworkUse Keyword 26 | highlight default link goworkReplace Keyword 27 | 28 | " comments are always in form of // ... 29 | syntax region goworkComment start="//" end="$" contains=@Spell 30 | highlight default link goworkComment Comment 31 | 32 | " make sure quoted import paths are higlighted 33 | syntax region goworkString start=+"+ skip=+\\\\\|\\"+ end=+"+ 34 | highlight default link goworkString String 35 | 36 | " replace operator is in the form of '=>' 37 | syntax match goworkReplaceOperator "\v\=\>" 38 | highlight default link goworkReplaceOperator Operator 39 | 40 | " match go versions 41 | syntax match goworkGoVersion "1\.\d\+" contained 42 | highlight default link goworkGoVersion Identifier 43 | 44 | " highlight versions: 45 | " * vX.Y.Z-pre 46 | " * vX.Y.Z 47 | " * vX.0.0-yyyyymmddhhmmss-abcdefabcdef 48 | " * vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef 49 | " * vX.Y.(Z+1)-0.yyyymmddhhss-abcdefabcdef 50 | " see https://godoc.org/golang.org/x/tools/internal/semver for more 51 | " information about how semantic versions are parsed and 52 | " https://golang.org/cmd/go/ for how pseudo-versions and +incompatible 53 | " are applied. 54 | 55 | 56 | " match vX.Y.Z and their prereleases 57 | syntax match goworkVersion "v\d\+\.\d\+\.\d\+\%(-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?" 58 | " ^--- version ---^^------------ pre-release ---------------------^^--------------- metadata ---------------------^ 59 | " ^--------------------------------------- semantic version -------------------------------------------------------^ 60 | 61 | " match pseudo versions 62 | " without a major version before the commit (e.g. vX.0.0-yyyymmddhhmmss-abcdefabcdef) 63 | syntax match goworkVersion "v\d\+\.0\.0-\d\{14\}-\x\+" 64 | " when most recent version before target is a pre-release 65 | syntax match goworkVersion "v\d\+\.\d\+\.\d\+-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?\.0\.\d\{14}-\x\+" 66 | " ^--- version ---^^--- ------ pre-release -----------------^^--------------- metadata ---------------------^ 67 | " ^------------------------------------- semantic version --------------------------------------------------^ 68 | " most recent version before the target is X.Y.Z 69 | syntax match goworkVersion "v\d\+\.\d\+\.\d\+\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?-0\.\d\{14}-\x\+" 70 | " ^--- version ---^^--------------- metadata ---------------------^ 71 | 72 | " match incompatible vX.Y.Z and their prereleases 73 | syntax match goworkVersion "v[2-9]\{1}\d*\.\d\+\.\d\+\%(-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?+incompatible" 74 | " ^------- version -------^^------------- pre-release ---------------------^^--------------- metadata ---------------------^ 75 | " ^------------------------------------------- semantic version -----------------------------------------------------------^ 76 | 77 | " match incompatible pseudo versions 78 | " incompatible without a major version before the commit (e.g. vX.0.0-yyyymmddhhmmss-abcdefabcdef) 79 | syntax match goworkVersion "v[2-9]\{1}\d*\.0\.0-\d\{14\}-\x\++incompatible" 80 | " when most recent version before target is a pre-release 81 | syntax match goworkVersion "v[2-9]\{1}\d*\.\d\+\.\d\+-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?\.0\.\d\{14}-\x\++incompatible" 82 | " ^------- version -------^^---------- pre-release -----------------^^--------------- metadata ---------------------^ 83 | " ^---------------------------------------- semantic version ------------------------------------------------------^ 84 | " most recent version before the target is X.Y.Z 85 | syntax match goworkVersion "v[2-9]\{1}\d*\.\d\+\.\d\+\%(+\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?-0\.\d\{14}-\x\++incompatible" 86 | " ^------- version -------^^---------------- metadata ---------------------^ 87 | highlight default link goworkVersion Identifier 88 | 89 | let b:current_syntax = "gowork" 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-go [![GitHub Actions Status](https://github.com/fatih/vim-go/workflows/test/badge.svg)](https://github.com/fatih/vim-go/actions) 2 | 3 | 4 | 5 |

6 | Vim-go logo 7 |

8 | 9 | ## Features 10 | 11 | This plugin adds Go language support for Vim, with the following main features: 12 | 13 | * Compile your package with `:GoBuild`, install it with `:GoInstall` or test it 14 | with `:GoTest`. Run a single test with `:GoTestFunc`). 15 | * Quickly execute your current file(s) with `:GoRun`. 16 | * Improved syntax highlighting and folding. 17 | * Debug programs with integrated [`delve`](https://github.com/go-delve/delve) support with `:GoDebugStart`. 18 | * Completion and many other features support via `gopls`. 19 | * formatting on save keeps the cursor position and undo history. 20 | * Go to symbol/declaration with `:GoDef`. 21 | * Look up documentation with `:GoDoc` or `:GoDocBrowser`. 22 | * Easily import packages via `:GoImport`, remove them via `:GoDrop`. 23 | * Precise type-safe renaming of identifiers with `:GoRename`. 24 | * See which code is covered by tests with `:GoCoverage`. 25 | * Add or remove tags on struct fields with `:GoAddTags` and `:GoRemoveTags`. 26 | * Lint your code with `:GoLint` or `:GoMetaLinter`, run your code through `:GoVet` to catch static errors, or make sure errors are checked with `:GoErrCheck`. 27 | * Advanced source analysis utilizing `gopls`, such as `:GoImplements`, `:GoCallees`, and `:GoReferrers`. 28 | * ... and many more! Please see [doc/vim-go.txt](doc/vim-go.txt) for more information. 29 | * Integration with [`gopls`](https://github.com/golang/tools/blob/master/gopls/README.md). 30 | * The `gopls` instance can be shared with other Vim plugins. 31 | * Vim-go's use of `gopls` can be disabled and alternative tools can be used when desired. 32 | * Integration with [`Tagbar`](https://github.com/preservim/tagbar) via [`gotags`](https://github.com/jstemmer/gotags). 33 | * Integration with [`Ultisnips`](https://github.com/SirVer/ultisnips) and other snippet engines. 34 | 35 | ## Install 36 | 37 | vim-go requires at least Vim 8.2.5072 or Neovim 0.4.0. 38 | 39 | The [**latest stable release**](https://github.com/fatih/vim-go/releases/latest) is the 40 | recommended version to use. If you choose to use the master branch instead, 41 | please do so with caution; it is a _development_ branch. 42 | 43 | 44 | vim-go follows the standard runtime path structure. Below are some helper lines 45 | for popular package managers: 46 | 47 | * [Vim 8 packages](http://vimhelp.appspot.com/repeat.txt.html#packages) 48 | * `git clone https://github.com/fatih/vim-go.git ~/.vim/pack/plugins/start/vim-go` 49 | * [Neovim packages](https://neovim.io/doc/user/repeat.html#packages) 50 | * `git clone https://github.com/fatih/vim-go.git ~/.local/share/nvim/site/pack/plugins/start/vim-go` 51 | * [Pathogen](https://github.com/tpope/vim-pathogen) 52 | * `git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go` 53 | * [vim-plug](https://github.com/junegunn/vim-plug) 54 | * `Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }` 55 | * [Vundle](https://github.com/VundleVim/Vundle.vim) 56 | * `Plugin 'fatih/vim-go'` 57 | 58 | You will also need to install all the necessary binaries. vim-go makes it easy 59 | to install all of them by providing a command, `:GoInstallBinaries`, which will 60 | `go install` all the required binaries. 61 | 62 | Check out the Install section in [the documentation](doc/vim-go.txt) for more 63 | detailed instructions (`:help go-install`). 64 | 65 | ## Usage 66 | 67 | The full documentation can be found at [doc/vim-go.txt](doc/vim-go.txt). You can 68 | display it from within Vim with `:help vim-go`. 69 | 70 | Depending on your installation method, you may have to generate the plugin's 71 | [`help tags`](http://vimhelp.appspot.com/helphelp.txt.html#%3Ahelptags) 72 | manually (e.g. `:helptags ALL`). 73 | 74 | We also have a [tutorial](https://github.com/fatih/vim-go/wiki/Tutorial) in the [official vim-go wiki](https://github.com/fatih/vim-go/wiki). 75 | 76 | ## FAQ and troubleshooting 77 | 78 | The FAQ and troubleshooting tips are in the documentation and can be quickly 79 | accessed using `:help go-troubleshooting`. If you believe you've found a bug or 80 | shortcoming in vim-go that is neither addressed by help nor in [existing 81 | issues](https://github.com/fatih/vim-go/issues), please open an issue with 82 | clear reproduction steps. `:GoReportGitHubIssue` can be used pre-populate a lot 83 | of the information needed when creating a new issue. 84 | 85 | ## Contributing 86 | 87 | All PRs are welcome. If you are planning to contribute a large patch or to 88 | integrate a new tool, please create an issue first to get any upfront questions 89 | or design decisions out of the way first. 90 | 91 | You can run the tests locally by running `make`. It will lint the VimL for you, 92 | lint the documentation, and run the tests against the minimum required version 93 | of Vim, other versions of Vim that may be critical to support, and Neovim. 94 | 95 | ## License 96 | 97 | The BSD 3-Clause License - see [`LICENSE`](LICENSE) for more details 98 | 99 | -------------------------------------------------------------------------------- /scripts/runtest.vim: -------------------------------------------------------------------------------- 1 | " Make sure some options are set to sane defaults and output all messages in 2 | " English. 3 | 4 | " vint: -ProhibitSetNoCompatible 5 | 6 | " don't spam the user when Vim is started in Vi compatibility mode 7 | let s:cpo_save = &cpo 8 | set cpo&vim 9 | 10 | set nocompatible nomore shellslash encoding=utf-8 shortmess+=WIF 11 | lang mess C 12 | 13 | " Initialize variables. 14 | let s:total_started = reltime() 15 | let s:fail = 0 16 | let s:done = 0 17 | let s:logs = [] 18 | let s:gopath = $GOPATH 19 | if !exists('g:test_verbose') 20 | let g:test_verbose = 0 21 | endif 22 | 23 | function! s:logmessages() abort 24 | " Add all messages (usually errors). 25 | redir => s:mess 26 | silent messages 27 | redir END 28 | let s:logs = s:logs + filter(split(s:mess, "\n"), 'v:val !~ "^Messages maintainer"') 29 | silent messages clear 30 | endfunction 31 | 32 | function! s:clearOptions() abort 33 | " clear all the vim-go options 34 | for l:k in keys(g:) 35 | if l:k =~ '^go_' && l:k !~ '^go_loaded_' 36 | call execute(printf('unlet g:%s', l:k)) 37 | endif 38 | endfor 39 | endfunction 40 | 41 | " Source the passed test file. 42 | source % 43 | 44 | " cd into the folder of the test file. 45 | let s:testfile = expand('%:t') 46 | let s:dir = expand('%:p:h') 47 | call go#util#Chdir(s:dir) 48 | 49 | " Export root path to vim-go dir. 50 | let g:vim_go_root = fnamemodify(getcwd(), ':p') 51 | 52 | " Get a list of all Test_ functions for the given file. 53 | redir @q 54 | silent function /^Test_ 55 | redir END 56 | let s:tests = split(substitute(@q, 'function \(\k\+()\)', '\1', 'g')) 57 | 58 | " log any messages already accumulated. 59 | call s:logmessages() 60 | " Iterate over all tests and execute them. 61 | for s:test in sort(s:tests) 62 | " Since we extract the tests from a regexp the "abort" keyword is also in 63 | " the list, which is not a test name :-) 64 | if s:test == 'abort' 65 | continue 66 | endif 67 | 68 | " make sure g:go_echo_command_info is not set so that we don't get 69 | " unexpected messages when commands are executed. 70 | let g:go_echo_command_info = 0 71 | 72 | " make sure gopls doesn't use multi-client mode; there seem to be some racy 73 | " conditions when trying to shutdown the server after each test when 74 | " multi-client mode is used. 75 | let g:go_gopls_options = [] 76 | 77 | let s:started = reltime() 78 | if g:test_verbose is 1 79 | call add(s:logs, printf("=== RUN %s", s:test[:-3])) 80 | endif 81 | try 82 | exe 'call ' . s:test 83 | " sleep to give events a chance to be processed. This is especially 84 | " important for the LSP code to have a chance to run before Vim exits, in 85 | " order to avoid errors trying to write to the gopls channels since Vim 86 | " would otherwise stop gopls before the event handlers were run and result 87 | " in 'stream closed' errors when the events were run _after_ gopls exited. 88 | sleep 50m 89 | catch 90 | call assert_report(printf('at %s: %s', v:throwpoint, v:exception)) 91 | endtry 92 | 93 | let s:elapsed_time = substitute(reltimestr(reltime(s:started)), '^\s*\(.\{-}\)\s*$', '\1', '') 94 | 95 | " Restore GOPATH after each test. 96 | let $GOPATH = s:gopath 97 | " Restore the working directory after each test. 98 | call go#util#Chdir(s:dir) 99 | 100 | try 101 | " exit gopls after each test 102 | call go#lsp#Exit() 103 | catch /^Vim(call):E900: Invalid channel id/ 104 | " do nothing - gopls has stopped 105 | finally 106 | call s:clearOptions() 107 | endtry 108 | 109 | let s:done += 1 110 | 111 | if len(v:errors) > 0 112 | let s:fail += 1 113 | call add(s:logs, printf("--- FAIL %s (%ss)", s:test[:-3], s:elapsed_time)) 114 | call s:logmessages() 115 | call extend(s:logs, map(v:errors, '" ". v:val')) 116 | 117 | " Reset so we can capture failures of the next test. 118 | let v:errors = [] 119 | else 120 | if g:test_verbose is 1 121 | call s:logmessages() 122 | call add(s:logs, printf("--- PASS %s (%ss)", s:test[:-3], s:elapsed_time)) 123 | else 124 | silent messages clear 125 | endif 126 | endif 127 | endfor 128 | 129 | " Create an empty fail to indicate that at least one test failed. 130 | if s:fail > 0 131 | split /tmp/vim-go-test/FAILED 132 | silent write 133 | endif 134 | 135 | let s:total_elapsed_time = substitute(reltimestr(reltime(s:total_started)), '^\s*\(.\{-}\)\s*$', '\1', '') 136 | 137 | " Also store all internal messages from s:logs as well. 138 | silent! split /tmp/vim-go-test/test.tmp 139 | call append(line('$'), s:logs) 140 | call append(line('$'), printf("%s %s %s %ss / %s tests", 141 | \ (s:fail > 0 ? 'FAIL' : 'ok '), 142 | \ s:testfile, 143 | \ repeat(' ', 25 - len(s:testfile)), 144 | \ s:total_elapsed_time, s:done)) 145 | if g:test_verbose is 0 146 | silent :g/^$/d 147 | endif 148 | silent! write 149 | 150 | " Our work here is done. 151 | qall! 152 | 153 | " restore Vi compatibility settings 154 | let &cpo = s:cpo_save 155 | unlet s:cpo_save 156 | 157 | " vim:ts=2:sts=2:sw=2:et 158 | -------------------------------------------------------------------------------- /ftplugin/go/mappings.vim: -------------------------------------------------------------------------------- 1 | " go_jump_to_error defines whether we should pass the bang attribute to the 2 | " command or not. This is only used for mappings, because the user can't pass 3 | " the bang attribute to the plug mappings below. So instead of hardcoding it 4 | " as 0 (no '!' attribute) or 1 (with '!' attribute) we pass the user setting, 5 | " which by default is enabled. For commands the user has the ability to pass 6 | " the '!', such as :GoBuild or :GoBuild! 7 | if !exists("g:go_jump_to_error") 8 | let g:go_jump_to_error = 1 9 | endif 10 | 11 | " Some handy plug mappings 12 | nnoremap (go-run) :call go#cmd#Run(!g:go_jump_to_error) 13 | 14 | if has("nvim") || has("terminal") 15 | nnoremap (go-run-vertical) :call go#cmd#RunTerm(!g:go_jump_to_error, 'vsplit', []) 16 | nnoremap (go-run-split) :call go#cmd#RunTerm(!g:go_jump_to_error, 'split', []) 17 | nnoremap (go-run-tab) :call go#cmd#RunTerm(!g:go_jump_to_error, 'tabe', []) 18 | endif 19 | 20 | nnoremap (go-build) :call go#cmd#Build(!g:go_jump_to_error) 21 | nnoremap (go-generate) :call go#cmd#Generate(!g:go_jump_to_error) 22 | nnoremap (go-install) :call go#cmd#Install(!g:go_jump_to_error) 23 | nnoremap (go-test) :call go#test#Test(!g:go_jump_to_error, 0) 24 | nnoremap (go-test-func) :call go#test#Func(!g:go_jump_to_error) 25 | nnoremap (go-test-compile) :call go#test#Test(!g:go_jump_to_error, 1) 26 | nnoremap (go-test-file) :call go#test#File(!g:go_jump_to_error) 27 | 28 | nnoremap (go-coverage) :call go#coverage#Buffer(!g:go_jump_to_error) 29 | nnoremap (go-coverage-clear) :call go#coverage#Clear() 30 | nnoremap (go-coverage-toggle) :call go#coverage#BufferToggle(!g:go_jump_to_error) 31 | nnoremap (go-coverage-browser) :call go#coverage#Browser(!g:go_jump_to_error) 32 | 33 | nnoremap (go-files) :call go#tool#Files() 34 | nnoremap (go-deps) :call go#tool#Deps() 35 | nnoremap (go-info) :call go#tool#Info(1) 36 | nnoremap (go-import) :call go#import#SwitchImport(1, '', expand(''), '') 37 | nnoremap (go-imports) :call go#fmt#Format(1) 38 | nnoremap (go-fmt) :call go#fmt#Format(0) 39 | 40 | nnoremap (go-implements) :call go#implements#Implements(-1) 41 | nnoremap (go-referrers) :call go#referrers#Referrers(-1) 42 | nnoremap (go-sameids) :call go#sameids#SameIds(1) 43 | nnoremap (go-sameids-toggle) :call go#sameids#ToggleSameIds() 44 | 45 | nnoremap (go-rename) :call go#rename#Rename(!g:go_jump_to_error) 46 | 47 | nnoremap (go-decls) :call go#decls#Decls(0, '') 48 | nnoremap (go-decls-dir) :call go#decls#Decls(1, '') 49 | 50 | nnoremap (go-def) :call go#def#Jump('', 0) 51 | nnoremap (go-def-vertical) :call go#def#Jump("vsplit", 0) 52 | nnoremap (go-def-split) :call go#def#Jump("split", 0) 53 | nnoremap (go-def-tab) :call go#def#Jump("tab", 0) 54 | 55 | nnoremap (go-def-type) :call go#def#Jump('', 1) 56 | nnoremap (go-def-type-vertical) :call go#def#Jump("vsplit", 1) 57 | nnoremap (go-def-type-split) :call go#def#Jump("split", 1) 58 | nnoremap (go-def-type-tab) :call go#def#Jump("tab", 1) 59 | 60 | nnoremap (go-def-pop) :call go#def#StackPop() 61 | nnoremap (go-def-stack) :call go#def#Stack() 62 | nnoremap (go-def-stack-clear) :call go#def#StackClear() 63 | 64 | nnoremap (go-doc) :call go#doc#Open("new", "split") 65 | nnoremap (go-doc-tab) :call go#doc#Open("tabnew", "tabe") 66 | nnoremap (go-doc-vertical) :call go#doc#Open("vnew", "vsplit") 67 | nnoremap (go-doc-split) :call go#doc#Open("new", "split") 68 | nnoremap (go-doc-browser) :call go#doc#OpenBrowser() 69 | 70 | nnoremap (go-metalinter) :call go#lint#Gometa(!g:go_jump_to_error, 0) 71 | nnoremap (go-lint) :call go#lint#Golint(!g:go_jump_to_error) 72 | nnoremap (go-vet) :call go#lint#Vet(!g:go_jump_to_error) 73 | 74 | nnoremap (go-alternate-edit) :call go#alternate#Switch(0, "edit") 75 | nnoremap (go-alternate-vertical) :call go#alternate#Switch(0, "vsplit") 76 | nnoremap (go-alternate-split) :call go#alternate#Switch(0, "split") 77 | 78 | " go-iferr is deprecated, but remains for backward compatibility 79 | nnoremap (go-iferr) :call go#iferr#Generate() 80 | nnoremap (go-if-err) :call go#iferr#Generate() 81 | 82 | nnoremap (go-diagnostics) :call go#lint#Diagnostics(!g:go_jump_to_error) 83 | 84 | nnoremap (go-fill-struct) :call go#fillstruct#FillStruct() 85 | 86 | xnoremap (go-extract) :call go#extract#Extract(0) 87 | 88 | " vim: sw=2 ts=2 et 89 | -------------------------------------------------------------------------------- /autoload/go/impl.vim: -------------------------------------------------------------------------------- 1 | " don't spam the user when Vim is started in Vi compatibility mode 2 | let s:cpo_save = &cpo 3 | set cpo&vim 4 | 5 | function! go#impl#Impl(...) abort 6 | let recv = "" 7 | let iface = "" 8 | let interactive = 0 9 | 10 | let pos = getpos('.') 11 | 12 | if a:0 is 0 13 | " Interactive mode if user didn't pass any arguments. 14 | let recv = s:getReceiver() 15 | let iface = input("vim-go: generating method stubs for interface: ") 16 | redraw! 17 | if empty(iface) 18 | call go#util#EchoError('usage: interface type is not provided') 19 | return 20 | endif 21 | elseif a:0 is 1 22 | " we assume the user only passed the interface type, 23 | " i.e: ':GoImpl io.Writer' 24 | let recv = s:getReceiver() 25 | let iface = a:1 26 | elseif a:0 > 2 27 | " user passed receiver and interface type both, 28 | " i.e: 'GoImpl f *Foo io.Writer' 29 | let recv = join(a:000[:-2], ' ') 30 | let iface = a:000[-1] 31 | else 32 | call go#util#EchoError('usage: GoImpl {receiver} {receiver type} {interface}') 33 | return 34 | endif 35 | 36 | " Make sure we put the generated code *after* the struct. 37 | if getline(".") =~ "struct " 38 | normal! $% 39 | endif 40 | 41 | try 42 | let dirname = fnameescape(expand('%:p:h')) 43 | let [result, err] = go#util#Exec(['impl', '-dir', dirname, recv, iface]) 44 | let result = substitute(result, "\n*$", "", "") 45 | if err 46 | call go#util#EchoError(result) 47 | return 48 | endif 49 | 50 | if result is# '' 51 | return 52 | end 53 | 54 | put ='' 55 | silent put =result 56 | finally 57 | call setpos('.', pos) 58 | endtry 59 | endfunction 60 | 61 | function! s:getReceiver() 62 | let receiveType = expand("") 63 | if receiveType == "type" 64 | normal! w 65 | let receiveType = expand("") 66 | elseif receiveType == "struct" 67 | normal! ge 68 | let receiveType = expand("") 69 | endif 70 | return printf("%s *%s", tolower(receiveType)[0], receiveType) 71 | endfunction 72 | 73 | if exists('*uniq') 74 | function! s:uniq(list) 75 | return uniq(a:list) 76 | endfunction 77 | else 78 | " Note: Believe that the list is sorted 79 | function! s:uniq(list) 80 | let i = len(a:list) - 1 81 | while 0 < i 82 | if a:list[i-1] ==# a:list[i] 83 | call remove(a:list, i) 84 | let i -= 2 85 | else 86 | let i -= 1 87 | endif 88 | endwhile 89 | return a:list 90 | endfunction 91 | endif 92 | 93 | function! s:root_dirs() abort 94 | let dirs = [] 95 | let root = go#util#env("goroot") 96 | if root !=# '' && isdirectory(root) 97 | call add(dirs, root) 98 | endif 99 | 100 | let paths = map(split(go#util#env("gopath"), go#util#PathListSep()), "substitute(v:val, '\\\\', '/', 'g')") 101 | if !empty(filter(paths, 'isdirectory(v:val)')) 102 | call extend(dirs, paths) 103 | endif 104 | 105 | return dirs 106 | endfunction 107 | 108 | function! s:go_packages(dirs, arglead) abort 109 | let pkgs = [] 110 | for dir in a:dirs 111 | " this may expand to multiple lines 112 | let scr_root = expand(dir . '/src/') 113 | for pkg in split(globpath(scr_root, a:arglead.'*'), "\n") 114 | if isdirectory(pkg) 115 | let pkg .= '/' 116 | elseif pkg !~ '\.a$' 117 | continue 118 | endif 119 | 120 | " without this the result can have duplicates in form of 121 | " 'encoding/json' and '/encoding/json/' 122 | let pkg = go#util#StripPathSep(pkg) 123 | 124 | " remove the scr root and keep the package in tact 125 | let pkg = substitute(pkg, scr_root, "", "") 126 | call add(pkgs, pkg) 127 | endfor 128 | endfor 129 | 130 | return pkgs 131 | endfunction 132 | 133 | function! s:interface_list(pkg) abort 134 | let [contents, err] = go#util#Exec(['go', 'doc', a:pkg]) 135 | if err 136 | return [] 137 | endif 138 | 139 | let contents = split(contents, "\n") 140 | call filter(contents, 'v:val =~# ''^type\s\+\h\w*\s\+interface''') 141 | return map(contents, 'a:pkg . "." . matchstr(v:val, ''^type\s\+\zs\h\w*\ze\s\+interface'')') 142 | endfunction 143 | 144 | " Complete package and interface for {interface} 145 | function! go#impl#Complete(arglead, cmdline, cursorpos) abort 146 | let words = split(a:cmdline, '\s\+', 1) 147 | 148 | if words[-1] ==# '' 149 | " if no words are given, just start completing the first package we found 150 | return s:uniq(sort(s:go_packages(s:root_dirs(), a:arglead))) 151 | elseif words[-1] =~# '^\(\h\w.*\.\%(\h\w*\)\=$\)\@!\S*$' 152 | " start matching go packages. It's negate match of the below match 153 | return s:uniq(sort(s:go_packages(s:root_dirs(), a:arglead))) 154 | elseif words[-1] =~# '^\h\w.*\.\%(\h\w*\)\=$' 155 | " match the following, anything that could indicate an interface candidate 156 | " 157 | " io. 158 | " io.Wr 159 | " github.com/fatih/color. 160 | " github.com/fatih/color.U 161 | " github.com/fatih/color.Un 162 | let splitted = split(words[-1], '\.', 1) 163 | let pkg = join(splitted[:-2], '.') 164 | let interface = splitted[-1] 165 | return s:uniq(sort(filter(s:interface_list(pkg), 'v:val =~? words[-1]'))) 166 | else 167 | return [] 168 | endif 169 | endfunction 170 | 171 | " restore Vi compatibility settings 172 | let &cpo = s:cpo_save 173 | unlet s:cpo_save 174 | 175 | " vim: sw=2 ts=2 et 176 | -------------------------------------------------------------------------------- /ftplugin/go.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2013 The Go Authors. All rights reserved. 2 | " Use of this source code is governed by a BSD-style 3 | " license that can be found in the LICENSE file. 4 | " 5 | " go.vim: Vim filetype plugin for Go. 6 | 7 | if exists("b:did_ftplugin") 8 | finish 9 | endif 10 | let b:did_ftplugin = 1 11 | 12 | " don't spam the user when Vim is started in Vi compatibility mode 13 | let s:cpo_save = &cpo 14 | set cpo&vim 15 | 16 | let b:undo_ftplugin = "setl fo< com< cms<" 17 | \ . "| exe 'au! vim-go-buffer * '" 18 | 19 | setlocal formatoptions-=t 20 | 21 | setlocal comments=s1:/*,mb:*,ex:*/,:// 22 | setlocal commentstring=//\ %s 23 | 24 | setlocal noexpandtab 25 | 26 | compiler go 27 | 28 | if go#config#CodeCompletionEnabled() 29 | " Set autocompletion 30 | setlocal omnifunc=go#complete#Complete 31 | endif 32 | 33 | if get(g:, "go_doc_keywordprg_enabled", 1) 34 | " keywordprg doesn't allow to use vim commands, override it 35 | nnoremap K :GoDoc 36 | endif 37 | 38 | if get(g:, "go_def_mapping_enabled", 1) 39 | " these are default Vim mappings, we're overriding them to make them 40 | " useful again for Go source code 41 | nnoremap gd :GoDef 42 | nnoremap gD :GoDefType 43 | nnoremap :GoDef 44 | nnoremap :GoDef 45 | nnoremap g :GoDef 46 | nnoremap :call go#def#Jump("split", 0) 47 | nnoremap ] :call go#def#Jump("split", 0) 48 | if exists('*settagstack') is 0 || has('patch-8.2.0077') is 0 49 | nnoremap :call go#def#StackPop(v:count1) 50 | endif 51 | endif 52 | 53 | if get(g:, "go_textobj_enabled", 1) 54 | onoremap af :call go#textobj#Function('a') 55 | xnoremap af :call go#textobj#Function('a') 56 | 57 | onoremap if :call go#textobj#Function('i') 58 | xnoremap if :call go#textobj#Function('i') 59 | 60 | onoremap ac :call go#textobj#Comment('a') 61 | xnoremap ac :call go#textobj#Comment('a') 62 | 63 | onoremap ic :call go#textobj#Comment('i') 64 | xnoremap ic :call go#textobj#Comment('i') 65 | 66 | " Remap ]] and [[ to jump betweeen functions as they are useless in Go 67 | nnoremap ]] :call go#textobj#FunctionJump('n', 'next') 68 | nnoremap [[ :call go#textobj#FunctionJump('n', 'prev') 69 | 70 | onoremap ]] :call go#textobj#FunctionJump('o', 'next') 71 | onoremap [[ :call go#textobj#FunctionJump('o', 'prev') 72 | 73 | xnoremap ]] :call go#textobj#FunctionJump('v', 'next') 74 | xnoremap [[ :call go#textobj#FunctionJump('v', 'prev') 75 | endif 76 | 77 | " Autocommands 78 | " ============================================================================ 79 | " 80 | augroup vim-go-buffer 81 | autocmd! * 82 | 83 | " The file is registered (textDocument/DidOpen) with gopls in plugin/go.vim 84 | " on the FileType event. 85 | 86 | if go#util#has_job() 87 | autocmd BufWritePost,FileChangedShellPost call go#lsp#DidChange(resolve(expand(':p'))) 88 | autocmd BufDelete call go#lsp#DidClose(resolve(expand(':p'))) 89 | endif 90 | 91 | " send the textDocument/didChange notification when idle. go#lsp#DidChange 92 | " will not send an event if the buffer hasn't changed since the last 93 | " notification. 94 | autocmd CursorHold,CursorHoldI call go#lsp#DidChange(resolve(expand(':p'))) 95 | 96 | autocmd BufEnter,CursorHold call go#auto#update_autocmd() 97 | 98 | " Echo the identifier information when completion is done. Useful to see 99 | " the signature of a function, etc... 100 | if exists('##CompleteDone') 101 | autocmd CompleteDone call go#auto#complete_done() 102 | endif 103 | 104 | autocmd BufWritePre call go#auto#fmt_autosave() 105 | autocmd BufWritePost call go#auto#metalinter_autosave() 106 | 107 | " TODO(bc): autocmd BufWinLeave call go#lsp#DidChange(expand(':p')) 108 | 109 | if !has('textprop') 110 | "TODO(bc): how to clear sameids and diagnostics when a non-go buffer is 111 | " loaded into a window and the previously loaded buffer is still loaded in 112 | " another window? 113 | 114 | " TODO(bc): only clear when the new buffer isn't the old buffer 115 | 116 | " clear SameIds when the buffer is unloaded from its last window so that 117 | " loading another buffer (especially of a different filetype) in the same 118 | " window doesn't highlight the most recently matched identifier's positions. 119 | autocmd BufWinLeave call go#sameids#ClearSameIds() 120 | " clear SameIds when a new buffer is loaded in the window so that the 121 | " previous buffer's highlighting isn't used. 122 | autocmd BufWinEnter call go#sameids#ClearSameIds() 123 | 124 | " clear diagnostics when the buffer is unloaded from its last window so that 125 | " loading another buffer (especially of a different filetype) in the same 126 | " window doesn't highlight the previously loaded buffer's diagnostics. 127 | autocmd BufWinLeave call go#lsp#ClearDiagnosticHighlights() 128 | " clear diagnostics when a new buffer is loaded in the window so that the 129 | " previous buffer's diagnostics aren't used. 130 | "autocmd BufWinEnter call go#lsp#ClearDiagnosticHighlights() 131 | endif 132 | augroup end 133 | 134 | " restore Vi compatibility settings 135 | let &cpo = s:cpo_save 136 | unlet s:cpo_save 137 | 138 | " vim: sw=2 ts=2 et 139 | --------------------------------------------------------------------------------