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

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

run-node-commands.md · 236 lines · 11.9 KBmarkdown Blame HistoryRaw
📦 Turbo JS 91999d1 k33g 12h ago1# How to run Node commands from the editor
2
3This guide shows how to install, format, lint, test and run your project without leaving Turbo JS. It assumes the editor is installed and you have a directory with a `package.json` in it.
4
5## Get a starter file
6
7Start the editor **from the directory holding `package.json`**, then choose **JavaScript ▸ Create tools file** (`Alt-J`, then `C`).
8
9That writes `.turbo-js/tools.toml` with the commands a Node project runs most, and opens it. The first three:
10
11```toml
12[[tool]]
13name = "~I~nstall"
14command = "npm install"
15output = "popup"
16
17[[tool]]
18name = "~F~ormat"
19command = "npx prettier --write ."
20output = "popup"
21
22[[tool]]
23name = "~L~int"
24command = "npx eslint ."
25output = "popup"
26```
27
28Each `[[tool]]` becomes one line of the **JavaScript** menu, in the order they appear — unless it names a `menu` of its own, which a later section covers. The file is read every time the menu opens, so an edit takes effect immediately.
29
30## Run one
31
32`Alt-J`, then the letter between the tildes — `I` to install, `T` to test.
33
34**Test** opens a **popup** at once, which fills in as the command runs. Its title carries the command and, once it has ended, how it went:
35
36```
37┌──────────────── node --test — ok ─────────────────┐
38│ ✔ greets by name (1.204ms) │
39│ ℹ tests 1 │
40│ ℹ suites 0 │
41│ ℹ pass 1 │
42│ ℹ fail 0 │
43│ │
44│ [ Close ] │
45└────────────────────────────────────────────────────┘
46```
47
48| Key | Effect |
49| --- | --- |
50| `↑` `↓` `PgUp` `PgDn` `Home` `End` | Read through the output |
51| `Escape` | Close it — and **stop the command** if it is still running |
52| `Enter` | Close it |
53
54A command that succeeded silently — `npx prettier --write .` on a project already formatted — shows `(no output)` rather than a blank box, so you can tell it from one that has not started.
55
56**Run** asks first, because a Node project has no single entry point the editor could know:
57
58```
59┌──────────────── Run ────────────────┐
60│ script, e.g. main.js │
61│ [ ] │
62└─────────────────────────────────────┘
63```
64
65Type `main.js` and press `Enter`. A terminal window opens and the script runs in it; when it ends the window stays, showing what it printed. Press `Ctrl-W` to close it. Run it again and the box remembers the name for the rest of the session.
66
67## The rest of the menu
68
69| Item | What it runs | Where |
70| --- | --- | --- |
71| **Install** | `npm install` — the dependencies `package.json` names, into `node_modules/` | a popup |
72| **Format** | `npx prettier --write .` — Prettier over the whole project | a popup; the open files are re-read afterwards |
73| **Lint** | `npx eslint .` — ESLint over the whole project | a popup; ESLint 9 needs an `eslint.config.js` |
74| **Test** | `node --test` — Node's own runner over every `*.test.js`, `*.spec.js` and `test/**/*.js` | a popup |
75| **Run** | `node <script>` — the script you name | a terminal, because a script may read the keyboard |
76| **Start** | `npm start` — whatever the `start` script in `package.json` says | a terminal, because it is usually a server |
77
78`npx` runs the project's own Prettier and ESLint when `package.json` depends on them, and downloads them into npm's cache the first time otherwise — which is why the first **Format** on a machine takes a few seconds and the second does not.
79
80`npm install` can take a while. The popup is modal, so while it runs you cannot type anywhere else; `Escape` closes it and stops the install.
81
82## Choose where the output goes
83
84Set `output` on a tool:
85
86| `output` | What you get |
87| --- | --- |
88| `popup` | A dialog that fills in as it runs. The default. |
89| `terminal` | A terminal window: colours, `Ctrl-C`, and the keyboard reaches the program |
90| `editor` | An editing window once it has finished, to search with `Ctrl-F` |
91
92`Run` and `Start` are `terminal` in the starter file, and they are the example of why the key exists: a popup cannot answer a script that reads `process.stdin`, and cannot be interrupted with `Ctrl-C` while a server is listening.
93
94Reach for `editor` when the output is something to work through — the tree `npm ls` prints, or a long test report you want to search.
95
96## A long command holds the editor
97
98A popup is modal: while `npm install` runs, you cannot type anywhere else. `Escape` closes it and stops the command.
99
100If that gets in the way for a particular command, give it `output = "terminal"` — the window is an ordinary one and you can carry on working beside it. That is what making the key configurable is for.
101
102## What happens to your open files
103
104`npx prettier --write .` rewrites the file you are looking at, `npm install` writes `node_modules/` and `package-lock.json` into the directory, and a tool of your own may do anything. When a command finishes, the editor **re-reads every open file that has no unsaved changes**, so a file another command changed appears as it now is, and the project tree is refreshed so a new one shows up. The status bar says how many.
105
106A file with unsaved changes is **left alone**, and the status bar says so too:
107
108```
109Reloaded 2 files; 1 file with unsaved changes left alone
110```
111
112That is deliberate: your edit and the command genuinely disagree, and the editor is not the one that should decide which wins. Save first (`F2`) and run the command again, or keep editing. With **Format** in particular: save, then format, or Prettier's work on that file is skipped.
113
114## Add your own commands
115
116Edit `.turbo-js/tools.toml`. A command goes to `sh -c`, so one entry can be a whole sequence:
117
118```toml
119[[tool]]
120name = "~C~heck"
121command = "node --check {{script, e.g. main.js}}"
122output = "popup"
123
124[[tool]]
125name = "Lint and ~t~est"
126command = "npx eslint . && node --test"
127output = "popup"
128
129[[tool]]
130name = "~W~atch"
131command = "node --watch {{script, e.g. server.js}}"
132output = "terminal"
133
134[[tool]]
135name = "~D~ependencies"
136command = "npm ls --all"
137output = "editor"
138```
139
140Give each a hot key with tildes, and keep them distinct — the menu answers the first match it finds.
141
142## Put a tool in a menu of its own
143
144A tool that has nothing to do with JavaScript does not belong in the JavaScript menu. Give it a `menu`:
145
146```toml
147[[tool]]
148name = "~E~cho"
149command = "echo TADA"
150output = "terminal"
151menu = "Tools"
152
153[[tool]]
154name = "~U~p"
155command = "docker compose up -d"
156menu = "Docker"
157
158[[tool]]
159name = "~D~own"
160command = "docker compose down"
161menu = "Docker"
162```
163
164That gives you a **Tools** menu and a **Docker** menu on the bar, between JavaScript and Help, in the order the names first appear in the file. Docker holds both its tools. Nothing needs restarting: save the file and the bar follows.
165
166The name is yours to choose — there is no list to pick from. Leave `menu` out and the tool stays in JavaScript, which is where six of the seven starter commands are.
167
168### The hot key is chosen for you
169
170You cannot know, when writing the file, which letters the editor's own menus have taken. So it works it out: the first letter of the name that nothing else claims gets the tildes.
171
172`Tools` gets `Alt-T`, because `T` is free. A menu called `Format` would get `Alt-M`, because `F` is File's, `o` is Options' and `r` is Run's. A menu called `Jobs` would get `Alt-B`, because `J` is JavaScript's and `o` is Options'.
173
174Write the tildes yourself — `menu = "Doc~k~er"` — and a free letter is kept. A taken one is not: the bar answers the *first* menu matching a key, so honouring your choice would make one of the two menus unreachable. It picks another letter and says nothing.
175
176## Variants
177
178- **Your project uses pnpm, Yarn or Bun.** Replace `npm install` with `pnpm install`, `npx eslint .` with `pnpm exec eslint .`, and so on. The starter file is npm because npm ships with Node; nothing in the editor knows which package manager runs.
179- **You have one script and never another.** Replace `node {{script, e.g. main.js}}` with `node main.js`, and the box stops appearing. The placeholder is there because a starter file cannot know which file is the program.
180- **Your tests use Vitest, Jest or Mocha.** Replace `node --test` with `npx vitest run`, `npx jest` or `npx mocha`. `npm test` also works, if `package.json` has a `test` script that is not the `echo "Error: no test specified"` npm writes by default.
181- **You started the editor from a subdirectory.** Commands run there, and `npm` looks for `package.json` there and in the directories above — but `npx prettier --write .` formats only that subdirectory. Start from the directory `package.json` is in.
182- **The file has a mistake in it.** The menu shows a greyed-out `Cannot read tools` where the commands would be, and **Create tools file** is still there.
183- **`npx eslint .` says it cannot find a configuration file.** ESLint 9 reads `eslint.config.js`; `npm init @eslint/config@latest` writes one. Older projects have `.eslintrc.json`, which ESLint 9 no longer reads.
184- **You want a menu named after one that exists.** `menu = "File"` gives you a second File menu, further along the bar, with a different hot key. Nothing stops you; nothing recommends it either.
185- **Your menu has no hot key.** Every letter in its name was already taken. `F10` and the arrow keys reach it, and so does the mouse. Rename it to something with a free letter.
186- **You misspelt `output`'s value.** The whole file is refused and the menu says `Cannot read tools`, naming the tool and listing what it could have been. A silent fallback would have sent the output somewhere you did not ask for.
187
188## Ask for a value when the command runs
189
190`Run` already does. The pattern is a `{{label}}` where the value goes:
191
192```toml
193[[tool]]
194name = "~A~dd a package"
195command = "npm install {{package name}}"
196output = "popup"
197```
198
199Choosing it opens a box titled **Add a package** with one field, labelled `package name`. **Enter** runs the command. Escape, and nothing runs. Several placeholders give several fields, in the order they appear; **Tab** moves between them.
200
201The value is quoted, so a path with a space in it stays one argument.
202
203### One field standing for several arguments
204
205Quoting is wrong when you mean "put these on the end". Add `...` inside the braces and the value goes in verbatim:
206
207```toml
208[[tool]]
209name = "Run with ~a~rguments"
210command = "node main.js {{arguments...}}"
211output = "terminal"
212```
213
214Type `--verbose input.txt` and both reach the script as separate arguments — `process.argv.slice(2)` holds them.
215
216### The same value twice
217
218Write the label twice; you are asked once:
219
220```toml
221[[tool]]
222name = "Test ~o~ne"
223command = "node --test {{file}} && node --check {{file}}"
224```
225
226### Variants
227
228- **The value is the same most times.** Run it once and the box remembers what you typed, for the rest of the session. It is not written to disk.
229- **Your command has braces in it already.** `awk '{print $1}'` and `find . -exec rm {} +` are left alone: only double braces ask for anything. So is a JavaScript `${x}` inside a `node -e` one-liner — one brace, not two.
230- **The command asks for more values than fit on screen.** The editor says so rather than opening a box whose OK button is below the bottom of the terminal. Make the terminal taller, or split the command into two tools.
231
232## See also
233
234- Every key of the file and every rule: [JavaScript tools reference](../reference/javascript-tools.md)
235- Why Install comes first, and why an unmodified file reloads: [JavaScript tools](../explanation/javascript-tools.md)
236- The windows the commands run in: [Terminal windows](../reference/terminal.md)