turbo-editors/turbo-gopublic Fork 0
v1.0.0
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.

📦 Turbo Go 3d7798b · on v1.0.0 · k33g · 13h ago
go-tools.md · 236 lines · 10.2 KBmarkdown
Blame HistoryOpen raw

Reference: go tools

Neutral description of .turbo-go/tools.toml, the Go menu, and what running a command does.

File

Property Value
Path ./.turbo-go/tools.toml
Search The working directory only. Parent directories are not searched.
Read Every time one of its menus opens, for the items
Re-read Whenever the file's size or modification time changes, for the set of menus
Missing file Not an error
Unreadable file An error, shown in the menu
User-level file None. Unlike snippets, there is no ~/.config/turbo-go/tools.toml.

File format

One [[tool]] table per command.

Key Type Required Description
name string yes What the menu shows. May carry a hot key written with tildes, as in "~T~est".
command string yes The shell command to run
output string no Where its output goes: popup, terminal or editor. Absent means popup.
menu string no Which menu it appears in. Absent means Go. Any name; the menu is created for you. May carry a hot key written with tildes.

menu is not checked against a list, because there is no list: a name that no other tool uses simply creates a menu. A tool with no name, no command, or an output naming something that does not exist makes the whole file an error. An unknown output is refused rather than corrected: "termnial" would otherwise look as though it had worked while sending the output somewhere else.

Example

[[tool]]
name = "~T~est"
command = "go test ./..."
output = "popup"

[[tool]]
name = "~E~cho"
command = "echo TADA"
output = "terminal"
menu = "Tools"

The starter file

Go ▸ Create tools file writes these five, in this order:

Name Command Output
Format gofmt -l -w . popup
Lint go vet ./... popup
Build go build ./... popup
Test go test ./... popup
Run go run . terminal

None of them names a menu, so all five are in the Go menu. Every one names its output, including the four that name the default: the key is the interesting part of the format, and a file where it appears once is a file where nobody notices it exists.

The item is greyed out once the project has a tools file, so it cannot overwrite one. The file is written through a temporary file in the same directory, renamed into place.

The Go menu

Always on the bar, whether or not a tools file exists. Its hot key is Alt-G.

Item Condition
One line per tool with no menu, in file order The file holds at least one
Cannot read tools, greyed out The file is present but unreadable
Create tools file The project has no tools file
Open tools file The project has one

A menu naming anything other than Go puts a menu of that name on the bar.

Property Value
Position Between Go and Help
Order The order each name first appears in the file
Items One line per tool naming that menu, in file order. Nothing else — Create tools file and Open tools file stay in Go.
Unreadable file No menus at all; the Go menu carries the error
While the editor runs Added, removed and renamed as the file changes, without restarting

Hot keys

Assigned automatically, because a name from a file cannot be checked against the fixed menus in advance.

Case Result
No tildes in the name The first letter no other menu has claimed is marked. Format becomes For~m~at: F is File's, o is Options', r is Run's.
Tildes naming a free letter Kept as written. Doc~k~er answers to Alt-K.
Tildes naming a taken letter Dropped, and a free letter chosen instead. ~F~oo becomes F~o~o.
Every letter taken No hot key. F10 and the mouse still open it.

The letters the editor's own menus hold are F, E, S, R, O, W, N (Snippets), G and H.

Running a command

Common to every output:

Property Value
Shell /bin/sh -c "<command>" on Linux and macOS; cmd.exe /S /C "<command>" — the shell %COMSPEC% names — on Windows
Directory The directory the editor was started in
Standard error Merged into standard output, in the order the command wrote them

Going through a shell means pipes, globs, && and ; all work, so one tool can be a sequence. On Windows the shell is cmd.exe, which knows &&, | and > but does not expand globs, and where ; is not a separator.

output = "popup"

Property Value
Opens Immediately, before the command has finished
Modal Yes: nothing else in the editor can be used while it is up
Fills in As output arrives, following it until you scroll back
Title while running <command> — running
Title when finished <command> — ok, or <command> — exit <n>
Empty output, finished Shows (no output)
Empty output, running Shows nothing
Output cap 10000 lines; past it the oldest go and a … n earlier lines dropped … line says so
Key Effect
PgUp PgDn Home End Read through the output
Wheel The same
Escape, Enter, Close Close it, stopping the command if it is still running

Closing stops the command because there is no other way to interrupt one whose output is not in a terminal.

output = "terminal"

