Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/cmd/gopls: gopls doesn't work #30027

Closed
skanehira opened this issue Jan 31, 2019 · 5 comments
Closed

x/tools/cmd/gopls: gopls doesn't work #30027

skanehira opened this issue Jan 31, 2019 · 5 comments
Milestone

Comments

@skanehira
Copy link
Contributor

@skanehira skanehira commented Jan 31, 2019

What version of Go are you using (go version)?

$ go version
go version go1.11.5 darwin/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN="/Users/skanehira/dev/go/bin"
GOCACHE="/Users/skanehira/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/skanehira/dev/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.11.5/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.11.5/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/yy/krfkwtjx48xb0m25vb5ncth40000gn/T/go-build711822326=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

  1. Using vim-lsp and gopls on vim to run LspDefinition
  2. At first it successed but the next not work.

What did you expect to see?

What did you see instead?

gopls log Output
[Trace - 9:46:13 AM] Sending request 'initialize - (1)'.
Params: {"rootUri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui","initializationOptions":{},"capabilities":{"workspace":{"applyEdit ":true}},"rootPath":"/Users/skanehira/dev/go/src/github.com/skanehira/docui","trace":"off"}

[Trace - 9:46:13 AM] Received response 'initialize - (1)' in 0ms.
Params: {"capabilities":{"textDocumentSync":{"openClose":true,"change":1,"save":{}},"hoverProvider":true,"completionProvider":{"triggerCharacters":["."]},"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"codeActionProvider":true,"codeLensProvider":{},"documentFormattingProvider":true,"documentRangeFormattingProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"documentLinkProvider":{},"executeCommandProvider":{"commands":null},"workspace":{"workspaceFolders":{}}}}

[Trace - 9:46:13 AM] Sending notification 'textDocument/didOpen'.
Params: {"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","version":1,"languageId":"go","text":"package main\n\nimport (\n\t"os"\n\n\t"github.com/skanehira/docui/panel"\n\n\t"github.com/jroimartin/gocui"\n)\n\nfunc main() {\n\tfor {\n\t\tgui := panel.New(gocui.Output256)\n\t\tgui.Logger.Info("docui start")\n\t\terr := gui.MainLoop()\n\n\t\tswitch err {\n\t\tcase gocui.ErrQuit:\n\t\t\tgui.Logger.Info("docui finished")\n\t\t\tgui.Close()\n\t\t\tos.Exit(0)\n\t\tcase panel.ExecFlag:\n\t\t\tgui.Gui.Close()\n\t\t\tgui.Panels[panel.ContainerListPanel].(*panel.ContainerList).Exec()\n\t\t}\n\t}\n}"}}

[Trace - 9:46:13 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","diagnostics":[]}

[Trace - 9:46:18 AM] Sending request 'textDocument/definition - (2)'.
Params: {"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go"},"position":{"character":13,"line":14}}

[Trace - 9:46:18 AM] Received response 'textDocument/definition - (2)' in 0ms.
Params: [{"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/gui.go","range":{"start":{"line":350,"character":14},"end":{"line":350,"character":22}}}]

