textrun-shell 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -45
- package/dist/actions/command-with-input.js +2 -2
- package/dist/actions/command.js +5 -3
- package/dist/actions/server.js +2 -2
- package/dist/helpers/configuration.js +4 -0
- package/package.json +16 -16
package/README.md
CHANGED
|
@@ -3,55 +3,79 @@
|
|
|
3
3
|
This package provides [Text-Runner](https://github.com/kevgo/text-runner)
|
|
4
4
|
actions for documenting console commands to be executed by the reader.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
## Setup
|
|
7
7
|
|
|
8
|
-
To add this package as a Text-Runner plugin
|
|
9
|
-
|
|
8
|
+
To add this package as a Text-Runner plugin:
|
|
9
|
+
|
|
10
|
+
<pre type="npm/install">
|
|
11
|
+
npm i -D textrun-shell
|
|
12
|
+
</pre>
|
|
10
13
|
|
|
11
14
|
<!-- TODO: verify this somehow -->
|
|
12
15
|
|
|
13
|
-
You can define the absolute path of
|
|
14
|
-
**textrun-shell.js** file in the root directory of your
|
|
15
|
-
an example:
|
|
16
|
+
You can define the absolute path of binaries that your documentation tests call
|
|
17
|
+
by creating a file **textrun-shell.js** file in the root directory of your
|
|
18
|
+
documentation. Here is an example:
|
|
16
19
|
|
|
17
20
|
```js
|
|
21
|
+
import * as path from "path"
|
|
22
|
+
import * as url from "url"
|
|
23
|
+
|
|
24
|
+
const __dirname = url.fileURLToPath(new URL(".", import.meta.url))
|
|
25
|
+
const foo_path = path.join(__dirname, "bin", "foo")
|
|
26
|
+
// console.log(`calling "foo" in the documentation now runs ${foo_path}`)
|
|
27
|
+
|
|
18
28
|
export default {
|
|
19
|
-
|
|
20
|
-
"
|
|
29
|
+
globals: {
|
|
30
|
+
"foo": foo_path
|
|
21
31
|
}
|
|
22
32
|
}
|
|
23
33
|
```
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
## shell/command
|
|
26
36
|
|
|
27
37
|
The <b type="action/name-full">shell/command</b> action runs a shell command and
|
|
28
|
-
waits until it finishes.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
>
|
|
33
|
-
> ```
|
|
34
|
-
> $ echo Hello world!
|
|
35
|
-
> ```
|
|
36
|
-
>
|
|
37
|
-
> It welcomes us with a nice greeting:
|
|
38
|
-
>
|
|
39
|
-
> ```
|
|
40
|
-
> Hello world!
|
|
41
|
-
> ```
|
|
42
|
-
|
|
43
|
-
The source code of this Shell tutorial when executed and verified by Text-Runner
|
|
44
|
-
looks like this:
|
|
38
|
+
waits until it finishes. The <b type="action/name-full">shell/command-output</b>
|
|
39
|
+
action verifies the output of the most recently executed shell command.
|
|
40
|
+
|
|
41
|
+
As an example, here is a hypothetical tutorial for how to use the Linux shell:
|
|
45
42
|
|
|
46
43
|
<a type="extension/runnable-region">
|
|
47
44
|
|
|
48
|
-
```
|
|
45
|
+
```html
|
|
49
46
|
The "echo" command prints text on the command line. For example, let's run:
|
|
50
47
|
|
|
51
48
|
<pre type="shell/command">
|
|
52
49
|
echo Hello world!
|
|
53
50
|
</pre>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
</a>
|
|
54
|
+
|
|
55
|
+
Some tutorials print a dollar sign at the beginning of the command to execute,
|
|
56
|
+
indicating an interactive command prompt. These dollar signs are ignored.
|
|
57
|
+
|
|
58
|
+
### allow-error attribute
|
|
59
|
+
|
|
60
|
+
By default, this step fails if the subshell command exits with a non-zero exit
|
|
61
|
+
code. To allow errors, add the `allow-error` attribute, like so:
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<pre type="shell/command" allow-error>
|
|
65
|
+
echo Hello world!
|
|
66
|
+
</pre>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## shell/command-output
|
|
70
|
+
|
|
71
|
+
The <b type="action/name-full">shell/command-output</b> action verifies the
|
|
72
|
+
output of the most recently executed shell command.
|
|
73
|
+
|
|
74
|
+
Here is the next paragraph of our hypothetical tutorial for the Linux shell:
|
|
75
|
+
|
|
76
|
+
<a type="extension/runnable-region">
|
|
54
77
|
|
|
78
|
+
```md
|
|
55
79
|
It welcomes us with a nice greeting:
|
|
56
80
|
|
|
57
81
|
<pre type="shell/command-output">
|
|
@@ -61,11 +85,10 @@ Hello world!
|
|
|
61
85
|
|
|
62
86
|
</a>
|
|
63
87
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
of the last shell command run.
|
|
88
|
+
Some tutorials print a dollar sign at the beginning of the command to execute,
|
|
89
|
+
indicating an interactive command prompt. These dollar signs are ignored.
|
|
67
90
|
|
|
68
|
-
|
|
91
|
+
## shell/command-with-input
|
|
69
92
|
|
|
70
93
|
You can run a shell command and enter text into it with the
|
|
71
94
|
<b type="action/name-full">shell/command-with-input</b> action.
|
|
@@ -115,7 +138,7 @@ and provide user input with an HTML table:
|
|
|
115
138
|
</tr>
|
|
116
139
|
<tr>
|
|
117
140
|
<td>which day is today</td>
|
|
118
|
-
<td>
|
|
141
|
+
<td>Monday</td>
|
|
119
142
|
</tr>
|
|
120
143
|
</table>
|
|
121
144
|
|
|
@@ -124,22 +147,23 @@ and provide user input with an HTML table:
|
|
|
124
147
|
It prints:
|
|
125
148
|
|
|
126
149
|
<pre type="shell/command-output">
|
|
127
|
-
Hello Text-Runner, happy
|
|
128
|
-
</pre
|
|
150
|
+
Hello Text-Runner, happy Monday!
|
|
151
|
+
</pre>
|
|
129
152
|
|
|
130
153
|
If the table contains multiple columns, the first column contains output to wait
|
|
131
154
|
for, and the last one text to enter once the output from the first column has
|
|
132
155
|
appeared. Middle columns are ignored. `<th>` elements are considered
|
|
133
156
|
descriptions and are also ignored.
|
|
134
157
|
|
|
135
|
-
|
|
158
|
+
## shell/server
|
|
136
159
|
|
|
137
160
|
Long-running processes, for example web or database servers, keep running while
|
|
138
161
|
Text-Runner continues executing other actions.
|
|
139
162
|
|
|
140
163
|
<a type="workspace/new-file">
|
|
141
164
|
|
|
142
|
-
As an example, let's say we
|
|
165
|
+
As an example, let's say we write a tutorial about developing a web server, have
|
|
166
|
+
just created an implementation in file **server.js**:
|
|
143
167
|
|
|
144
168
|
```js
|
|
145
169
|
console.log("server is running")
|
|
@@ -148,11 +172,9 @@ setTimeout(() => {}, 100_000)
|
|
|
148
172
|
|
|
149
173
|
</a>
|
|
150
174
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
<b type="action/name-full">shell/server
|
|
154
|
-
the <b type="action/name-full">shell/stop-server</b> action. Here is an example
|
|
155
|
-
that shows them in action:
|
|
175
|
+
Our tutorial instructs the user to start this long-running server to run in
|
|
176
|
+
parallel with Text-Runner with the
|
|
177
|
+
<b type="action/name-full">shell/server</b> action:
|
|
156
178
|
|
|
157
179
|
<a type="extension/runnable-region">
|
|
158
180
|
|
|
@@ -162,16 +184,46 @@ Start the server:
|
|
|
162
184
|
<pre type="shell/server">
|
|
163
185
|
node server.js
|
|
164
186
|
</pre>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
</a>
|
|
190
|
+
|
|
191
|
+
## shell/server-output
|
|
165
192
|
|
|
166
|
-
|
|
193
|
+
After we started a long-running server through
|
|
194
|
+
<em type="action/name-full">shell/server</em> above, we can await specific
|
|
195
|
+
output from it using the
|
|
196
|
+
<b type="action/name-full">shell/server-output</b> action.
|
|
197
|
+
|
|
198
|
+
Here is the next paragraph of our hypothetic server tutorial:
|
|
199
|
+
|
|
200
|
+
<a type="extension/runnable-region">
|
|
201
|
+
|
|
202
|
+
```html
|
|
203
|
+
Wait until the server is fully booted up:
|
|
167
204
|
|
|
168
205
|
<pre type="shell/server-output">
|
|
169
206
|
server is running
|
|
170
207
|
</pre>
|
|
171
|
-
|
|
172
|
-
Now you can interact with the server. When you are done, stop the server:
|
|
173
|
-
<a type="shell/stop-server">shell/stop-server</a>
|
|
174
208
|
```
|
|
175
209
|
|
|
176
210
|
</a>
|
|
211
|
+
|
|
212
|
+
## shell/stop-server
|
|
213
|
+
|
|
214
|
+
Stop a long-running process with the
|
|
215
|
+
<b type="action/name-full">shell/stop-server</b> action.
|
|
216
|
+
|
|
217
|
+
Here is the final part of our hypothetical server tutorial:
|
|
218
|
+
|
|
219
|
+
<a type="extension/runnable-region">
|
|
220
|
+
|
|
221
|
+
```html
|
|
222
|
+
When you are done, stop the server:
|
|
223
|
+
|
|
224
|
+
<pre type="shell/stop-server">
|
|
225
|
+
killall node
|
|
226
|
+
</pre>
|
|
177
227
|
```
|
|
228
|
+
|
|
229
|
+
</a>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { styleText } from "node:util";
|
|
2
2
|
import * as observableProcess from "observable-process";
|
|
3
3
|
import { callArgs } from "textrun-extension";
|
|
4
4
|
import { CurrentCommand } from "../helpers/current-command.js";
|
|
@@ -18,7 +18,7 @@ export async function commandWithInput(action) {
|
|
|
18
18
|
if (commandsToRun === "") {
|
|
19
19
|
throw new Error(`the <${action.region[0].tag} ${action.configuration.regionMarker}="exec-with-input"> region contains no commands to run`);
|
|
20
20
|
}
|
|
21
|
-
action.name(`running console command: ${
|
|
21
|
+
action.name(`running console command: ${styleText("cyan", commandsToRun)}`);
|
|
22
22
|
let input = [];
|
|
23
23
|
if (action.region.hasNodeOfType("table")) {
|
|
24
24
|
input = getInput(action.region);
|
package/dist/actions/command.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { styleText } from "node:util";
|
|
2
2
|
import * as observableProcess from "observable-process";
|
|
3
3
|
import * as trExt from "textrun-extension";
|
|
4
4
|
import { Configuration } from "../helpers/configuration.js";
|
|
@@ -6,6 +6,7 @@ import { CurrentCommand } from "../helpers/current-command.js";
|
|
|
6
6
|
import { trimDollar } from "../helpers/trim-dollar.js";
|
|
7
7
|
/** Runs the given commands synchronously on the console. */
|
|
8
8
|
export async function command(action) {
|
|
9
|
+
action.name("run shell command");
|
|
9
10
|
const configPath = action.configuration.sourceDir.joinStr("textrun-shell.js");
|
|
10
11
|
const config = await Configuration.load(configPath);
|
|
11
12
|
const commandsToRun = action.region
|
|
@@ -19,7 +20,8 @@ export async function command(action) {
|
|
|
19
20
|
if (commandsToRun === "") {
|
|
20
21
|
throw new Error(`the <${action.region[0].tag} ${action.configuration.regionMarker}="shell/command"> region contains no commands to run`);
|
|
21
22
|
}
|
|
22
|
-
action.
|
|
23
|
+
const allowError = action.region[0].attributes["allow-error"] !== undefined;
|
|
24
|
+
action.name(`running console command: ${styleText("cyan", commandsToRun)}`);
|
|
23
25
|
const processor = observableProcess.start(trExt.callArgs(commandsToRun, process.platform), {
|
|
24
26
|
cwd: action.configuration.workspace.platformified()
|
|
25
27
|
});
|
|
@@ -27,7 +29,7 @@ export async function command(action) {
|
|
|
27
29
|
const finished = (await processor.waitForEnd());
|
|
28
30
|
action.log(finished.combinedText);
|
|
29
31
|
CurrentCommand.set(finished);
|
|
30
|
-
if (finished.exitCode !== 0) {
|
|
32
|
+
if (finished.exitCode !== 0 && !allowError) {
|
|
31
33
|
throw new Error(`command "${commandsToRun}" failed with exit code ${finished.exitCode}`);
|
|
32
34
|
}
|
|
33
35
|
}
|
package/dist/actions/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { styleText } from "node:util";
|
|
2
2
|
import * as observableProcess from "observable-process";
|
|
3
3
|
import * as trExt from "textrun-extension";
|
|
4
4
|
import { CurrentServer } from "../helpers/current-server.js";
|
|
@@ -15,7 +15,7 @@ export function server(action) {
|
|
|
15
15
|
.filter((line) => line.length > 0)
|
|
16
16
|
.map(trimDollar)
|
|
17
17
|
.join(" && ");
|
|
18
|
-
action.name(`starting a server process: ${
|
|
18
|
+
action.name(`starting a server process: ${styleText(["bold", "cyan"], commandsToRun)}`);
|
|
19
19
|
CurrentServer.instance().set(observableProcess.start(trExt.callArgs(commandsToRun, process.platform), {
|
|
20
20
|
cwd: action.configuration.workspace.platformified()
|
|
21
21
|
}));
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import Debug from "debug";
|
|
1
2
|
import { PathMapper } from "./path-mapper.js";
|
|
3
|
+
const debug = Debug("shell");
|
|
2
4
|
/** Configuration represents the configuration options for the textrun-shell library. */
|
|
3
5
|
export class Configuration {
|
|
4
6
|
constructor(file) {
|
|
@@ -13,10 +15,12 @@ export class Configuration {
|
|
|
13
15
|
static async load(filePath) {
|
|
14
16
|
try {
|
|
15
17
|
const content = await import(filePath);
|
|
18
|
+
debug(`found path mapping in ${filePath}`);
|
|
16
19
|
const config = content.default;
|
|
17
20
|
return new Configuration(config);
|
|
18
21
|
}
|
|
19
22
|
catch (e) {
|
|
23
|
+
debug(`found no path mapping in ${filePath}`);
|
|
20
24
|
return Configuration.default();
|
|
21
25
|
}
|
|
22
26
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "textrun-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -9,29 +9,29 @@
|
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc -p tsconfig-build.json",
|
|
12
|
-
"clean": "rm -rf dist",
|
|
13
12
|
"cuke": "cucumber-js --format=progress",
|
|
14
13
|
"doc": "text-runner",
|
|
15
|
-
"fix": "eslint --fix --ignore-pattern=dist/ . && dprint fmt && sort-package-json --quiet",
|
|
14
|
+
"fix": "eslint --fix --ignore-pattern=dist/ . && dprint fmt && sort-package-json --quiet && ../tools/rta ghokin fmt replace features",
|
|
16
15
|
"lint": "dprint check && sort-package-json --check --quiet && eslint --ignore-pattern=dist/ . && depcheck --config=../.depcheckrc",
|
|
16
|
+
"reset": "rm -rf dist && yarn run build",
|
|
17
17
|
"unit": "node --test --import tsx 'src/**/*.test.ts'"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"assert-no-diff": "
|
|
21
|
-
"
|
|
22
|
-
"end-child-processes": "
|
|
23
|
-
"observable-process": "8.0.0
|
|
24
|
-
"strip-ansi": "7.1.
|
|
25
|
-
"text-runner-engine": "7.
|
|
26
|
-
"textrun-extension": "0.
|
|
20
|
+
"assert-no-diff": "4.1.0",
|
|
21
|
+
"debug": "4.4.3",
|
|
22
|
+
"end-child-processes": "2.0.3",
|
|
23
|
+
"observable-process": "8.0.0",
|
|
24
|
+
"strip-ansi": "7.1.2",
|
|
25
|
+
"text-runner-engine": "7.2.0",
|
|
26
|
+
"textrun-extension": "0.4.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"shared-cucumber-steps": "*",
|
|
30
|
-
"text-runner": "7.
|
|
31
|
-
"textrun-action": "0.
|
|
32
|
-
"textrun-extension": "0.
|
|
33
|
-
"textrun-workspace": "0.
|
|
34
|
-
"tsx": "4.
|
|
30
|
+
"text-runner": "7.2.0",
|
|
31
|
+
"textrun-action": "0.4.0",
|
|
32
|
+
"textrun-extension": "0.4.0",
|
|
33
|
+
"textrun-workspace": "0.4.0",
|
|
34
|
+
"tsx": "4.20.6"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "aecf7efd5e22e88535fe97ad7341b1a057520268"
|
|
37
37
|
}
|