Property Value
Window A terminal window of its own, titled with the command
Environment The editor's own, with TERM set to xterm-256color
After it exits The window stays, showing its output
Modal No: the editor carries on beside it

Because it is a real terminal, colours, paging, Ctrl-C and reading from the keyboard all work. See Terminal windows.

Keys in a finished terminal window:

Key Effect
Shift-PgUp, Shift-PgDn Read back through the output
Ctrl-W Close the window
Anything else Reaches the editor, not the dead shell

output = "editor"

Property Value
Shows A popup while it runs, as above
On closing the popup An editing window holding the output, titled with the command
Filled Once, when the command has finished — not as it goes
The window An ordinary editing window with no file name: searchable with Ctrl-F, and Save as keeps it

Reloading after a command

When a command finishes, every open file is considered.

The file What happens
Unmodified, and changed on disk Re-read; its syntax is re-decided and its title refreshed
Unmodified, and unchanged on disk Left alone, not counted
Has unsaved changes Left alone and counted as skipped
Has never been named Left alone
Has gone from disk Left alone

The cursor stays where it was, clamped into whatever the file now holds. The undo history is discarded, because undoing back past a reload would restore text the file no longer has.

The project tree is refreshed at the same moment.

Status bar When
Running <command> The window opens
Reloaded 2 files Two files were re-read, none skipped
Reloaded 2 files; 1 file with unsaved changes left alone Some were skipped
Command finished; 1 file with unsaved changes left alone Nothing was re-read, something was skipped

Errors

Message Cause
Cannot read tools in the menu The file is present but not valid TOML, or holds a tool with no name or no command
Already there: .turbo-go/tools.toml Creating in a project that already has one. Unreachable from the menu, which greys the item out; still possible for a caller that is not a menu.
This project has no .turbo-go/tools.toml yet. Opening in a project that has none, likewise
Cannot tell which directory this is: … The working directory could not be read
Terminal windows are not supported on this platform yet Running a command in a terminal needs a pseudo-terminal, which Linux, macOS and Windows have; see Terminal windows

Asking for a value

A {{label}} anywhere in a command is a value the editor asks for before it runs, in a box titled after the tool. The text between the braces is what the box asks for.

Written Asked for Substituted
{{module path}} module path shell-quoted
{{extra flags...}} extra flags verbatim

A value is shell-quoted by default, so a path with a space in it stays one argument. A trailing ... inside the braces asks for it verbatim instead, which is how one field can stand for several arguments.

[[tool]]
name = "~I~nit module"
command = "go mod init {{module path}}"
output = "popup"
Rule Behaviour
Several placeholders One box, one field each, in the order they appear in the command
The same label twice One field; every occurrence gets what is typed into it
A label written both ways Asked for once; each occurrence honours its own braces
Escape, or Cancel The command does not run
A field left empty Substituted as empty — the command reports its own complaint
Running the tool again The box starts from what was typed last time, for this session only
More fields than fit on screen Refused, with a message saying how many fit

Double braces, not single. awk '{print $1}' and find . -exec rm {} + are ordinary commands, and a single-brace syntax would read the first as a request for a value called print $1.

Nothing is written to disk. A value somebody typed this afternoon is not a decision the project made, so it does not go in the project's own directory.

Errors

Error Cause
tool "X": "{{module" is never closed An opening {{ with no }} after it
tool "X": {{}} asks for a value but does not say what it is A placeholder with no label, or one that is only ...

Both are refused when the file is read, so a half-typed placeholder never reaches the shell with its braces still in it.

See also

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# Reference: go tools

> Neutral description of `.turbo-go/tools.toml`, the Go menu, and what running a command does.

## File

| Property | Value |
| --- | --- |
| Path | `./.turbo-go/tools.toml` |
| Search | The working directory only. Parent directories are **not** searched. |
| Read | Every time one of its menus opens, for the items |
| Re-read | Whenever the file's size or modification time changes, for the **set** of menus |
| Missing file | Not an error |
| Unreadable file | An error, shown in the menu |
| User-level file | **None.** Unlike snippets, there is no `~/.config/turbo-go/tools.toml`. |

## File format

One `[[tool]]` table per command.

| Key | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | What the menu shows. May carry a hot key written with tildes, as in `"~T~est"`. |
| `command` | string | yes | The shell command to run |
| `output` | string | no | Where its output goes: `popup`, `terminal` or `editor`. Absent means `popup`. |
| `menu` | string | no | Which menu it appears in. Absent means `Go`. Any name; the menu is created for you. May carry a hot key written with tildes. |