[Trace - 9:46:18 AM] Sending notification 'textDocument/didOpen'.
Params: {"textDocument":{"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui%40v0.4.0/gui.go","version":1,"languageId":"go","text":"// Copyright 2014 The gocui Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gocui\n\nimport (\n\t"errors"\n\n\t"github.com/nsf/termbox-go"\n)\n\nvar (\n\t// ErrQuit is used to decide if the MainLoop finished successfully.\n\tErrQuit = errors.New("quit")\n\n\t// ErrUnknownView allows to assert if a View must be initialized.\n\tErrUnknownView = errors.New("unknown view")\n)\n\n// OutputMode represents the terminal's output mode (8 or 256 colors).\ntype OutputMode termbox.OutputMode\n\nconst (\n\t// OutputNormal provides 8-colors terminal mode.\n\tOutputNormal = OutputMode(termbox.OutputNormal)\n\n\t// Output256 provides 256-colors terminal mode.\n\tOutput256 = OutputMode(termbox.Output256)\n)\n\n// Gui represents the whole User Interface, including the views, layouts\n// and keybindings.\ntype Gui struct {\n\ttbEvents chan termbox.Event\n\tuserEvents chan userEvent\n\tviews []*View\n\tcurrentView *View\n\tmanagers []Manager\n\tkeybindings []*keybinding\n\tmaxX, maxY int\n\toutputMode OutputMode\n\n\t// BgColor and FgColor allow to configure the background and foreground\n\t// colors of the GUI.\n\tBgColor, FgColor Attribute\n\n\t// SelBgColor and SelFgColor allow to configure the background and\n\t// foreground colors of the frame of the current view.\n\tSelBgColor, SelFgColor Attribute\n\n\t// If Highlight is true, Sel{Bg,Fg}Colors will be used to draw the\n\t// frame of the current view.\n\tHighlight bool\n\n\t// If Cursor is true then the cursor is enabled.\n\tCursor bool\n\n\t// If Mouse is true then mouse events will be enabled.\n\tMouse bool\n\n\t// If InputEsc is true, when ESC sequence is in the buffer and it doesn't\n\t// match any known sequence, ESC means KeyEsc.\n\tInputEsc bool\n\n\t// If ASCII is true then use ASCII instead of unicode to draw the\n\t// interface. Using ASCII is more portable.\n\tASCII bool\n}\n\n// NewGui returns a new Gui object with a given output mode.\nfunc NewGui(mode OutputMode) (*Gui, error) {\n\tif err := termbox.Init(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tg := &Gui{}\n\n\tg.outputMode = mode\n\ttermbox.SetOutputMode(termbox.OutputMode(mode))\n\n\tg.tbEvents = make(chan termbox.Event, 20)\n\tg.userEvents = make(chan userEvent, 20)\n\n\tg.maxX, g.maxY = termbox.Size()\n\n\tg.BgColor, g.FgColor = ColorDefault, ColorDefault\n\tg.SelBgColor, g.SelFgColor = ColorDefault, ColorDefault\n\n\treturn g, nil\n}\n\n// Close finalizes the library. It should be called after a successful\n// initialization and when gocui is not needed anymore.\nfunc (g *Gui) Close() {\n\ttermbox.Close()\n}\n\n// Size returns the terminal's size.\nfunc (g *Gui) Size() (x, y int) {\n\treturn g.maxX, g.maxY\n}\n\n// SetRune writes a rune at the given point, relative to the top-left\n// corner of the terminal. It checks if the position is valid and applies\n// the given colors.\nfunc (g *Gui) SetRune(x, y int, ch rune, fgColor, bgColor Attribute) error {\n\tif x < 0 || y < 0 || x >= g.maxX || y >= g.maxY {\n\t\treturn errors.New("invalid point")\n\t}\n\ttermbox.SetCell(x, y, ch, termbox.Attribute(fgColor), termbox.Attribute(bgColor))\n\treturn nil\n}\n\n// Rune returns the rune contained in the cell at the given position.\n// It checks if the position is valid.\nfunc (g Gui) Rune(x, y int) (rune, error) {\n\tif x < 0 || y < 0 || x >= g.maxX || y >= g.maxY {\n\t\treturn ' ', errors.New("invalid point")\n\t}\n\tc := termbox.CellBuffer()[yg.maxX+x]\n\treturn c.Ch, nil\n}\n\n// SetView creates a new view with its top-left corner at (x0, y0)\n// and the bottom-right one at (x1, y1). If a view with the same name\n// already exists, its dimensions are updated; otherwise, the error\n// ErrUnknownView is returned, which allows to assert if the View must\n// be initialized. It checks if the position is valid.\nfunc (g *Gui) SetView(name string, x0, y0, x1, y1 int) (*View, error) {\n\tif x0 >= x1 || y0 >= y1 {\n\t\treturn nil, errors.New("invalid dimensions")\n\t}\n\tif name == "" {\n\t\treturn nil, errors.New("invalid name")\n\t}\n\n\tif v, err := g.View(name); err == nil {\n\t\tv.x0 = x0\n\t\tv.y0 = y0\n\t\tv.x1 = x1\n\t\tv.y1 = y1\n\t\tv.tainted = true\n\t\treturn v, nil\n\t}\n\n\tv := newView(name, x0, y0, x1, y1, g.outputMode)\n\tv.BgColor, v.FgColor = g.BgColor, g.FgColor\n\tv.SelBgColor, v.SelFgColor = g.SelBgColor, g.SelFgColor\n\tg.views = append(g.views, v)\n\treturn v, ErrUnknownView\n}\n\n// SetViewOnTop sets the given view on top of the existing ones.\nfunc (g *Gui) SetViewOnTop(name string) (*View, error) {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\ts := append(g.views[:i], g.views[i+1:]...)\n\t\t\tg.views = append(s, v)\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// SetViewOnBottom sets the given view on bottom of the existing ones.\nfunc (g *Gui) SetViewOnBottom(name string) (*View, error) {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\ts := append(g.views[:i], g.views[i+1:]...)\n\t\t\tg.views = append([]*View{v}, s...)\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// Views returns all the views in the GUI.\nfunc (g *Gui) Views() []*View {\n\treturn g.views\n}\n\n// View returns a pointer to the view with the given name, or error\n// ErrUnknownView if a view with that name does not exist.\nfunc (g *Gui) View(name string) (*View, error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// ViewByPosition returns a pointer to a view matching the given position, or\n// error ErrUnknownView if a view in that position does not exist.\nfunc (g *Gui) ViewByPosition(x, y int) (*View, error) {\n\t// traverse views in reverse order checking top views first\n\tfor i := len(g.views); i > 0; i-- {\n\t\tv := g.views[i-1]\n\t\tif x > v.x0 && x < v.x1 && y > v.y0 && y < v.y1 {\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// ViewPosition returns the coordinates of the view with the given name, or\n// error ErrUnknownView if a view with that name does not exist.\nfunc (g *Gui) ViewPosition(name string) (x0, y0, x1, y1 int, err error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\treturn v.x0, v.y0, v.x1, v.y1, nil\n\t\t}\n\t}\n\treturn 0, 0, 0, 0, ErrUnknownView\n}\n\n// DeleteView deletes a view by name.\nfunc (g *Gui) DeleteView(name string) error {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\tg.views = append(g.views[:i], g.views[i+1:]...)\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn ErrUnknownView\n}\n\n// SetCurrentView gives the focus to a given view.\nfunc (g *Gui) SetCurrentView(name string) (*View, error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\tg.currentView = v\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// CurrentView returns the currently focused view, or nil if no view\n// owns the focus.\nfunc (g *Gui) CurrentView() *View {\n\treturn g.currentView\n}\n\n// SetKeybinding creates a new keybinding. If viewname equals to ""\n// (empty string) then the keybinding will apply to all views. key must\n// be a rune or a Key.\nfunc (g *Gui) SetKeybinding(viewname string, key interface{}, mod Modifier, handler func(*Gui, *View) error) error {\n\tvar kb *keybinding\n\n\tk, ch, err := getKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\tkb = newKeybinding(viewname, k, ch, mod, handler)\n\tg.keybindings = append(g.keybindings, kb)\n\treturn nil\n}\n\n// DeleteKeybinding deletes a keybinding.\nfunc (g *Gui) DeleteKeybinding(viewname string, key interface{}, mod Modifier) error {\n\tk, ch, err := getKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor i, kb := range g.keybindings {\n\t\tif kb.viewName == viewname && kb.ch == ch && kb.key == k && kb.mod == mod {\n\t\t\tg.keybindings = append(g.keybindings[:i], g.keybindings[i+1:]...)\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn errors.New("keybinding not found")\n}\n\n// DeleteKeybindings deletes all keybindings of view.\nfunc (g *Gui) DeleteKeybindings(viewname string) {\n\tvar s []*keybinding\n\tfor _, kb := range g.keybindings {\n\t\tif kb.viewName != viewname {\n\t\t\ts = append(s, kb)\n\t\t}\n\t}\n\tg.keybindings = s\n}\n\n// getKey takes an empty interface with a key and returns the corresponding\n// typed Key or rune.\nfunc getKey(key interface{}) (Key, rune, error) {\n\tswitch t := key.(type) {\n\tcase Key:\n\t\treturn t, 0, nil\n\tcase rune:\n\t\treturn 0, t, nil\n\tdefault:\n\t\treturn 0, 0, errors.New("unknown type")\n\t}\n}\n\n// userEvent represents an event triggered by the user.\ntype userEvent struct {\n\tf func(*Gui) error\n}\n\n// Update executes the passed function. This method can be called safely from a\n// goroutine in order to update the GUI. It is important to note that the\n// passed function won't be executed immediately, instead it will be added to\n// the user events queue. Given that Update spawns a goroutine, the order in\n// which the user events will be handled is not guaranteed.\nfunc (g *Gui) Update(f func(*Gui) error) {\n\tgo func() { g.userEvents <- userEvent{f: f} }()\n}\n\n// A Manager is in charge of GUI's layout and can be used to build widgets.\ntype Manager interface {\n\t// Layout is called every time the GUI is redrawn, it must contain the\n\t// base views and its initializations.\n\tLayout(*Gui) error\n}\n\n// The ManagerFunc type is an adapter to allow the use of ordinary functions as\n// Managers. If f is a function with the appropriate signature, ManagerFunc(f)\n// is an Manager object that calls f.\ntype ManagerFunc func(*Gui) error\n\n// Layout calls f(g)\nfunc (f ManagerFunc) Layout(g *Gui) error {\n\treturn f(g)\n}\n\n// SetManager sets the given GUI managers. It deletes all views and\n// keybindings.\nfunc (g *Gui) SetManager(managers ...Manager) {\n\tg.managers = managers\n\tg.currentView = nil\n\tg.views = nil\n\tg.keybindings = nil\n\n\tgo func() { g.tbEvents <- termbox.Event{Type: termbox.EventResize} }()\n}\n\n// SetManagerFunc sets the given manager function. It deletes all views and\n// keybindings.\nfunc (g Gui) SetManagerFunc(manager func(...

vim-lsp log Output
木  1/31 09:46:13 2019:["lsp#register_server","server registered","gopls"]
木  1/31 09:46:13 2019:["lsp#register_server","server registered","php-language-server"]
木  1/31 09:46:13 2019:["lsp#register_server","server registered","flow-language-server"]
木  1/31 09:46:13 2019:["lsp#register_server","server registered","docker-langserver"]
木  1/31 09:46:13 2019:["lsp#register_server","server registered","css-languageserver"]
木  1/31 09:46:13 2019:["s:on_text_document_did_open()",1,"go","/Users/skanehira/dev/go/src/github.com/skanehira/docui","file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go"]
木  1/31 09:46:13 2019:[{"response":{"data":{"__data__":"vim-lsp","lsp_id":1,"server_name":"gopls"},"message":"started lsp server successfully"}}]
木  1/31 09:46:13 2019:["--->",1,"gopls",{"method":"initialize","params":{"rootUri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui","initializationOptions":{},"capabilities":{"workspace":{"applyEdit ":true}},"rootPath":"/Users/skanehira/dev/go/src/github.com/skanehira/docui","trace":"off"}}]
木  1/31 09:46:13 2019:["<---",1,"gopls",{"response":{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"codeLensProvider":{},"executeCommandProvider":{"commands":null},"workspace":{"workspaceFolders":{}},"hoverProvider":true,"documentLinkProvider":{},"typeDefinitionProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"codeActionProvider":true,"documentFormattingProvider":true,"definitionProvider":true,"textDocumentSync":{"save":{},"change":1,"openClose":true},"documentRangeFormattingProvider":true,"completionProvider":{"triggerCharacters":["."]}}}},"request":{"method":"initialize","jsonrpc":"2.0","id":1,"params":{"rootUri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui","initializationOptions":{},"capabilities":{"workspace":{"applyEdit ":true}},"rootPath":"/Users/skanehira/dev/go/src/github.com/skanehira/docui","trace":"off"}}}]
木  1/31 09:46:13 2019:[{"response":{"data":{"__data__":"vim-lsp","server_name":"gopls"},"message":"configuration sent"}}]
木  1/31 09:46:13 2019:["--->",1,"gopls",{"method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","version":1,"languageId":"go","text":"package main\n\nimport (\n\t\"os\"\n\n\t\"github.com/skanehira/docui/panel\"\n\n\t\"github.com/jroimartin/gocui\"\n)\n\nfunc main() {\n\tfor {\n\t\tgui := panel.New(gocui.Output256)\n\t\tgui.Logger.Info(\"docui start\")\n\t\terr := gui.MainLoop()\n\n\t\tswitch err {\n\t\tcase gocui.ErrQuit:\n\t\t\tgui.Logger.Info(\"docui finished\")\n\t\t\tgui.Close()\n\t\t\tos.Exit(0)\n\t\tcase panel.ExecFlag:\n\t\t\tgui.Gui.Close()\n\t\t\tgui.Panels[panel.ContainerListPanel].(*panel.ContainerList).Exec()\n\t\t}\n\t}\n}"}}}]
木  1/31 09:46:13 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","__data__":"vim-lsp","filetype":"go","server_name":"gopls"},"message":"textDocument/open sent"}}]
木  1/31 09:46:13 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","__data__":"vim-lsp","server_name":"gopls"},"message":"not dirty"}}]
木  1/31 09:46:13 2019:["<---",1,"gopls",{"response":{"method":"textDocument/publishDiagnostics","jsonrpc":"2.0","params":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","diagnostics":[]}}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"__data__":"vim-lsp","server_name":"gopls"},"message":"server already started"}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"__data__":"vim-lsp","init_result":{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"codeLensProvider":{},"executeCommandProvider":{"commands":null},"workspace":{"workspaceFolders":{}},"hoverProvider":true,"documentLinkProvider":{},"typeDefinitionProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"codeActionProvider":true,"documentFormattingProvider":true,"definitionProvider":true,"textDocumentSync":{"save":{},"change":1,"openClose":true},"documentRangeFormattingProvider":true,"completionProvider":{"triggerCharacters":["."]}}}},"server_name":"gopls"},"message":"lsp server already initialized"}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"__data__":"vim-lsp","server_name":"gopls"},"message":"configuration sent"}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","__data__":"vim-lsp","server_name":"gopls"},"message":"already opened"}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","__data__":"vim-lsp","server_name":"gopls"},"message":"not dirty"}}]
木  1/31 09:46:18 2019:["--->",1,"gopls",{"method":"textDocument/definition","on_notification":"---funcref---","params":{"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go"},"position":{"character":13,"line":14}}}]
木  1/31 09:46:18 2019:["<---",1,"gopls",{"response":{"id":2,"jsonrpc":"2.0","result":[{"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/gui.go","range":{"end":{"character":22,"line":350},"start":{"character":14,"line":350}}}]},"request":{"method":"textDocument/definition","jsonrpc":"2.0","id":2,"params":{"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go"},"position":{"character":13,"line":14}}}}]
木  1/31 09:46:18 2019:["s:on_text_document_did_close()",1]
木  1/31 09:46:18 2019:["s:on_text_document_did_open()",2,"go","/Users/skanehira/dev/go/src/github.com/skanehira/docui","file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui%40v0.4.0/gui.go"]
木  1/31 09:46:18 2019:[{"response":{"data":{"__data__":"vim-lsp","server_name":"gopls"},"message":"server already started"}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"__data__":"vim-lsp","init_result":{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"codeLensProvider":{},"executeCommandProvider":{"commands":null},"workspace":{"workspaceFolders":{}},"hoverProvider":true,"documentLinkProvider":{},"typeDefinitionProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"codeActionProvider":true,"documentFormattingProvider":true,"definitionProvider":true,"textDocumentSync":{"save":{},"change":1,"openClose":true},"documentRangeFormattingProvider":true,"completionProvider":{"triggerCharacters":["."]}}}},"server_name":"gopls"},"message":"lsp server already initialized"}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"__data__":"vim-lsp","server_name":"gopls"},"message":"configuration sent"}}]
木  1/31 09:46:18 2019:["--->",1,"gopls",{"method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui%40v0.4.0/gui.go","version":1,"languageId":"go","text":"// Copyright 2014 The gocui Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gocui\n\nimport (\n\t\"errors\"\n\n\t\"github.com/nsf/termbox-go\"\n)\n\nvar (\n\t// ErrQuit is used to decide if the MainLoop finished successfully.\n\tErrQuit = errors.New(\"quit\")\n\n\t// ErrUnknownView allows to assert if a View must be initialized.\n\tErrUnknownView = errors.New(\"unknown view\")\n)\n\n// OutputMode represents the terminal's output mode (8 or 256 colors).\ntype OutputMode termbox.OutputMode\n\nconst (\n\t// OutputNormal provides 8-colors terminal mode.\n\tOutputNormal = OutputMode(termbox.OutputNormal)\n\n\t// Output256 provides 256-colors terminal mode.\n\tOutput256 = OutputMode(termbox.Output256)\n)\n\n// Gui represents the whole User Interface, including the views, layouts\n// and keybindings.\ntype Gui struct {\n\ttbEvents    chan termbox.Event\n\tuserEvents  chan userEvent\n\tviews       []*View\n\tcurrentView *View\n\tmanagers    []Manager\n\tkeybindings []*keybinding\n\tmaxX, maxY  int\n\toutputMode  OutputMode\n\n\t// BgColor and FgColor allow to configure the background and foreground\n\t// colors of the GUI.\n\tBgColor, FgColor Attribute\n\n\t// SelBgColor and SelFgColor allow to configure the background and\n\t// foreground colors of the frame of the current view.\n\tSelBgColor, SelFgColor Attribute\n\n\t// If Highlight is true, Sel{Bg,Fg}Colors will be used to draw the\n\t// frame of the current view.\n\tHighlight bool\n\n\t// If Cursor is true then the cursor is enabled.\n\tCursor bool\n\n\t// If Mouse is true then mouse events will be enabled.\n\tMouse bool\n\n\t// If InputEsc is true, when ESC sequence is in the buffer and it doesn't\n\t// match any known sequence, ESC means KeyEsc.\n\tInputEsc bool\n\n\t// If ASCII is true then use ASCII instead of unicode to draw the\n\t// interface. Using ASCII is more portable.\n\tASCII bool\n}\n\n// NewGui returns a new Gui object with a given output mode.\nfunc NewGui(mode OutputMode) (*Gui, error) {\n\tif err := termbox.Init(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tg := &Gui{}\n\n\tg.outputMode = mode\n\ttermbox.SetOutputMode(termbox.OutputMode(mode))\n\n\tg.tbEvents = make(chan termbox.Event, 20)\n\tg.userEvents = make(chan userEvent, 20)\n\n\tg.maxX, g.maxY = termbox.Size()\n\n\tg.BgColor, g.FgColor = ColorDefault, ColorDefault\n\tg.SelBgColor, g.SelFgColor = ColorDefault, ColorDefault\n\n\treturn g, nil\n}\n\n// Close finalizes the library. It should be called after a successful\n// initialization and when gocui is not needed anymore.\nfunc (g *Gui) Close() {\n\ttermbox.Close()\n}\n\n// Size returns the terminal's size.\nfunc (g *Gui) Size() (x, y int) {\n\treturn g.maxX, g.maxY\n}\n\n// SetRune writes a rune at the given point, relative to the top-left\n// corner of the terminal. It checks if the position is valid and applies\n// the given colors.\nfunc (g *Gui) SetRune(x, y int, ch rune, fgColor, bgColor Attribute) error {\n\tif x < 0 || y < 0 || x >= g.maxX || y >= g.maxY {\n\t\treturn errors.New(\"invalid point\")\n\t}\n\ttermbox.SetCell(x, y, ch, termbox.Attribute(fgColor), termbox.Attribute(bgColor))\n\treturn nil\n}\n\n// Rune returns the rune contained in the cell at the given position.\n// It checks if the position is valid.\nfunc (g *Gui) Rune(x, y int) (rune, error) {\n\tif x < 0 || y < 0 || x >= g.maxX || y >= g.maxY {\n\t\treturn ' ', errors.New(\"invalid point\")\n\t}\n\tc := termbox.CellBuffer()[y*g.maxX+x]\n\treturn c.Ch, nil\n}\n\n// SetView creates a new view with its top-left corner at (x0, y0)\n// and the bottom-right one at (x1, y1). If a view with the same name\n// already exists, its dimensions are updated; otherwise, the error\n// ErrUnknownView is returned, which allows to assert if the View must\n// be initialized. It checks if the position is valid.\nfunc (g *Gui) SetView(name string, x0, y0, x1, y1 int) (*View, error) {\n\tif x0 >= x1 || y0 >= y1 {\n\t\treturn nil, errors.New(\"invalid dimensions\")\n\t}\n\tif name == \"\" {\n\t\treturn nil, errors.New(\"invalid name\")\n\t}\n\n\tif v, err := g.View(name); err == nil {\n\t\tv.x0 = x0\n\t\tv.y0 = y0\n\t\tv.x1 = x1\n\t\tv.y1 = y1\n\t\tv.tainted = true\n\t\treturn v, nil\n\t}\n\n\tv := newView(name, x0, y0, x1, y1, g.outputMode)\n\tv.BgColor, v.FgColor = g.BgColor, g.FgColor\n\tv.SelBgColor, v.SelFgColor = g.SelBgColor, g.SelFgColor\n\tg.views = append(g.views, v)\n\treturn v, ErrUnknownView\n}\n\n// SetViewOnTop sets the given view on top of the existing ones.\nfunc (g *Gui) SetViewOnTop(name string) (*View, error) {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\ts := append(g.views[:i], g.views[i+1:]...)\n\t\t\tg.views = append(s, v)\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// SetViewOnBottom sets the given view on bottom of the existing ones.\nfunc (g *Gui) SetViewOnBottom(name string) (*View, error) {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\ts := append(g.views[:i], g.views[i+1:]...)\n\t\t\tg.views = append([]*View{v}, s...)\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// Views returns all the views in the GUI.\nfunc (g *Gui) Views() []*View {\n\treturn g.views\n}\n\n// View returns a pointer to the view with the given name, or error\n// ErrUnknownView if a view with that name does not exist.\nfunc (g *Gui) View(name string) (*View, error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// ViewByPosition returns a pointer to a view matching the given position, or\n// error ErrUnknownView if a view in that position does not exist.\nfunc (g *Gui) ViewByPosition(x, y int) (*View, error) {\n\t// traverse views in reverse order checking top views first\n\tfor i := len(g.views); i > 0; i-- {\n\t\tv := g.views[i-1]\n\t\tif x > v.x0 && x < v.x1 && y > v.y0 && y < v.y1 {\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// ViewPosition returns the coordinates of the view with the given name, or\n// error ErrUnknownView if a view with that name does not exist.\nfunc (g *Gui) ViewPosition(name string) (x0, y0, x1, y1 int, err error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\treturn v.x0, v.y0, v.x1, v.y1, nil\n\t\t}\n\t}\n\treturn 0, 0, 0, 0, ErrUnknownView\n}\n\n// DeleteView deletes a view by name.\nfunc (g *Gui) DeleteView(name string) error {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\tg.views = append(g.views[:i], g.views[i+1:]...)\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn ErrUnknownView\n}\n\n// SetCurrentView gives the focus to a given view.\nfunc (g *Gui) SetCurrentView(name string) (*View, error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\tg.currentView = v\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// CurrentView returns the currently focused view, or nil if no view\n// owns the focus.\nfunc (g *Gui) CurrentView() *View {\n\treturn g.currentView\n}\n\n// SetKeybinding creates a new keybinding. If viewname equals to \"\"\n// (empty string) then the keybinding will apply to all views. key must\n// be a rune or a Key.\nfunc (g *Gui) SetKeybinding(viewname string, key interface{}, mod Modifier, handler func(*Gui, *View) error) error {\n\tvar kb *keybinding\n\n\tk, ch, err := getKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\tkb = newKeybinding(viewname, k, ch, mod, handler)\n\tg.keybindings = append(g.keybindings, kb)\n\treturn nil\n}\n\n// DeleteKeybinding deletes a keybinding.\nfunc (g *Gui) DeleteKeybinding(viewname string, key interface{}, mod Modifier) error {\n\tk, ch, err := getKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor i, kb := range g.keybindings {\n\t\tif kb.viewName == viewname && kb.ch == ch && kb.key == k && kb.mod == mod {\n\t\t\tg.keybindings = append(g.keybindings[:i], g.keybindings[i+1:]...)\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn errors.New(\"keybinding not found\")\n}\n\n// DeleteKeybindings deletes all keybindings of view.\nfunc (g *Gui) DeleteKeybindings(viewname string) {\n\tvar s []*keybinding\n\tfor _, kb := range g.keybindings {\n\t\tif kb.viewName != viewname {\n\t\t\ts = append(s, kb)\n\t\t}\n\t}\n\tg.keybindings = s\n}\n\n// getKey takes an empty interface with a key and returns the corresponding\n// typed Key or rune.\nfunc getKey(key interface{}) (Key, rune, error) {\n\tswitch t := key.(type) {\n\tcase Key:\n\t\treturn t, 0, nil\n\tcase rune:\n\t\treturn 0, t, nil\n\tdefault:\n\t\treturn 0, 0, errors.New(\"unknown type\")\n\t}\n}\n\n// userEvent represents an event triggered by the user.\ntype userEvent struct {\n\tf func(*Gui) error\n}\n\n// Update executes the passed function. This method can be called safely from a\n// goroutine in order to update the GUI. It is important to note that the\n// passed function won't be executed immediately, instead it will be added to\n// the user events queue. Given that Update spawns a goroutine, the order in\n// which the user events will be handled is not guaranteed.\nfunc (g *Gui) Update(f func(*Gui) error) {\n\tgo func() { g.userEvents <- userEvent{f: f} }()\n}\n\n// A Manager is in charge of GUI's layout and can be used to build widgets.\ntype Manager interface {\n\t// Layout is called every time the GUI is redrawn, it must contain the\n\t// base views and its initializations.\n\tLayout(*Gui) error\n}\n\n// The ManagerFunc type is an adapter to allow the use of ordinary functions as\n// Managers. If f is a function with the appropriate signature, ManagerFunc(f)\n// is an Manager object that calls f.\ntype ManagerFunc func(*Gui) error\n\n// Layout calls f(g)\nfunc (f ManagerFunc) Layout(g *Gui) error {\n\treturn f(g)\n}\n\n// SetManager sets the given GUI managers. It deletes all views and\n// keybindings.\nfunc (g *Gui) SetManager(managers ...Manager) {\n\tg.managers = managers\n\tg.currentView = nil\n\tg.views = nil\n\tg.keybindings = nil\n\n\tgo func() { g.tbEvents <- termbox.Event{Type: termbox.EventResize} }()\n}\n\n// SetManagerFunc sets the given manager function. It deletes all views and\n// keybindings.\nfunc (g *Gui) SetManagerFunc(manager func(*Gui) error) {\n\tg.SetManager(ManagerFunc(manager))\n}\n\n// MainLoop runs the main loop until an error is returned. A successful\n// finish should return ErrQuit.\nfunc (g *Gui) MainLoop() error {\n\tgo func() {\n\t\tfor {\n\t\t\tg.tbEvents <- termbox.PollEvent()\n\t\t}\n\t}()\n\n\tinputMode := termbox.InputAlt\n\tif g.InputEsc {\n\t\tinputMode = termbox.InputEsc\n\t}\n\tif g.Mouse {\n\t\tinputMode |= termbox.InputMouse\n\t}\n\ttermbox.SetInputMode(inputMode)\n\n\tif err := g.flush(); err != nil {\n\t\treturn err\n\t}\n\tfor {\n\t\tselect {\n\t\tcase ev := <-g.tbEvents:\n\t\t\tif err := g.handleEvent(&ev); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase ev := <-g.userEvents:\n\t\t\tif err := ev.f(g); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif err := g.consumeevents(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := g.flush(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n}\n\n// consumeevents handles the remaining events in the events pool.\nfunc (g *Gui) consumeevents() error {\n\tfor {\n\t\tselect {\n\t\tcase ev := <-g.tbEvents:\n\t\t\tif err := g.handleEvent(&ev); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase ev := <-g.userEvents:\n\t\t\tif err := ev.f(g); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t}\n}\n\n// handleEvent handles an event, based on its type (key-press, error,\n// etc.)\nfunc (g *Gui) handleEvent(ev *termbox.Event) error {\n\tswitch ev.Type {\n\tcase termbox.EventKey, termbox.EventMouse:\n\t\treturn g.onKey(ev)\n\tcase termbox.EventError:\n\t\treturn ev.Err\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// flush updates the gui, re-drawing frames and buffers.\nfunc (g *Gui) flush() error {\n\ttermbox.Clear(termbox.Attribute(g.FgColor), termbox.Attribute(g.BgColor))\n\n\tmaxX, maxY := termbox.Size()\n\t// if GUI's size has changed, we need to redraw all views\n\tif maxX != g.maxX || maxY != g.maxY {\n\t\tfor _, v := range g.views {\n\t\t\tv.tainted = true\n\t\t}\n\t}\n\tg.maxX, g.maxY = maxX, maxY\n\n\tfor _, m := range g.managers {\n\t\tif err := m.Layout(g); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tfor _, v := range g.views {\n\t\tif v.Frame {\n\t\t\tvar fgColor, bgColor Attribute\n\t\t\tif g.Highlight && v == g.currentView {\n\t\t\t\tfgColor = g.SelFgColor\n\t\t\t\tbgColor = g.SelBgColor\n\t\t\t} else {\n\t\t\t\tfgColor = g.FgColor\n\t\t\t\tbgColor = g.BgColor\n\t\t\t}\n\n\t\t\tif err := g.drawFrameEdges(v, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err := g.drawFrameCorners(v, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif v.Title != \"\" {\n\t\t\t\tif err := g.drawTitle(v, fgColor, bgColor); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif err := g.draw(v); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\ttermbox.Flush()\n\treturn nil\n}\n\n// drawFrameEdges draws the horizontal and vertical edges of a view.\nfunc (g *Gui) drawFrameEdges(v *View, fgColor, bgColor Attribute) error {\n\truneH, runeV := '─', '│'\n\tif g.ASCII {\n\t\truneH, runeV = '-', '|'\n\t}\n\n\tfor x := v.x0 + 1; x < v.x1 && x < g.maxX; x++ {\n\t\tif x < 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif v.y0 > -1 && v.y0 < g.maxY {\n\t\t\tif err := g.SetRune(x, v.y0, runeH, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif v.y1 > -1 && v.y1 < g.maxY {\n\t\t\tif err := g.SetRune(x, v.y1, runeH, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tfor y := v.y0 + 1; y < v.y1 && y < g.maxY; y++ {\n\t\tif y < 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif v.x0 > -1 && v.x0 < g.maxX {\n\t\t\tif err := g.SetRune(v.x0, y, runeV, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif v.x1 > -1 && v.x1 < g.maxX {\n\t\t\tif err := g.SetRune(v.x1, y, runeV, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// drawFrameCorners draws the corners of the view.\nfunc (g *Gui) drawFrameCorners(v *View, fgColor, bgColor Attribute) error {\n\truneTL, runeTR, runeBL, runeBR := '┌', '┐', '└', '┘'\n\tif g.ASCII {\n\t\truneTL, runeTR, runeBL, runeBR = '+', '+', '+', '+'\n\t}\n\n\tcorners := []struct {\n\t\tx, y int\n\t\tch   rune\n\t}{{v.x0, v.y0, runeTL}, {v.x1, v.y0, runeTR}, {v.x0, v.y1, runeBL}, {v.x1, v.y1, runeBR}}\n\n\tfor _, c := range corners {\n\t\tif c.x >= 0 && c.y >= 0 && c.x < g.maxX && c.y < g.maxY {\n\t\t\tif err := g.SetRune(c.x, c.y, c.ch, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// drawTitle draws the title of the view.\nfunc (g *Gui) drawTitle(v *View, fgColor, bgColor Attribute) error {\n\tif v.y0 < 0 || v.y0 >= g.maxY {\n\t\treturn nil\n\t}\n\n\tfor i, ch := range v.Title {\n\t\tx := v.x0 + i + 2\n\t\tif x < 0 {\n\t\t\tcontinue\n\t\t} else if x > v.x1-2 || x >= g.maxX {\n\t\t\tbreak\n\t\t}\n\t\tif err := g.SetRune(x, v.y0, ch, fgColor, bgColor); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// draw manages the cursor and calls the draw function of a view.\nfunc (g *Gui) draw(v *View) error {\n\tif g.Cursor {\n\t\tif curview := g.currentView; curview != nil {\n\t\t\tvMaxX, vMaxY := curview.Size()\n\t\t\tif curview.cx < 0 {\n\t\t\t\tcurview.cx = 0\n\t\t\t} else if curview.cx >= vMaxX {\n\t\t\t\tcurview.cx = vMaxX - 1\n\t\t\t}\n\t\t\tif curview.cy < 0 {\n\t\t\t\tcurview.cy = 0\n\t\t\t} else if curview.cy >= vMaxY {\n\t\t\t\tcurview.cy = vMaxY - 1\n\t\t\t}\n\n\t\t\tgMaxX, gMaxY := g.Size()\n\t\t\tcx, cy := curview.x0+curview.cx+1, curview.y0+curview.cy+1\n\t\t\tif cx >= 0 && cx < gMaxX && cy >= 0 && cy < gMaxY {\n\t\t\t\ttermbox.SetCursor(cx, cy)\n\t\t\t} else {\n\t\t\t\ttermbox.HideCursor()\n\t\t\t}\n\t\t}\n\t} else {\n\t\ttermbox.HideCursor()\n\t}\n\n\tv.clearRunes()\n\tif err := v.draw(); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// onKey manages key-press events. A keybinding handler is called when\n// a key-press or mouse event satisfies a configured keybinding. Furthermore,\n// currentView's internal buffer is modified if currentView.Editable is true.\nfunc (g *Gui) onKey(ev *termbox.Event) error {\n\tswitch ev.Type {\n\tcase termbox.EventKey:\n\t\tmatched, err := g.execKeybindings(g.currentView, ev)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif matched {\n\t\t\tbreak\n\t\t}\n\t\tif g.currentView != nil && g.currentView.Editable && g.currentView.Editor != nil {\n\t\t\tg.currentView.Editor.Edit(g.currentView, Key(ev.Key), ev.Ch, Modifier(ev.Mod))\n\t\t}\n\tcase termbox.EventMouse:\n\t\tmx, my := ev.MouseX, ev.MouseY\n\t\tv, err := g.ViewByPosition(mx, my)\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t\tif err := v.SetCursor(mx-v.x0-1, my-v.y0-1); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif _, err := g.execKeybindings(v, ev); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// execKeybindings executes the keybinding handlers that match the passed view\n// and event. The value of matched is true if there is a match and no errors.\nfunc (g *Gui) execKeybindings(v *View, ev *termbox.Event) (matched bool, err error) {\n\tmatched = false\n\tfor _, kb := range g.keybindings {\n\t\tif kb.handler == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif kb.matchKeypress(Key(ev.Key), ev.Ch, Modifier(ev.Mod)) && kb.matchView(v) {\n\t\t\tif err := kb.handler(g, v); err != nil {\n\t\t\t\treturn false, err\n\t\t\t}\n\t\t\tmatched = true\n\t\t}\n\t}\n\treturn matched, nil\n}"}}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui%40v0.4.0/gui.go","__data__":"vim-lsp","filetype":"go","server_name":"gopls"},"message":"textDocument/open sent"}}]
木  1/31 09:46:18 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui%40v0.4.0/gui.go","__data__":"vim-lsp","server_name":"gopls"},"message":"not dirty"}}]
木  1/31 09:46:18 2019:["<---(stderr)",1,"gopls",["panic: runtime error: invalid memory address or nil pointer dereference","[signal SIGSEGV: segmentation violation code=0x1 addr=0x48 pc=0x12bd3e0]","","goroutine 1919 [running]:","golang.org/x/tools/internal/lsp/source.Diagnostics(0x145c720, 0xc0000180d0, 0x145bb20, 0xc0001a8000, 0xc005df6de0, 0x52, 0xc000205e60, 0x0, 0x0)","\t/Users/skanehira/dev/go/pkg/mod/golang.org/x/tools@v0.0.0-20190130015043-a06a922acc1b/internal/lsp/source/diagnostics.go:34 +0xe0"]]
木  1/31 09:46:18 2019:["<---(stderr)",1,"gopls",["","golang.org/x/tools/internal/lsp.(*server).cacheAndDiagnose.func1(0x145c720, 0xc0000180d0, 0xc0000ee600, 0xc005df6de0, 0x52)","\t/Users/skanehira/dev/go/pkg/mod/golang.org/x/tools@v0.0.0-20190130015043-a06a922acc1b/internal/lsp/diagnostics.go:21 +0x81","created by golang.org/x/tools/internal/lsp.(*server).cacheAndDiagnose","\t/Users/skanehira/dev/go/pkg/mod/golang.org/x/tools@v0.0.0-20190130015043-a06a922acc1b/internal/lsp/diagnostics.go:20 +0xfe",""]]
木  1/31 09:46:18 2019:["s:on_exit",1,"gopls","exited",2]
木  1/31 09:46:19 2019:["s:on_text_document_did_close()",2]
木  1/31 09:46:19 2019:["s:on_text_document_did_open()",1,"go","/Users/skanehira/dev/go/src/github.com/skanehira/docui","file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go"]
木  1/31 09:46:19 2019:[{"response":{"data":{"__data__":"vim-lsp","lsp_id":2,"server_name":"gopls"},"message":"started lsp server successfully"}}]
木  1/31 09:46:19 2019:["--->",2,"gopls",{"method":"initialize","params":{"rootUri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui","initializationOptions":{},"capabilities":{"workspace":{"applyEdit ":true}},"rootPath":"/Users/skanehira/dev/go/src/github.com/skanehira/docui","trace":"off"}}]
木  1/31 09:46:19 2019:["<---",2,"gopls",{"response":{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"codeLensProvider":{},"executeCommandProvider":{"commands":null},"workspace":{"workspaceFolders":{}},"hoverProvider":true,"documentLinkProvider":{},"typeDefinitionProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"codeActionProvider":true,"documentFormattingProvider":true,"definitionProvider":true,"textDocumentSync":{"save":{},"change":1,"openClose":true},"documentRangeFormattingProvider":true,"completionProvider":{"triggerCharacters":["."]}}}},"request":{"method":"initialize","jsonrpc":"2.0","id":1,"params":{"rootUri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui","initializationOptions":{},"capabilities":{"workspace":{"applyEdit ":true}},"rootPath":"/Users/skanehira/dev/go/src/github.com/skanehira/docui","trace":"off"}}}]
木  1/31 09:46:19 2019:[{"response":{"data":{"__data__":"vim-lsp","server_name":"gopls"},"message":"configuration sent"}}]
木  1/31 09:46:19 2019:["--->",2,"gopls",{"method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","version":1,"languageId":"go","text":"package main\n\nimport (\n\t\"os\"\n\n\t\"github.com/skanehira/docui/panel\"\n\n\t\"github.com/jroimartin/gocui\"\n)\n\nfunc main() {\n\tfor {\n\t\tgui := panel.New(gocui.Output256)\n\t\tgui.Logger.Info(\"docui start\")\n\t\terr := gui.MainLoop()\n\n\t\tswitch err {\n\t\tcase gocui.ErrQuit:\n\t\t\tgui.Logger.Info(\"docui finished\")\n\t\t\tgui.Close()\n\t\t\tos.Exit(0)\n\t\tcase panel.ExecFlag:\n\t\t\tgui.Gui.Close()\n\t\t\tgui.Panels[panel.ContainerListPanel].(*panel.ContainerList).Exec()\n\t\t}\n\t}\n}"}}}]
木  1/31 09:46:19 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","__data__":"vim-lsp","filetype":"go","server_name":"gopls"},"message":"textDocument/open sent"}}]
木  1/31 09:46:19 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","__data__":"vim-lsp","server_name":"gopls"},"message":"not dirty"}}]
木  1/31 09:46:19 2019:["<---",2,"gopls",{"response":{"method":"textDocument/publishDiagnostics","jsonrpc":"2.0","params":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","diagnostics":[]}}}]
木  1/31 09:46:20 2019:[{"response":{"data":{"__data__":"vim-lsp","server_name":"gopls"},"message":"server already started"}}]
木  1/31 09:46:20 2019:[{"response":{"data":{"__data__":"vim-lsp","init_result":{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"codeLensProvider":{},"executeCommandProvider":{"commands":null},"workspace":{"workspaceFolders":{}},"hoverProvider":true,"documentLinkProvider":{},"typeDefinitionProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"codeActionProvider":true,"documentFormattingProvider":true,"definitionProvider":true,"textDocumentSync":{"save":{},"change":1,"openClose":true},"documentRangeFormattingProvider":true,"completionProvider":{"triggerCharacters":["."]}}}},"server_name":"gopls"},"message":"lsp server already initialized"}}]
木  1/31 09:46:20 2019:[{"response":{"data":{"__data__":"vim-lsp","server_name":"gopls"},"message":"configuration sent"}}]
木  1/31 09:46:20 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","__data__":"vim-lsp","server_name":"gopls"},"message":"already opened"}}]
木  1/31 09:46:20 2019:[{"response":{"data":{"path":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","__data__":"vim-lsp","server_name":"gopls"},"message":"not dirty"}}]
木  1/31 09:46:20 2019:["--->",2,"gopls",{"method":"textDocument/definition","on_notification":"---funcref---","params":{"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go"},"position":{"character":13,"line":17}}}]
木  1/31 09:46:20 2019:["<---",2,"gopls",{"response":{"id":2,"jsonrpc":"2.0","error":{"data":null,"code":0,"message":"invalid position for error"}},"request":{"method":"textDocument/definition","jsonrpc":"2.0","id":2,"params":{"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go"},"position":{"character":13,"line":17}}}}]
@mattn
Copy link
Member

@mattn mattn commented Jan 31, 2019

This is part of stacktrace.

[
  "panic: runtime error: invalid memory address or nil pointer dereference",
  "[signal SIGSEGV: segmentation violation code=0x1 addr=0x48 pc=0x12bd3e0]",
  "",
  "goroutine 1919 [running]:",
  "golang.org/x/tools/internal/lsp/source.Diagnostics(0x145c720, 0xc0000180d0, 0x145bb20, 0xc0001a8000, 0xc005df6de0, 0x52, 0xc000205e60, 0x0, 0x0)",
  "\t/Users/skanehira/dev/go/pkg/mod/golang.org/x/tools@v0.0.0-20190130015043-a06a922acc1b/internal/lsp/source/diagnostics.go:34 +0xe0"
]

[
  "",
  "golang.org/x/tools/internal/lsp.(*server).cacheAndDiagnose.func1(0x145c720, 0xc0000180d0, 0xc0000ee600, 0xc005df6de0, 0x52)",
  "\t/Users/skanehira/dev/go/pkg/mod/golang.org/x/tools@v0.0.0-20190130015043-a06a922acc1b/internal/lsp/diagnostics.go:21 +0x81",
  "created by golang.org/x/tools/internal/lsp.(*server).cacheAndDiagnose",
  "\t/Users/skanehira/dev/go/pkg/mod/golang.org/x/tools@v0.0.0-20190130015043-a06a922acc1b/internal/lsp/diagnostics.go:20 +0xfe",
  ""
]

https://github.com/golang/tools/blob/bb1329dc71a0cb59ec60f5bce4e5e087516677c0/internal/lsp/source/diagnostics.go#L34

pkg might be nil.

@pwaller
Copy link
Contributor

@pwaller pwaller commented Jan 31, 2019

/cc @stamblerre I think this is the same bug I reported on slack. Here are the salient details reproduced below.

v.getFile("file:///home/pwaller/.local/pkg/mod/golang.org/x/tools@v0.0.0-20181127232545-e782529d0ddd/go/packages/packages.go")
Message: failed to find or parse file:///home/pwaller/.local/pkg/mod/golang.org/x/tools%40v0.0.0-20181127232545-e782529d0ddd/go/packages/packages.go
  1. sourceURI := fromProtocolURI(uri) happens early in the request, this URI contains %40 rather than @ https://github.com/golang/tools/blob/a06a922acc1b97001c51689385e2144227c9e820/internal/lsp/diagnostics.go#L16
  2. view.GetFile() is called with a %40
  3. packages.Load is called with %40 https://github.com/golang/tools/blob/a06a922acc1b97001c51689385e2144227c9e820/internal/lsp/cache/view.go#L100
  4. fToken.Name() and fURI both contain @: https://github.com/golang/tools/blob/a06a922acc1b97001c51689385e2144227c9e820/internal/lsp/cache/view.go#L117
  5. resulting in the cache being keyed on a filename containing @
  6. pkg, err = nil, nil results in a nil dereference of pkg https://github.com/golang/tools/blob/a06a922acc1b97001c51689385e2144227c9e820/internal/lsp/source/diagnostics.go#L28

So it looks like an issue with path escaping. My surprise comes that surely this must be an issue for anyone using modules, since modules result in source files which have @ in the path. This lead me to believe I must be doing something wrong, but it's good to see I'm not the only one hitting it :)

@bradfitz bradfitz changed the title gopls doesn't work x/tools/cmd/gopls: gopls doesn't work Jan 31, 2019
@gopherbot gopherbot added this to the Unreleased milestone Jan 31, 2019
@gopherbot
Copy link

@gopherbot gopherbot commented Feb 4, 2019

Change https://golang.org/cl/161077 mentions this issue: internal/lsp: handle escaping URIs for files in the module cache

gopherbot pushed a commit to golang/tools that referenced this issue Feb 5, 2019
This change makes sure to handle escaped characters, for instance, files
in the module cache contain "@" in the path. Also, return errors when a
package is not found for a file.

Updates golang/go#30027

Change-Id: I6c4f6d0f30dde55701308b89785f02b671e81cc6
Reviewed-on: https://go-review.googlesource.com/c/161077
Reviewed-by: Ian Cottrell <iancottrell@google.com>
Reviewed-by: Yasuhiro MATSUMOTO <mattn.jp@gmail.com>
@stamblerre
Copy link
Contributor

@stamblerre stamblerre commented Feb 5, 2019

This case should be fixed now - @skanehira, can you confirm?

@skanehira
Copy link
Contributor Author

@skanehira skanehira commented Feb 6, 2019

@stamblerre
I confirmed the latest gopls and it worked!
Thank you fixed this.

gopls log Output
[Trace - 9:45:55 AM] Sending request 'initialize - (1)'.
Params: {"rootUri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui","initializationOptions":{},"capabilities":{"workspace":{"applyEdit ":true}},"rootPath":"/Users/skanehira/dev/go/src/github.com/skanehira/docui","trace":"off"}

[Trace - 9:45:55 AM] Received response 'initialize - (1)' in 1ms.
Params: {"capabilities":{"textDocumentSync":{"openClose":true,"change":1,"save":{}},"hoverProvider":true,"completionProvider":{"triggerCharacters":["."]},"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"codeActionProvider":true,"codeLensProvider":{},"documentFormattingProvider":true,"documentRangeFormattingProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"documentLinkProvider":{},"executeCommandProvider":{"commands":null},"workspace":{"workspaceFolders":{}}}}

[Trace - 9:45:55 AM] Sending notification 'textDocument/didOpen'.
Params: {"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","version":1,"languageId":"go","text":"package main\n\nimport (\n\t"flag"\n\t"log"\n\t"os"\n\n\t"github.com/jroimartin/gocui"\n\t"github.com/skanehira/docui/docker"\n\t"github.com/skanehira/docui/panel"\n)\n\nfunc main() {\n\tvar (\n\t\tendpoint = flag.String("endpoint", "unix:///var/run/docker.sock", "Docker endpoint")\n\t\tcert = flag.String("cert", "", "cert.pem file path")\n\t\tkey = flag.String("key", "", "key.pem file path")\n\t\tca = flag.String("ca", "", "ca.pem file path")\n\t)\n\tflag.Parse()\n\n\tconfig := docker.NewClientConfig(*endpoint, *cert, *key, *ca)\n\tdockerClient := docker.NewDocker(config)\n\n\t// when docker client cannot connect engine exit\n\tif err := dockerClient.Ping(); err != nil {\n\t\tlog.Println(err)\n\t\treturn\n\t}\n\n\tfor {\n\t\tgui := panel.New(gocui.Output256, dockerClient)\n\t\tgui.Logger.Info("docui start")\n\t\terr := gui.MainLoop()\n\n\t\tswitch err {\n\t\tcase gocui.ErrQuit:\n\t\t\tgui.Logger.Info("docui finished")\n\t\t\tgui.Close()\n\t\t\tos.Exit(0)\n\t\tcase panel.ExecFlag:\n\t\t\tgui.Gui.Close()\n\t\t\tgui.Panels[panel.ContainerListPanel].(*panel.ContainerList).Exec()\n\t\t}\n\t}\n}"}}

[Trace - 9:45:56 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go","diagnostics":[]}

[Trace - 9:46:00 AM] Sending request 'textDocument/definition - (2)'.
Params: {"textDocument":{"uri":"file:///Users/skanehira/dev/go/src/github.com/skanehira/docui/main.go"},"position":{"character":18,"line":33}}

[Trace - 9:46:00 AM] Received response 'textDocument/definition - (2)' in 0ms.
Params: [{"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/gui.go","range":{"start":{"line":350,"character":14},"end":{"line":350,"character":22}}}]

[Trace - 9:46:00 AM] Sending notification 'textDocument/didOpen'.
Params: {"textDocument":{"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui%40v0.4.0/gui.go","version":1,"languageId":"go","text":"// Copyright 2014 The gocui Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gocui\n\nimport (\n\t"errors"\n\n\t"github.com/nsf/termbox-go"\n)\n\nvar (\n\t// ErrQuit is used to decide if the MainLoop finished successfully.\n\tErrQuit = errors.New("quit")\n\n\t// ErrUnknownView allows to assert if a View must be initialized.\n\tErrUnknownView = errors.New("unknown view")\n)\n\n// OutputMode represents the terminal's output mode (8 or 256 colors).\ntype OutputMode termbox.OutputMode\n\nconst (\n\t// OutputNormal provides 8-colors terminal mode.\n\tOutputNormal = OutputMode(termbox.OutputNormal)\n\n\t// Output256 provides 256-colors terminal mode.\n\tOutput256 = OutputMode(termbox.Output256)\n)\n\n// Gui represents the whole User Interface, including the views, layouts\n// and keybindings.\ntype Gui struct {\n\ttbEvents chan termbox.Event\n\tuserEvents chan userEvent\n\tviews []*View\n\tcurrentView *View\n\tmanagers []Manager\n\tkeybindings []*keybinding\n\tmaxX, maxY int\n\toutputMode OutputMode\n\n\t// BgColor and FgColor allow to configure the background and foreground\n\t// colors of the GUI.\n\tBgColor, FgColor Attribute\n\n\t// SelBgColor and SelFgColor allow to configure the background and\n\t// foreground colors of the frame of the current view.\n\tSelBgColor, SelFgColor Attribute\n\n\t// If Highlight is true, Sel{Bg,Fg}Colors will be used to draw the\n\t// frame of the current view.\n\tHighlight bool\n\n\t// If Cursor is true then the cursor is enabled.\n\tCursor bool\n\n\t// If Mouse is true then mouse events will be enabled.\n\tMouse bool\n\n\t// If InputEsc is true, when ESC sequence is in the buffer and it doesn't\n\t// match any known sequence, ESC means KeyEsc.\n\tInputEsc bool\n\n\t// If ASCII is true then use ASCII instead of unicode to draw the\n\t// interface. Using ASCII is more portable.\n\tASCII bool\n}\n\n// NewGui returns a new Gui object with a given output mode.\nfunc NewGui(mode OutputMode) (*Gui, error) {\n\tif err := termbox.Init(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tg := &Gui{}\n\n\tg.outputMode = mode\n\ttermbox.SetOutputMode(termbox.OutputMode(mode))\n\n\tg.tbEvents = make(chan termbox.Event, 20)\n\tg.userEvents = make(chan userEvent, 20)\n\n\tg.maxX, g.maxY = termbox.Size()\n\n\tg.BgColor, g.FgColor = ColorDefault, ColorDefault\n\tg.SelBgColor, g.SelFgColor = ColorDefault, ColorDefault\n\n\treturn g, nil\n}\n\n// Close finalizes the library. It should be called after a successful\n// initialization and when gocui is not needed anymore.\nfunc (g *Gui) Close() {\n\ttermbox.Close()\n}\n\n// Size returns the terminal's size.\nfunc (g *Gui) Size() (x, y int) {\n\treturn g.maxX, g.maxY\n}\n\n// SetRune writes a rune at the given point, relative to the top-left\n// corner of the terminal. It checks if the position is valid and applies\n// the given colors.\nfunc (g *Gui) SetRune(x, y int, ch rune, fgColor, bgColor Attribute) error {\n\tif x < 0 || y < 0 || x >= g.maxX || y >= g.maxY {\n\t\treturn errors.New("invalid point")\n\t}\n\ttermbox.SetCell(x, y, ch, termbox.Attribute(fgColor), termbox.Attribute(bgColor))\n\treturn nil\n}\n\n// Rune returns the rune contained in the cell at the given position.\n// It checks if the position is valid.\nfunc (g Gui) Rune(x, y int) (rune, error) {\n\tif x < 0 || y < 0 || x >= g.maxX || y >= g.maxY {\n\t\treturn ' ', errors.New("invalid point")\n\t}\n\tc := termbox.CellBuffer()[yg.maxX+x]\n\treturn c.Ch, nil\n}\n\n// SetView creates a new view with its top-left corner at (x0, y0)\n// and the bottom-right one at (x1, y1). If a view with the same name\n// already exists, its dimensions are updated; otherwise, the error\n// ErrUnknownView is returned, which allows to assert if the View must\n// be initialized. It checks if the position is valid.\nfunc (g *Gui) SetView(name string, x0, y0, x1, y1 int) (*View, error) {\n\tif x0 >= x1 || y0 >= y1 {\n\t\treturn nil, errors.New("invalid dimensions")\n\t}\n\tif name == "" {\n\t\treturn nil, errors.New("invalid name")\n\t}\n\n\tif v, err := g.View(name); err == nil {\n\t\tv.x0 = x0\n\t\tv.y0 = y0\n\t\tv.x1 = x1\n\t\tv.y1 = y1\n\t\tv.tainted = true\n\t\treturn v, nil\n\t}\n\n\tv := newView(name, x0, y0, x1, y1, g.outputMode)\n\tv.BgColor, v.FgColor = g.BgColor, g.FgColor\n\tv.SelBgColor, v.SelFgColor = g.SelBgColor, g.SelFgColor\n\tg.views = append(g.views, v)\n\treturn v, ErrUnknownView\n}\n\n// SetViewOnTop sets the given view on top of the existing ones.\nfunc (g *Gui) SetViewOnTop(name string) (*View, error) {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\ts := append(g.views[:i], g.views[i+1:]...)\n\t\t\tg.views = append(s, v)\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// SetViewOnBottom sets the given view on bottom of the existing ones.\nfunc (g *Gui) SetViewOnBottom(name string) (*View, error) {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\ts := append(g.views[:i], g.views[i+1:]...)\n\t\t\tg.views = append([]*View{v}, s...)\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// Views returns all the views in the GUI.\nfunc (g *Gui) Views() []*View {\n\treturn g.views\n}\n\n// View returns a pointer to the view with the given name, or error\n// ErrUnknownView if a view with that name does not exist.\nfunc (g *Gui) View(name string) (*View, error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// ViewByPosition returns a pointer to a view matching the given position, or\n// error ErrUnknownView if a view in that position does not exist.\nfunc (g *Gui) ViewByPosition(x, y int) (*View, error) {\n\t// traverse views in reverse order checking top views first\n\tfor i := len(g.views); i > 0; i-- {\n\t\tv := g.views[i-1]\n\t\tif x > v.x0 && x < v.x1 && y > v.y0 && y < v.y1 {\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// ViewPosition returns the coordinates of the view with the given name, or\n// error ErrUnknownView if a view with that name does not exist.\nfunc (g *Gui) ViewPosition(name string) (x0, y0, x1, y1 int, err error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\treturn v.x0, v.y0, v.x1, v.y1, nil\n\t\t}\n\t}\n\treturn 0, 0, 0, 0, ErrUnknownView\n}\n\n// DeleteView deletes a view by name.\nfunc (g *Gui) DeleteView(name string) error {\n\tfor i, v := range g.views {\n\t\tif v.name == name {\n\t\t\tg.views = append(g.views[:i], g.views[i+1:]...)\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn ErrUnknownView\n}\n\n// SetCurrentView gives the focus to a given view.\nfunc (g *Gui) SetCurrentView(name string) (*View, error) {\n\tfor _, v := range g.views {\n\t\tif v.name == name {\n\t\t\tg.currentView = v\n\t\t\treturn v, nil\n\t\t}\n\t}\n\treturn nil, ErrUnknownView\n}\n\n// CurrentView returns the currently focused view, or nil if no view\n// owns the focus.\nfunc (g *Gui) CurrentView() *View {\n\treturn g.currentView\n}\n\n// SetKeybinding creates a new keybinding. If viewname equals to ""\n// (empty string) then the keybinding will apply to all views. key must\n// be a rune or a Key.\nfunc (g *Gui) SetKeybinding(viewname string, key interface{}, mod Modifier, handler func(*Gui, *View) error) error {\n\tvar kb *keybinding\n\n\tk, ch, err := getKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\tkb = newKeybinding(viewname, k, ch, mod, handler)\n\tg.keybindings = append(g.keybindings, kb)\n\treturn nil\n}\n\n// DeleteKeybinding deletes a keybinding.\nfunc (g *Gui) DeleteKeybinding(viewname string, key interface{}, mod Modifier) error {\n\tk, ch, err := getKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor i, kb := range g.keybindings {\n\t\tif kb.viewName == viewname && kb.ch == ch && kb.key == k && kb.mod == mod {\n\t\t\tg.keybindings = append(g.keybindings[:i], g.keybindings[i+1:]...)\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn errors.New("keybinding not found")\n}\n\n// DeleteKeybindings deletes all keybindings of view.\nfunc (g *Gui) DeleteKeybindings(viewname string) {\n\tvar s []*keybinding\n\tfor _, kb := range g.keybindings {\n\t\tif kb.viewName != viewname {\n\t\t\ts = append(s, kb)\n\t\t}\n\t}\n\tg.keybindings = s\n}\n\n// getKey takes an empty interface with a key and returns the corresponding\n// typed Key or rune.\nfunc getKey(key interface{}) (Key, rune, error) {\n\tswitch t := key.(type) {\n\tcase Key:\n\t\treturn t, 0, nil\n\tcase rune:\n\t\treturn 0, t, nil\n\tdefault:\n\t\treturn 0, 0, errors.New("unknown type")\n\t}\n}\n\n// userEvent represents an event triggered by the user.\ntype userEvent struct {\n\tf func(*Gui) error\n}\n\n// Update executes the passed function. This method can be called safely from a\n// goroutine in order to update the GUI. It is important to note that the\n// passed function won't be executed immediately, instead it will be added to\n// the user events queue. Given that Update spawns a goroutine, the order in\n// which the user events will be handled is not guaranteed.\nfunc (g *Gui) Update(f func(*Gui) error) {\n\tgo func() { g.userEvents <- userEvent{f: f} }()\n}\n\n// A Manager is in charge of GUI's layout and can be used to build widgets.\ntype Manager interface {\n\t// Layout is called every time the GUI is redrawn, it must contain the\n\t// base views and its initializations.\n\tLayout(*Gui) error\n}\n\n// The ManagerFunc type is an adapter to allow the use of ordinary functions as\n// Managers. If f is a function with the appropriate signature, ManagerFunc(f)\n// is an Manager object that calls f.\ntype ManagerFunc func(*Gui) error\n\n// Layout calls f(g)\nfunc (f ManagerFunc) Layout(g *Gui) error {\n\treturn f(g)\n}\n\n// SetManager sets the given GUI managers. It deletes all views and\n// keybindings.\nfunc (g *Gui) SetManager(managers ...Manager) {\n\tg.managers = managers\n\tg.currentView = nil\n\tg.views = nil\n\tg.keybindings = nil\n\n\tgo func() { g.tbEvents <- termbox.Event{Type: termbox.EventResize} }()\n}\n\n// SetManagerFunc sets the given manager function. It deletes all views and\n// keybindings.\nfunc (g *Gui) SetManagerFunc(manager func(*Gui) error) {\n\tg.SetManager(ManagerFunc(manager))\n}\n\n// MainLoop runs the main loop until an error is returned. A successful\n// finish should return ErrQuit.\nfunc (g *Gui) MainLoop() error {\n\tgo func() {\n\t\tfor {\n\t\t\tg.tbEvents <- termbox.PollEvent()\n\t\t}\n\t}()\n\n\tinputMode := termbox.InputAlt\n\tif g.InputEsc {\n\t\tinputMode = termbox.InputEsc\n\t}\n\tif g.Mouse {\n\t\tinputMode |= termbox.InputMouse\n\t}\n\ttermbox.SetInputMode(inputMode)\n\n\tif err := g.flush(); err != nil {\n\t\treturn err\n\t}\n\tfor {\n\t\tselect {\n\t\tcase ev := <-g.tbEvents:\n\t\t\tif err := g.handleEvent(&ev); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase ev := <-g.userEvents:\n\t\t\tif err := ev.f(g); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif err := g.consumeevents(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := g.flush(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n}\n\n// consumeevents handles the remaining events in the events pool.\nfunc (g *Gui) consumeevents() error {\n\tfor {\n\t\tselect {\n\t\tcase ev := <-g.tbEvents:\n\t\t\tif err := g.handleEvent(&ev); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase ev := <-g.userEvents:\n\t\t\tif err := ev.f(g); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t}\n}\n\n// handleEvent handles an event, based on its type (key-press, error,\n// etc.)\nfunc (g *Gui) handleEvent(ev *termbox.Event) error {\n\tswitch ev.Type {\n\tcase termbox.EventKey, termbox.EventMouse:\n\t\treturn g.onKey(ev)\n\tcase termbox.EventError:\n\t\treturn ev.Err\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// flush updates the gui, re-drawing frames and buffers.\nfunc (g *Gui) flush() error {\n\ttermbox.Clear(termbox.Attribute(g.FgColor), termbox.Attribute(g.BgColor))\n\n\tmaxX, maxY := termbox.Size()\n\t// if GUI's size has changed, we need to redraw all views\n\tif maxX != g.maxX || maxY != g.maxY {\n\t\tfor _, v := range g.views {\n\t\t\tv.tainted = true\n\t\t}\n\t}\n\tg.maxX, g.maxY = maxX, maxY\n\n\tfor _, m := range g.managers {\n\t\tif err := m.Layout(g); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tfor _, v := range g.views {\n\t\tif v.Frame {\n\t\t\tvar fgColor, bgColor Attribute\n\t\t\tif g.Highlight && v == g.currentView {\n\t\t\t\tfgColor = g.SelFgColor\n\t\t\t\tbgColor = g.SelBgColor\n\t\t\t} else {\n\t\t\t\tfgColor = g.FgColor\n\t\t\t\tbgColor = g.BgColor\n\t\t\t}\n\n\t\t\tif err := g.drawFrameEdges(v, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err := g.drawFrameCorners(v, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif v.Title != "" {\n\t\t\t\tif err := g.drawTitle(v, fgColor, bgColor); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif err := g.draw(v); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\ttermbox.Flush()\n\treturn nil\n}\n\n// drawFrameEdges draws the horizontal and vertical edges of a view.\nfunc (g *Gui) drawFrameEdges(v *View, fgColor, bgColor Attribute) error {\n\truneH, runeV := '─', '│'\n\tif g.ASCII {\n\t\truneH, runeV = '-', '|'\n\t}\n\n\tfor x := v.x0 + 1; x < v.x1 && x < g.maxX; x++ {\n\t\tif x < 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif v.y0 > -1 && v.y0 < g.maxY {\n\t\t\tif err := g.SetRune(x, v.y0, runeH, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif v.y1 > -1 && v.y1 < g.maxY {\n\t\t\tif err := g.SetRune(x, v.y1, runeH, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tfor y := v.y0 + 1; y < v.y1 && y < g.maxY; y++ {\n\t\tif y < 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif v.x0 > -1 && v.x0 < g.maxX {\n\t\t\tif err := g.SetRune(v.x0, y, runeV, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif v.x1 > -1 && v.x1 < g.maxX {\n\t\t\tif err := g.SetRune(v.x1, y, runeV, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// drawFrameCorners draws the corners of the view.\nfunc (g *Gui) drawFrameCorners(v *View, fgColor, bgColor Attribute) error {\n\truneTL, runeTR, runeBL, runeBR := '┌', '┐', '└', '┘'\n\tif g.ASCII {\n\t\truneTL, runeTR, runeBL, runeBR = '+', '+', '+', '+'\n\t}\n\n\tcorners := []struct {\n\t\tx, y int\n\t\tch rune\n\t}{{v.x0, v.y0, runeTL}, {v.x1, v.y0, runeTR}, {v.x0, v.y1, runeBL}, {v.x1, v.y1, runeBR}}\n\n\tfor _, c := range corners {\n\t\tif c.x >= 0 && c.y >= 0 && c.x < g.maxX && c.y < g.maxY {\n\t\t\tif err := g.SetRune(c.x, c.y, c.ch, fgColor, bgColor); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// drawTitle draws the title of the view.\nfunc (g *Gui) drawTitle(v *View, fgColor, bgColor Attribute) error {\n\tif v.y0 < 0 || v.y0 >= g.maxY {\n\t\treturn nil\n\t}\n\n\tfor i, ch := range v.Title {\n\t\tx := v.x0 + i + 2\n\t\tif x < 0 {\n\t\t\tcontinue\n\t\t} else if x > v.x1-2 || x >= g.maxX {\n\t\t\tbreak\n\t\t}\n\t\tif err := g.SetRune(x, v.y0, ch, fgColor, bgColor); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// draw manages the cursor and calls the draw function of a view.\nfunc (g *Gui) draw(v *View) error {\n\tif g.Cursor {\n\t\tif curview := g.currentView; curview != nil {\n\t\t\tvMaxX, vMaxY := curview.Size()\n\t\t\tif curview.cx < 0 {\n\t\t\t\tcurview.cx = 0\n\t\t\t} else if curview.cx >= vMaxX {\n\t\t\t\tcurview.cx = vMaxX - 1\n\t\t\t}\n\t\t\tif curview.cy < 0 {\n\t\t\t\tcurview.cy = 0\n\t\t\t} else if curview.cy >= vMaxY {\n\t\t\t\tcurview.cy = vMaxY - 1\n\t\t\t}\n\n\t\t\tgMaxX, gMaxY := g.Size()\n\t\t\tcx, cy := curview.x0+curview.cx+1, curview.y0+curview.cy+1\n\t\t\tif cx >= 0 && cx < gMaxX && cy >= 0 && cy < gMaxY {\n\t\t\t\ttermbox.SetCursor(cx, cy)\n\t\t\t} else {\n\t\t\t\ttermbox.HideCursor()\n\t\t\t}\n\t\t}\n\t} else {\n\t\ttermbox.HideCursor()\n\t}\n\n\tv.clearRunes()\n\tif err := v.draw(); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// onKey manages key-press events. A keybinding handler is called when\n// a key-press or mouse event satisfies a configured keybinding. Furthermore,\n// currentView's internal buffer is modified if currentView.Editable is true.\nfunc (g *Gui) onKey(ev *termbox.Event) error {\n\tswitch ev.Type {\n\tcase termbox.EventKey:\n\t\tmatched, err := g.execKeybindings(g.currentView, ev)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif matched {\n\t\t\tbreak\n\t\t}\n\t\tif g.currentView != nil && g.currentView.Editable && g.currentView.Editor != nil {\n\t\t\tg.currentView.Editor.Edit(g.currentView, Key(ev.Key), ev.Ch, Modifier(ev.Mod))\n\t\t}\n\tcase termbox.EventMouse:\n\t\tmx, my := ev.MouseX, ev.MouseY\n\t\tv, err := g.ViewByPosition(mx, my)\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t\tif err := v.SetCursor(mx-v.x0-1, my-v.y0-1); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif _, err := g.execKeybindings(v, ev); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// execKeybindings executes the keybinding handlers that match the passed view\n// and event. The value of matched is true if there is a match and no errors.\nfunc (g *Gui) execKeybindings(v *View, ev *termbox.Event) (matched bool, err error) {\n\tmatched = false\n\tfor _, kb := range g.keybindings {\n\t\tif kb.handler == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif kb.matchKeypress(Key(ev.Key), ev.Ch, Modifier(ev.Mod)) && kb.matchView(v) {\n\t\t\tif err := kb.handler(g, v); err != nil {\n\t\t\t\treturn false, err\n\t\t\t}\n\t\t\tmatched = true\n\t\t}\n\t}\n\treturn matched, nil\n}"}}

[Trace - 9:46:00 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/edit.go","diagnostics":[]}

[Trace - 9:46:00 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/escape.go","diagnostics":[]}

[Trace - 9:46:00 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/gui.go","diagnostics":[]}

[Trace - 9:46:00 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/keybinding.go","diagnostics":[]}

[Trace - 9:46:00 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/view.go","diagnostics":[]}

[Trace - 9:46:00 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/attribute.go","diagnostics":[]}

[Trace - 9:46:00 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///Users/skanehira/dev/go/pkg/mod/github.com/jroimartin/gocui@v0.4.0/doc.go","diagnostics":[]}

@stamblerre stamblerre closed this Feb 6, 2019
@golang golang locked and limited conversation to collaborators Feb 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.