github.com/v2fly/tools@v0.100.0/internal/lsp/cmd/remote.go (about) 1 // Copyright 2020 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 package cmd 6 7 import ( 8 "context" 9 "encoding/json" 10 "flag" 11 "fmt" 12 "log" 13 "os" 14 15 "github.com/v2fly/tools/internal/lsp/command" 16 "github.com/v2fly/tools/internal/lsp/lsprpc" 17 errors "golang.org/x/xerrors" 18 ) 19 20 type remote struct { 21 subcommands 22 23 // For backward compatibility, allow aliasing this command (it was previously 24 // called 'inspect'). 25 // 26 // TODO(rFindley): delete this after allowing some transition time in case 27 // there were any users of 'inspect' (I suspect not). 28 alias string 29 } 30 31 func newRemote(app *Application, alias string) *remote { 32 return &remote{ 33 subcommands: subcommands{ 34 &listSessions{app: app}, 35 &startDebugging{app: app}, 36 }, 37 alias: alias, 38 } 39 } 40 41 func (r *remote) Name() string { 42 if r.alias != "" { 43 return r.alias 44 } 45 return "remote" 46 } 47 48 func (r *remote) ShortHelp() string { 49 short := "interact with the gopls daemon" 50 if r.alias != "" { 51 short += " (deprecated: use 'remote')" 52 } 53 return short 54 } 55 56 // listSessions is an inspect subcommand to list current sessions. 57 type listSessions struct { 58 app *Application 59 } 60 61 func (c *listSessions) Name() string { return "sessions" } 62 func (c *listSessions) Usage() string { return "" } 63 func (c *listSessions) ShortHelp() string { 64 return "print information about current gopls sessions" 65 } 66 67 const listSessionsExamples = ` 68 Examples: 69 70 1) list sessions for the default daemon: 71 72 $ gopls -remote=auto remote sessions 73 or just 74 $ gopls remote sessions 75 76 2) list sessions for a specific daemon: 77 78 $ gopls -remote=localhost:8082 remote sessions 79 ` 80 81 func (c *listSessions) DetailedHelp(f *flag.FlagSet) { 82 fmt.Fprint(f.Output(), listSessionsExamples) 83 f.PrintDefaults() 84 } 85 86 func (c *listSessions) Run(ctx context.Context, args ...string) error { 87 remote := c.app.Remote 88 if remote == "" { 89 remote = "auto" 90 } 91 state, err := lsprpc.QueryServerState(ctx, remote) 92 if err != nil { 93 return err 94 } 95 v, err := json.MarshalIndent(state, "", "\t") 96 if err != nil { 97 log.Fatal(err) 98 } 99 os.Stdout.Write(v) 100 return nil 101 } 102 103 type startDebugging struct { 104 app *Application 105 } 106 107 func (c *startDebugging) Name() string { return "debug" } 108 func (c *startDebugging) Usage() string { return "[host:port]" } 109 func (c *startDebugging) ShortHelp() string { 110 return "start the debug server" 111 } 112 113 const startDebuggingExamples = ` 114 Examples: 115 116 1) start a debug server for the default daemon, on an arbitrary port: 117 118 $ gopls -remote=auto remote debug 119 or just 120 $ gopls remote debug 121 122 2) start for a specific daemon, on a specific port: 123 124 $ gopls -remote=localhost:8082 remote debug localhost:8083 125 ` 126 127 func (c *startDebugging) DetailedHelp(f *flag.FlagSet) { 128 fmt.Fprint(f.Output(), startDebuggingExamples) 129 f.PrintDefaults() 130 } 131 132 func (c *startDebugging) Run(ctx context.Context, args ...string) error { 133 if len(args) > 1 { 134 fmt.Fprintln(os.Stderr, c.Usage()) 135 return errors.New("invalid usage") 136 } 137 remote := c.app.Remote 138 if remote == "" { 139 remote = "auto" 140 } 141 debugAddr := "" 142 if len(args) > 0 { 143 debugAddr = args[0] 144 } 145 debugArgs := command.DebuggingArgs{ 146 Addr: debugAddr, 147 } 148 var result command.DebuggingResult 149 if err := lsprpc.ExecuteCommand(ctx, remote, command.StartDebugging.ID(), debugArgs, &result); err != nil { 150 return err 151 } 152 if len(result.URLs) == 0 { 153 return errors.New("no debugging URLs") 154 } 155 for _, url := range result.URLs { 156 fmt.Printf("debugging on %s\n", url) 157 } 158 return nil 159 }