`menu` is not checked against a list, because there is no list: a name that no other tool uses simply creates a menu. A tool with no `name`, no `command`, or an `output` naming something that does not exist makes the whole file an error. An unknown `output` is **refused rather than corrected**: `"termnial"` would otherwise look as though it had worked while sending the output somewhere else.

### Example

```toml
[[tool]]
name = "~T~est"
command = "go test ./..."
output = "popup"

[[tool]]
name = "~E~cho"
command = "echo TADA"
output = "terminal"
menu = "Tools"
```

## The starter file

**Go ▸ Create tools file** writes these five, in this order:

| Name | Command | Output |
| --- | --- | --- |
| Format | `gofmt -l -w .` | `popup` |
| Lint | `go vet ./...` | `popup` |
| Build | `go build ./...` | `popup` |
| Test | `go test ./...` | `popup` |
| Run | `go run .` | `terminal` |

None of them names a `menu`, so all five are in the Go menu. Every one names its `output`, including the four that name the default: the key is the interesting part of the format, and a file where it appears once is a file where nobody notices it exists.

The item is greyed out once the project has a tools file, so it cannot overwrite one. The file is written through a temporary file in the same directory, renamed into place.

## The Go menu

Always on the bar, whether or not a tools file exists. Its hot key is `Alt-G`.

| Item | Condition |
| --- | --- |
| One line per tool with no `menu`, in file order | The file holds at least one |
| `Cannot read tools`, greyed out | The file is present but unreadable |
| `Create tools file` | The project has no tools file |
| `Open tools file` | The project has one |

## Menus a tool asks for

A `menu` naming anything other than `Go` puts a menu of that name on the bar.

| Property | Value |
| --- | --- |
| Position | Between Go and Help |
| Order | The order each name first appears in the file |
| Items | One line per tool naming that menu, in file order. Nothing else — `Create tools file` and `Open tools file` stay in Go. |
| Unreadable file | No menus at all; the Go menu carries the error |
| While the editor runs | Added, removed and renamed as the file changes, without restarting |

### Hot keys

Assigned automatically, because a name from a file cannot be checked against the fixed menus in advance.

| Case | Result |
| --- | --- |
| No tildes in the name | The first letter no other menu has claimed is marked. `Format` becomes `For~m~at`: `F` is File's, `o` is Options', `r` is Run's. |
| Tildes naming a free letter | Kept as written. `Doc~k~er` answers to `Alt-K`. |
| Tildes naming a taken letter | Dropped, and a free letter chosen instead. `~F~oo` becomes `F~o~o`. |
| Every letter taken | No hot key. `F10` and the mouse still open it. |

The letters the editor's own menus hold are `F`, `E`, `S`, `R`, `O`, `W`, `N` (Snippets), `G` and `H`.

## Running a command

Common to every output:

| Property | Value |
| --- | --- |
| Shell | `/bin/sh -c "<command>"` on Linux and macOS; `cmd.exe /S /C "<command>"` — the shell `%COMSPEC%` names — on Windows |
| Directory | The directory the editor was started in |
| Standard error | Merged into standard output, in the order the command wrote them |

Going through a shell means pipes, globs, `&&` and `;` all work, so one tool can be a sequence. On Windows the shell is cmd.exe, which knows `&&`, `|` and `>` but does not expand globs, and where `;` is not a separator.

### `output = "popup"`

| Property | Value |
| --- | --- |
| Opens | Immediately, before the command has finished |
| Modal | Yes: nothing else in the editor can be used while it is up |
| Fills in | As output arrives, following it until you scroll back |
| Title while running | `<command> — running` |
| Title when finished | `<command> — ok`, or `<command> — exit <n>` |
| Empty output, finished | Shows `(no output)` |
| Empty output, running | Shows nothing |
| Output cap | 10000 lines; past it the oldest go and a `… n earlier lines dropped …` line says so |

| Key | Effect |
| --- | --- |
| `↑` `↓` `PgUp` `PgDn` `Home` `End` | Read through the output |
| Wheel | The same |
| `Escape`, `Enter`, **Close** | Close it, **stopping the command** if it is still running |

Closing stops the command because there is no other way to interrupt one whose output is not in a terminal.

### `output = "terminal"`

