turbo-editors/turbo-rustpublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-rust.git
git clone ssh://git@rickub.com/turbo-editors/turbo-rust.git

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

rustlang.go · 126 lines · 4.4 KBGo Blame HistoryRaw
📦 Turbo Rust 713ea5c k33g 10h ago1// Package rustlang is everything about Turbo Rust that is about *Rust*: how the
2// editor names itself, which language server it talks to, what a Cargo
3// project's starter files say, and how Rust source is coloured.
4//
5// Everything else the editor does lives in turbo-core, which knows nothing
6// about Rust. This package is the whole of the difference between Turbo Rust
7// and Turbo Go, which is what makes a third editor a matter of writing one of
8// these rather than forking anything.
9//
10// rustlang.Register() // teach the library to colour Rust
11// editor := app.New(screen, name, rustlang.Profile())
12package rustlang
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-rust) and the stem of its environment
24// variables (as TURBO_RUST_…), so it is not free to change.
25const (
26 Name = "Turbo Rust"
27 Slug = "turbo-rust"
28)
29
30// Language is the name Rust is known by: the value LanguageOf returns for a .rs
31// file, and what a snippets file writes in its languages key.
32const Language syntax.Language = "rust"
33
34// ServerCommand is the language server Turbo Rust talks to, and InstallHint the
35// single command that installs it.
36//
37// rustup is the way nearly everybody has Rust, and `rustup component add` is
38// the shortest true answer for them. Somebody who installed Rust from their
39// distribution will have their own package for it; the hint has to fit on a
40// status bar, so it names the common case.
41const (
42 ServerCommand = "rust-analyzer"
43 InstallHint = "rustup component add rust-analyzer"
44)
45
46// Profile returns the editor Turbo Rust is.
47//
48// It is a function rather than a variable because Server.Dirs is worked out
49// from the environment, and a variable would freeze whatever CARGO_HOME said
50// when the package was linked.
51func Profile() profile.Profile {
52 return profile.Profile{
53 Name: Name,
54 Slug: Slug,
55 Language: "Rust",
56 // R is Run's and S is Search's, so the hot key lands on the T. The
57 // alternative was naming the menu Cargo, which would have taken C — but
58 // the menu holds whatever the project put in its tools file, and that is
59 // not always cargo.
60 ToolsMenu: "Rus~t~",
61 // Cargo.toml is the crate's boundary, and the crate is what
62 // rust-analyzer loads. A workspace root has one too, and the nearest one
63 // going up is the right answer for both.
64 RootMarkers: []string{"Cargo.toml"},
65 Server: profile.Server{
66 Command: ServerCommand,
67 // rust-analyzer takes no subcommand, unlike gopls.
68 Args: nil,
69 InstallHint: InstallHint,
70 Dirs: []string{CargoBinDir(), RustupToolchainBinDir()},
71 },
72 Templates: profile.Templates{
73 Settings: settingsTemplate,
74 Snippets: snippetsTemplate,
75 Tools: toolsTemplate,
76 Agents: agentsTemplate,
77 },
78 }
79}
80
81// Register teaches turbo-core to colour Rust.
82//
83// It is called explicitly at start-up rather than from an init function so that
84// "which languages does this editor know?" is answered by reading main, not by
85// working out which packages were imported.
86func Register() {
87 syntax.Register(syntax.Definition{
88 Language: Language,
89 Extensions: []string{".rs"},
90 Highlight: Highlight,
91 })
92}
93
94// CargoBinDir returns where cargo puts the binaries it installs: CARGO_HOME/bin
95// when CARGO_HOME is set, and ~/.cargo/bin otherwise.
96//
97// It is one of the two places rust-analyzer is looked for after PATH.
98func CargoBinDir() string {
99 if home := os.Getenv("CARGO_HOME"); home != "" {
100 return filepath.Join(home, "bin")
101 }
102 home, err := os.UserHomeDir()
103 if err != nil {
104 return ""
105 }
106 return filepath.Join(home, ".cargo", "bin")
107}
108
109// RustupToolchainBinDir returns rustup's own binary directory,
110// RUSTUP_HOME/bin, defaulting to ~/.rustup/bin.
111//
112// `rustup component add rust-analyzer` — the command the install hint gives —
113// puts a shim on PATH through ~/.cargo/bin, but a machine where the cargo
114// directory was never added to PATH still has this one, and looking in both is
115// cheaper than explaining the difference to somebody whose completion is
116// silently missing.
117func RustupToolchainBinDir() string {
118 if home := os.Getenv("RUSTUP_HOME"); home != "" {
119 return filepath.Join(home, "bin")
120 }
121 home, err := os.UserHomeDir()
122 if err != nil {
123 return ""
124 }
125 return filepath.Join(home, ".rustup", "bin")
126}