turbo-editors/turbo-corepublic Fork 0
v1.0.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

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

actions_view.go · 171 lines · 5.3 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 17h ago1// Everything the Options, Window and Help menus do: how the editor looks and
2// how its windows are arranged.
3package app
4
5import (
6 "fmt"
7 "path/filepath"
8 "strings"
9
📦 Turbo Core f3ade8d k33g 10h ago10 "rickub.com/turbo-editors/turbo-core/editor"
11 "rickub.com/turbo-editors/turbo-core/theme"
12 "rickub.com/turbo-editors/turbo-core/ui"
13 "rickub.com/turbo-editors/turbo-core/version"
🛟 Updated. 28d5985 k33g 17h ago14)
15
16// ToggleLineNumbers shows or hides the gutter in the front window.
17func (a *App) ToggleLineNumbers() {
18 a.withView(func(v *editor.View) { v.SetLineNumbers(!v.LineNumbers()) })
19}
20
21// ChooseTheme offers the available themes and applies the one picked.
22func (a *App) ChooseTheme() {
23 names := theme.Available(a.profile.ThemeDir())
24 dialog, list := NewChoiceDialog("Theme", names, indexOf(names, a.themeName), a.screenRect())
25
26 a.pushModal(dialog, func(result ui.Result) {
27 if result == ui.ResultOK && list.Selected() >= 0 {
28 a.setTheme(names[list.Selected()])
29 a.rememberTheme(a.themeName)
30 a.Message("Theme: " + a.theme.Name())
31 }
32 })
33}
34
35// NextWindow brings the window behind the front one forward.
36func (a *App) NextWindow() { a.desktop.Next() }
37
38// TileWindows lays every window out side by side.
39func (a *App) TileWindows() { a.desktop.Tile() }
40
41// CascadeWindows stacks the windows with their titles showing.
42func (a *App) CascadeWindows() { a.desktop.Cascade() }
43
44// MaximizeWindow gives the front window the whole desktop, or puts it back
45// where it was if it already has it — the same toggle as the frame's box, so
46// the menu and the button never disagree.
47func (a *App) MaximizeWindow() {
48 if window := a.desktop.Active(); window != nil {
49 a.desktop.ToggleMaximize(window)
50 }
51}
52
53// ListWindows offers the open windows and brings the chosen one forward.
54func (a *App) ListWindows() {
55 windows := a.desktop.Windows()
56 if len(windows) == 0 {
57 return
58 }
59
60 names := make([]string, len(windows))
61 for i, window := range windows {
62 names[i] = fmt.Sprintf("%d. %s", window.Number(), window.Title())
63 }
64
65 dialog, list := NewChoiceDialog("Windows", names, len(windows)-1, a.screenRect())
66 a.pushModal(dialog, func(result ui.Result) {
67 if result == ui.ResultOK && list.Selected() >= 0 {
68 a.desktop.Focus(windows[list.Selected()])
69 }
70 })
71}
72
73// ShowLanguageStatus reports what the language server is doing, in enough
74// detail to explain a completion that produced nothing.
75func (a *App) ShowLanguageStatus() {
76 a.ShowMessage("Language server", strings.Join(a.languageReport(), "\n"))
77}
78
79// languageReport builds the lines the status box shows.
80func (a *App) languageReport() []string {
81 report := a.language.Report()
82 lines := []string{report.Status}
83
84 if report.ServerPath != "" {
85 lines = append(lines, "Server: "+report.ServerPath)
86 }
87 if report.Root != "" {
88 lines = append(lines, "Root: "+report.Root)
89 }
90 if !report.Ready {
91 return append(lines, "", "Editing and colouring work without it;", "only completion needs a language server.")
92 }
93 return append(lines, a.currentFileReport()...)
94}
95
96// currentFileReport says what the server knows about the file being edited,
97// which is where an unexplained empty completion is usually explained.
98func (a *App) currentFileReport() []string {
99 view := a.activeView()
100 if view == nil {
101 return nil
102 }
103 path := view.Buffer().Path()
104 if path == "" {
105 return []string{"", "This window has no file yet, so the server", "has nothing to answer about. Save it first."}
106 }
107
108 lines := []string{"File: " + filepath.Base(path)}
109 if !a.language.Knows(path) {
110 return append(lines, "", "The server has not been told about it.")
111 }
112 if diagnostic, ok := a.language.FirstError(path); ok {
113 return append(lines, "Problem: "+diagnostic.Message, "",
114 "Completion needs the file's package to compile.")
115 }
116 return lines
117}
118
119// ShowAbout shows the About box.
120func (a *App) ShowAbout() {
121 a.ShowMessage("About", aboutText(a.profile.Name, a.profile.Language, version.Current(), a.theme.Name()))
122}
123
124// aboutText is what the About box says.
125//
126// The language comes from the profile rather than being written into this
127// string: this box belongs to the library, and the library is not for Go. It
128// said "an editor for Go" in every editor built on it until Turbo Rust showed
129// somebody the wrong sentence.
130//
131// A fact the build did not record is **left out rather than shown empty**: a
132// binary from `go install …@v0.2.0` knows its version and nothing else, and a
133// blank "Commit:" line would say only that the editor failed to fill it in.
134func aboutText(name, language string, info version.Info, themeName string) string {
135 lines := []string{
136 name + " " + info.Number,
137 "",
138 "A Turbo C-style editor for " + language + ",",
139 "written in Go.",
140 "",
141 }
142 if info.Commit != "" {
143 lines = append(lines, "Commit: "+info.Commit)
144 }
145 if built := info.BuiltAt(); built != "" {
146 lines = append(lines, "Built: "+built)
147 }
148 return strings.Join(append(lines, "Theme: "+themeName), "\n")
149}
150
151// ShowKeyboardHelp lists the keys worth knowing.
152func (a *App) ShowKeyboardHelp() {
153 a.ShowMessage("Keyboard", strings.Join([]string{
154 "F2 Save F3 Open F4 New",
155 "F6 Next window F7 Find next",
156 "F10 Menu F12 Go to definition",
157 "Ctrl-F Find Ctrl-G Go to line",
158 "Ctrl-Space Completion",
159 "Alt-1…9 Window Alt-X Exit",
160 }, "\n"))
161}
162
163// indexOf returns where a name sits in a list, or zero when it is absent.
164func indexOf(names []string, wanted string) int {
165 for i, name := range names {
166 if name == wanted {
167 return i
168 }
169 }
170 return 0
171}