turbo-editors/turbo-gopublic Fork 0
v1.0.2
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-go.git
git clone ssh://git@rickub.com/turbo-editors/turbo-go.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

golang.go · 118 lines · 3.9 KBGo Blame HistoryRaw
📦 Turbo Go 3d7798b k33g 10h ago1// Package golang is everything about Turbo Go that is about *Go*: how the
2// editor names itself, which language server it talks to, what a Go project's
3// starter files say, and how Go source is coloured.
4//
5// Everything else the editor does lives in turbo-core, which knows nothing
6// about Go. This package is the whole of the difference between Turbo Go and
7// Turbo Rust, which is what makes a third editor a matter of writing one of
8// these rather than forking anything.
9//
10// golang.Register() // teach the library to colour Go
11// editor := app.New(screen, name, golang.Profile())
12package golang
13
14import (
15 "os"
16 "path/filepath"
17
18 "rickub.com/turbo-editors/turbo-core/profile"
19 "rickub.com/turbo-editors/turbo-core/syntax"
20)
21
22// Name and Slug are what the editor calls itself. The slug is also its binary,
23// its project directory (as .turbo-go) and the stem of its environment
24// variables (as TURBO_GO_…), so it is not free to change.
25const (
26 Name = "Turbo Go"
27 Slug = "turbo-go"
28)
29
30// Language is the name Go is known by: the value LanguageOf returns for a .go
31// file, and what a snippets file writes in its languages key.
32const Language syntax.Language = "go"
33
34// ServerCommand is the language server Turbo Go talks to, and InstallHint the
35// single command that installs it.
36const (
37 ServerCommand = "gopls"
38 InstallHint = "go install golang.org/x/tools/gopls@latest"
39)
40
41// Profile returns the editor Turbo Go is.
42//
43// It is a function rather than a variable because Server.Dirs is worked out
44// from the environment, and a variable would freeze whatever GOPATH said when
45// the package was linked.
46func Profile() profile.Profile {
47 return profile.Profile{
48 Name: Name,
49 Slug: Slug,
50 Language: "Go",
51 // Go is fixed on the bar and takes G, which no other menu claims.
52 ToolsMenu: "~G~o",
53 // go.mod is the module's boundary, and the module is what gopls loads.
54 RootMarkers: []string{"go.mod"},
55 Server: profile.Server{
56 Command: ServerCommand,
57 // gopls needs a subcommand; most language servers do not.
58 Args: []string{"serve"},
59 InstallHint: InstallHint,
60 Dirs: []string{BinDir()},
61 },
62 Templates: profile.Templates{
63 Settings: settingsTemplate,
64 Snippets: snippetsTemplate,
65 Tools: toolsTemplate,
66 Agents: agentsTemplate,
67 },
68 }
69}
70
71// Register teaches turbo-core to colour Go.
72//
73// It is called explicitly at start-up rather than from an init function so that
74// "which languages does this editor know?" is answered by reading main, not by
75// working out which packages were imported.
76func Register() {
77 syntax.Register(syntax.Definition{
78 Language: Language,
79 Extensions: []string{".go"},
80 Highlight: highlight,
81 })
82}
83
84// highlight colours Go source with go/scanner — the same lexer the Go toolchain
85// uses, so the editor and the compiler agree about what a token is.
86//
87// It works in byte offsets rather than a line at a time, which is why it goes
88// through syntax.LineIndex instead of syntax.LineScanner.
89func highlight(src string) [][]syntax.Span {
90 lines := syntax.NewLineIndex(src)
91 out := make([][]syntax.Span, lines.Count())
92
93 tokens := scanTokens(src)
94 for i, class := range classify(tokens) {
95 lines.AppendSpans(out, tokens[i].start, tokens[i].end, class)
96 }
97 return out
98}
99
100// BinDir returns where "go install" puts binaries: GOBIN when it is set,
101// GOPATH/bin otherwise, and the conventional ~/go/bin when neither is.
102//
103// It is where gopls is looked for after PATH, because `go install` puts it
104// somewhere that is very often not on PATH — which is the single most common
105// reason completion is missing on a machine that has gopls.
106func BinDir() string {
107 if gobin := os.Getenv("GOBIN"); gobin != "" {
108 return gobin
109 }
110 if gopath := os.Getenv("GOPATH"); gopath != "" {
111 return filepath.Join(gopath, "bin")
112 }
113 home, err := os.UserHomeDir()
114 if err != nil {
115 return ""
116 }
117 return filepath.Join(home, "go", "bin")
118}