diff --git a/.gitignore b/.gitignore index 3c856ee..ecd9c13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -workflows \ No newline at end of file +workflows +.DS_Store diff --git a/README.md b/README.md index 01d8f50..3b08e65 100644 --- a/README.md +++ b/README.md @@ -282,7 +282,6 @@ e.g: | GoDebug stop | stop debug session and unmap debug keymap | | GoBreakToggle | | | GoBreakCondition | conditional break | -| GoDbgStop | Stop debug session, same as GoDebug stop | ## Switch between go and test file @@ -359,15 +358,32 @@ GDB style key mapping is used | P | cap P: pause | | p | print, hover value (also in visual mode) | +### Moving from vscode-go debug + +Please check [Vscode Launch configurations](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) +for more info +go.nvim support launch debuger from vscode-go .vscode/launch.json configurations +If launch.json is valid, run `GoDebug` will launch from the launch.json configuration. + +#### Note: + +Please use jsonls/null-ls check your launch.json is valid json file. Following syntax is not supported + +- Trailing comma +- Comment + +Here is a sample [launch.json](https://github.com/ray-x/go.nvim/blob/master/playground/sampleApp/.vscode/launch.json) + ### Commands -| Command | Description | -| -------------- | ------------------------------------------------------------------------------------------- | -| GoDebug | Start debugger, to debug test, run `Debug test`, to add addition args run `Debug arg1 arg2` | -| GoBreakToggle | toggle break point | -| BreakCondition | conditional break point | -| ReplRun | dap repl run_last | -| ReplToggle | dap repl toggle | +| Command | Description | +| -------------- | ----------------------------------------------------------------------------------------------- | +| GoDebug | Start debugger, to debug test, run `GoDebug test`, to add addition args run `GoDebug arg1 arg2` | +| GoDebugConfig | Open launch.json file | +| GoBreakToggle | toggle break point | +| BreakCondition | conditional break point | +| ReplRun | dap repl run_last | +| ReplToggle | dap repl toggle | ### Required DAP plugins diff --git a/doc/go.txt b/doc/go.txt index 9f7d426..9f74ec0 100644 --- a/doc/go.txt +++ b/doc/go.txt @@ -218,7 +218,7 @@ COMMANDS *go-nvim-commands* < :{range}GoRmTag [flags] *:GoRmTags* - Remove struct tags. Will only apply to the fields in + Remove struct tags. Will apply to the fields in {range} if it's given, or applied to all fields in the struct if it's omitted. @@ -234,6 +234,14 @@ COMMANDS *go-nvim-commands* :GoDebug {options} *:GoDebug* Start debuger options: test, restart, nearest, file, stop + If no option provided, will + 1) check launch.json and launch the valid configuration from + launch.json + 2) fallback to GoDebug file + +:GoDebugConfig *:GoDebugConfig* + Open launch.json + :GoBreakToggle *:GoBreakToggle* Debuger breakpoint toggle diff --git a/lua/go.lua b/lua/go.lua index a4e57f2..39a4886 100644 --- a/lua/go.lua +++ b/lua/go.lua @@ -16,28 +16,30 @@ _GO_NVIM_CFG = { verbose = false, log_path = vim.fn.expand("$HOME") .. "/tmp/gonvim.log", lsp_cfg = false, -- false: do nothing - -- true: apply non-default gopls setup defined in go/lsp.lua - -- if lsp_cfg is a table, merge table with with non-default gopls setup in go/lsp.lua, e.g. + -- true: apply non-default gopls setup defined in go/lsp.lua + -- if lsp_cfg is a table, merge table with with non-default gopls setup in go/lsp.lua, e.g. lsp_gofumpt = false, -- true: set default gofmt in gopls format to gofumpt lsp_on_attach = nil, -- nil: use on_attach function defined in go/lsp.lua for gopls, - -- when lsp_cfg is true - -- if lsp_on_attach is a function: use this function as on_attach function for gopls, - -- when lsp_cfg is true + -- when lsp_cfg is true + -- if lsp_on_attach is a function: use this function as on_attach function for gopls, + -- when lsp_cfg is true lsp_codelens = true, lsp_diag_hdlr = true, -- hook lsp diag handler gopls_cmd = nil, --- you can provide gopls path and cmd if it not in PATH, e.g. cmd = { "/home/ray/.local/nvim/data/lspinstall/go/gopls" } gopls_remote_auto = true, gocoverage_sign = "█", gocoverage_sign_priority = 5, + launch_json = nil, -- the launch.json file path, default to .vscode/launch.json dap_debug = true, dap_debug_gui = true, dap_debug_keymap = true, -- true: use keymap for debugger defined in go/dap.lua - -- false: do not use keymap in go/dap.lua. you must define your own. + -- false: do not use keymap in go/dap.lua. you must define your own. dap_vt = true, -- false, true and 'all frames' build_tags = "", --- you can provide extra build tags for tests or debugger textobjects = true, test_runner = "go", -- richgo, go test, richgo, dlv, ginkgo run_in_floaterm = false, -- set to true to run in float window. + launch_json = vim.fn.getcwd() .. "/.vscode/launch.json", } local dap_config = function() @@ -162,9 +164,9 @@ function go.setup(cfg) vim.cmd( [[command! -nargs=* -complete=custom,v:lua.package.loaded.go.dbg_complete GoDebug lua require"go.dap".run()]] ) - vim.cmd([[command! GoBreakToggle lua require"go.dap".breakpt()]]) + vim.cmd([[command! GoDebugConfig lua require"go.launch".config()]]) + vim.cmd([[command! GoBreakToggle lua require"go.dap".breakpt()]]) vim.cmd([[command! BreakCondition lua require"dap".set_breakpoint(vim.fn.input("Breakpoint condition: "))]]) - vim.cmd([[command! ReplRun lua require"dap".repl.run_last()]]) vim.cmd([[command! ReplToggle lua require"dap".repl.toggle()]]) vim.cmd([[command! ReplOpen lua require"dap".repl.open(), 'split']]) diff --git a/lua/go/dap.lua b/lua/go/dap.lua index 239a494..e287284 100644 --- a/lua/go/dap.lua +++ b/lua/go/dap.lua @@ -96,6 +96,7 @@ M.run = function(...) local ctl_opt = select(2, ...) -- testopts = {"test", "nearest", "file", "stop", "restart"} + log("plugin loaded", mode, ctl_opt) if mode == "stop" or ctl_opt == "stop" then return require("go.dap").stop(true) end @@ -111,6 +112,7 @@ M.run = function(...) M.pre_mode = mode end + M.prepare() local session = require("dap").session() if session ~= nil and session.initialized == true then vim.notify("debug session already start, press c to continue", vim.lsp.log_levels.INFO) @@ -118,9 +120,7 @@ M.run = function(...) end keybind() - M.prepare() - log("plugin loaded", mode) if _GO_NVIM_CFG.dap_debug_gui then require("dapui").setup() if not require("dapui.windows").sidebar:is_open() then @@ -182,6 +182,9 @@ M.run = function(...) end end + local launch = require("go.launch") + local cfg_exist, cfg_file = launch.vs_launch() + log(mode, cfg_exist, cfg_file) if mode == "test" then dap_cfg.name = dap_cfg.name .. " test" dap_cfg.mode = "test" @@ -198,6 +201,13 @@ M.run = function(...) log(dap_cfg) dap.configurations.go = { dap_cfg } dap.continue() + elseif cfg_exist then + log("using cfg") + launch.load() + for _, cfg in ipairs(dap.configurations.go) do + cfg.dlvToolPath = vim.fn.exepath('dlv') + end + dap.continue() else dap_cfg.program = sep .. "${relativeFileDirname}" dap_cfg.args = args diff --git a/lua/go/launch.lua b/lua/go/launch.lua new file mode 100644 index 0000000..8c0a1af --- /dev/null +++ b/lua/go/launch.lua @@ -0,0 +1,98 @@ +local launch_json_content = [[ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch main", + "type": "go", + "request": "launch", + "mode": "exec", + "remotePath": "", + "port": 38697, + "host": "127.0.0.1", + "program": "${workspaceFolder}/main.go", + "env": { + }, + "args": [], + "cwd": ${workspaceFolder}", + "envFile", "${workspaceFolder}/.env" + "buildFlags":"" + }, + { + "name": "debug main", + "type": "go", + "request": "launch", + "mode": "debug", + "remotePath": "", + "port": 38697, + "host": "127.0.0.1", + "program": "${workspaceFolder}/main.go", + "env": { + }, + "args": [], + "cwd": ${workspaceFolder}", + "envFile", "${workspaceFolder}/.env" + "buildFlags":"" + }, + { + "name": "debug main", + "type": "go", + "request": "attach", + "mode": "debug", + "remotePath": "", + "port": 38697, + "host": "127.0.0.1", + "program": "${workspaceFolder}/main.go", + "env": { + }, + "args": [], + "cwd": ${workspaceFolder}", + "processId":"", + "envFile", "${workspaceFolder}/.env" + "buildFlags":"" + } + ] +} +]] + +local util = require("go.utils") +local log = util.log +local M = {} + +function M.vs_launch() + local launch_json = _GO_NVIM_CFG.launch_json or (vim.fn.getcwd() .. "/.vscode/launch.json") + log(launch_json) + if vim.fn.filereadable(launch_json) == 1 then + return true, launch_json + else + return false, launch_json + end +end + +function M.config() + local launch_json = _GO_NVIM_CFG.launch_json or (vim.fn.getcwd() .. "/.vscode/launch.json") + + local cmd = "e " .. launch_json + if vim.fn.filereadable(launch_json) == 1 then + return vim.cmd(cmd) + end + + -- vim.fn.writefile(launch_json_content, launch_json) + local contents = vim.fn.split(launch_json_content, "\n") + vim.fn.writefile(contents, launch_json) + vim.cmd(cmd) +end + +function M.load() + if _GO_NVIM_CFG.launch_json_loaded == true then + return + end + + local dap = require("dap") + local launch = require("dap.ext.vscode").load_launchjs + launch(_GO_NVIM_CFG.launch_json) + _GO_NVIM_CFG.launch_json_loaded = true + log(dap.configurations) +end + +return M diff --git a/playground/sampleApp/.vscode/launch.json b/playground/sampleApp/.vscode/launch.json new file mode 100644 index 0000000..4f89ab6 --- /dev/null +++ b/playground/sampleApp/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch main", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/main.go" + }, + { + "name": "Launch test function", + "type": "go", + "request": "launch", + "mode": "test", + "program": "${workspaceFolder}/pkg", + "args": [ + "-test.run", + "FindAllSubStr" + ] + } + ] + } \ No newline at end of file diff --git a/playground/sampleApp/go.mod b/playground/sampleApp/go.mod new file mode 100644 index 0000000..1e7ee25 --- /dev/null +++ b/playground/sampleApp/go.mod @@ -0,0 +1,21 @@ +module sampleApp + +go 1.17 + +require ( + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.7.4 // indirect + github.com/go-playground/locales v0.13.0 // indirect + github.com/go-playground/universal-translator v0.17.0 // indirect + github.com/go-playground/validator/v10 v10.4.1 // indirect + github.com/golang/protobuf v1.3.3 // indirect + github.com/json-iterator/go v1.1.9 // indirect + github.com/leodido/go-urn v1.2.0 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect + github.com/ugorji/go/codec v1.1.7 // indirect + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect +) diff --git a/playground/sampleApp/go.sum b/playground/sampleApp/go.sum new file mode 100644 index 0000000..9ef949a --- /dev/null +++ b/playground/sampleApp/go.sum @@ -0,0 +1,49 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= +github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/playground/sampleApp/main.go b/playground/sampleApp/main.go new file mode 100644 index 0000000..e8affc3 --- /dev/null +++ b/playground/sampleApp/main.go @@ -0,0 +1,11 @@ +package main + +import ( + "fmt" + "sampleApp/pkg" +) + +func main() { + result := pkg.FindAllSubStr("Find niddle in stack", "niddle") + fmt.Println(result) +} diff --git a/playground/sampleApp/pkg/findAllSubStr.go b/playground/sampleApp/pkg/findAllSubStr.go new file mode 100644 index 0000000..3546cc4 --- /dev/null +++ b/playground/sampleApp/pkg/findAllSubStr.go @@ -0,0 +1,17 @@ +package pkg + +import ( + "strings" +) + +func FindAllSubStr(stack, niddle string) (result []int) { + stack = strings.ToLower(stack) + niddle = strings.ToLower(niddle) + for idx := 1; idx >= 0; { + if idx = strings.Index(stack, niddle); idx != -1 { + result = append(result, idx) + stack = stack[idx+1:] + } + } + return result +} diff --git a/playground/sampleApp/pkg/findAllSubStr_test.go b/playground/sampleApp/pkg/findAllSubStr_test.go new file mode 100644 index 0000000..b745651 --- /dev/null +++ b/playground/sampleApp/pkg/findAllSubStr_test.go @@ -0,0 +1,36 @@ +package pkg + +import ( + "reflect" + "testing" +) + +func TestFindAllSubStr(t *testing.T) { + type args struct { + stack string + niddle string + } + tests := []struct { + name string + args args + wantResult []int + }{ + // TODO: Add test cases. + { + name: "test 1 should return 2 idx", + args: args{ + stack: "foobarbafoo", + niddle: "foo", + }, + wantResult: []int{0, 7}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if gotResult := FindAllSubStr(tt.args.stack, tt.args.niddle); !reflect.DeepEqual(gotResult, tt.wantResult) { + t.Errorf("FindAllSubStr() = %v, want %v", gotResult, tt.wantResult) + } + }) + } +}