| Property | Value |
| --- | --- |
| Window | A terminal window of its own, titled with the command |
| Environment | The editor's own, with `TERM` set to `xterm-256color` |
| After it exits | The window stays, showing its output |
| Modal | No: the editor carries on beside it |

Because it is a real terminal, colours, paging, `Ctrl-C` and reading from the keyboard all work. See [Terminal windows](terminal.md).

Keys in a **finished** terminal window:

| Key | Effect |
| --- | --- |
| `Shift-PgUp`, `Shift-PgDn` | Read back through the output |
| `Ctrl-W` | Close the window |
| Anything else | Reaches the editor, not the dead shell |

### `output = "editor"`

| Property | Value |
| --- | --- |
| Shows | A popup while it runs, as above |
| On closing the popup | An editing window holding the output, titled with the command |
| Filled | Once, when the command has finished — not as it goes |
| The window | An ordinary editing window with no file name: searchable with `Ctrl-F`, and `Save as` keeps it |

## Reloading after a command

When a command finishes, every open file is considered.

| The file | What happens |
| --- | --- |
| Unmodified, and changed on disk | Re-read; its syntax is re-decided and its title refreshed |
| Unmodified, and unchanged on disk | Left alone, not counted |
| Has unsaved changes | Left alone and counted as skipped |
| Has never been named | Left alone |
| Has gone from disk | Left alone |

The cursor stays where it was, clamped into whatever the file now holds. The undo history is discarded, because undoing back past a reload would restore text the file no longer has.

The project tree is refreshed at the same moment.

| Status bar | When |
| --- | --- |
| `Running <command>` | The window opens |
| `Reloaded 2 files` | Two files were re-read, none skipped |
| `Reloaded 2 files; 1 file with unsaved changes left alone` | Some were skipped |
| `Command finished; 1 file with unsaved changes left alone` | Nothing was re-read, something was skipped |

## Errors

| Message | Cause |
| --- | --- |
| `Cannot read tools` in the menu | The file is present but not valid TOML, or holds a tool with no name or no command |
| `Already there: .turbo-go/tools.toml` | Creating in a project that already has one. Unreachable from the menu, which greys the item out; still possible for a caller that is not a menu. |
| `This project has no .turbo-go/tools.toml yet.` | Opening in a project that has none, likewise |
| `Cannot tell which directory this is: …` | The working directory could not be read |
| `Terminal windows are not supported on this platform yet` | Running a command in a terminal needs a pseudo-terminal, which Linux, macOS and Windows have; see [Terminal windows](terminal.md) |

## Asking for a value

A `{{label}}` anywhere in a command is a value the editor asks for before it runs, in a box titled after the tool. The text between the braces is what the box asks for.

| Written | Asked for | Substituted |
| --- | --- | --- |
| `{{module path}}` | `module path` | shell-quoted |
| `{{extra flags...}}` | `extra flags` | verbatim |

A value is **shell-quoted** by default, so a path with a space in it stays one argument. A trailing `...` inside the braces asks for it verbatim instead, which is how one field can stand for several arguments.

```toml
[[tool]]
name = "~I~nit module"
command = "go mod init {{module path}}"
output = "popup"
```

| Rule | Behaviour |
| --- | --- |
| Several placeholders | One box, one field each, in the order they appear in the command |
| The same label twice | One field; every occurrence gets what is typed into it |
| A label written both ways | Asked for once; each occurrence honours its own braces |
| Escape, or Cancel | The command does not run |
| A field left empty | Substituted as empty — the command reports its own complaint |
| Running the tool again | The box starts from what was typed last time, for this session only |
| More fields than fit on screen | Refused, with a message saying how many fit |

**Double braces, not single.** `awk '{print $1}'` and `find . -exec rm {} +` are ordinary commands, and a single-brace syntax would read the first as a request for a value called `print $1`.

Nothing is written to disk. A value somebody typed this afternoon is not a decision the project made, so it does not go in the project's own directory.

### Errors

| Error | Cause |
| --- | --- |
| `tool "X": "{{module" is never closed` | An opening `{{` with no `}}` after it |
| `tool "X": {{}} asks for a value but does not say what it is` | A placeholder with no label, or one that is only `...` |

Both are refused when the file is read, so a half-typed placeholder never reaches the shell with its braces still in it.

## See also

- [How to run go commands from the editor](../how-to/run-go-commands.md)
- [Go tools](../explanation/go-tools.md)
- [Terminal windows](terminal.md)