Skip to content

Commit 1784b17

Browse files
authored
Command Line: Add support for line continuation and improved colors (#3326)
1 parent f545843 commit 1784b17

5 files changed

+83
-21
lines changed

plugins/command-line/index.html

+28
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ <h1>How to use</h1>
4949
</dl>
5050

5151
<p>Optional: To automatically present some lines as output, you can prefix those lines with any string and specify the prefix using the <code class="language-markup">data-filter-output</code> attribute on the <code class="language-markup">&lt;pre></code> element. For example, <code class="language-markup">data-filter-output="(out)"</code> will treat lines beginning with <code class="language-markup">(out)</code> as output and remove the prefix.</p>
52+
53+
<p>Output lines are user selectable by default, so if you select the whole content of the code block, it will select the shell commands and any output lines. This may not be desireable if you want to copy/paste just the commands and not the output. If you want to make the output not user selectable then add the following to your CSS:</p>
54+
55+
<pre><code class="language-css">.command-line span.token.output {
56+
user-select: none;
57+
}</code></pre>
58+
59+
<p>Optional: For multi-line commands you can specify the <code class="language-markup">data-continuation-str</code> attribute on the <code class="language-markup">&lt;pre></code> element. For example, <code class="language-markup">data-continuation-str="\"</code> will treat lines ending with <code class="language-markup">\</code> as being continued on the following line. Continued lines will have a prompt as set by the attribute <code class="language-markup">data-continuation-prompt</code> or a default of <code class="language-markup">&gt;</code>.</p>
5260
</section>
5361

5462
<section>
@@ -90,6 +98,26 @@ <h2>Windows PowerShell With Output</h2>
9098
d-r-- 10/14/2015 5:06 PM Searches
9199
d-r-- 10/14/2015 5:06 PM Videos</code></pre>
92100

101+
<h2>Line continuation with Output (bash)</h2>
102+
<pre class="command-line" data-filter-output="(out)" data-continuation-str="\" ><code class="language-bash">echo "hello"
103+
(out)hello
104+
echo one \
105+
two \
106+
three
107+
(out)one two three
108+
(out)
109+
echo "goodbye"
110+
(out)goodbye</code></pre>
111+
112+
<h2>Line continuation with Output (PowerShell)</h2>
113+
<pre class="command-line" data-prompt="PS C:\Users\Chris>" data-continuation-prompt=">>" data-filter-output="(out)" data-continuation-str=" `"><code class="language-powershell">Write-Host `
114+
'Hello' `
115+
'from' `
116+
'PowerShell!'
117+
(out)Hello from PowerShell!
118+
Write-Host 'Goodbye from PowerShell!'
119+
(out)Goodbye from PowerShell!</code></pre>
120+
93121
</section>
94122

95123
<footer data-src="assets/templates/footer.html" data-type="text/html"></footer>

plugins/command-line/prism-command-line.css

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
letter-spacing: -1px;
77
margin-right: 1em;
88
pointer-events: none;
9+
text-align: right;
910

1011
-webkit-user-select: none;
1112
-moz-user-select: none;
@@ -14,7 +15,7 @@
1415
}
1516

1617
.command-line-prompt > span:before {
17-
color: #999;
18+
opacity: 0.4;
1819
content: ' ';
1920
display: block;
2021
padding-right: 0.8em;
@@ -31,3 +32,12 @@
3132
.command-line-prompt > span[data-prompt]:before {
3233
content: attr(data-prompt);
3334
}
35+
36+
.command-line-prompt > span[data-continuation-prompt]:before {
37+
content: attr(data-continuation-prompt);
38+
}
39+
40+
.command-line span.token.output {
41+
/* Make shell output lines a bit lighter to distinguish them from shell commands */
42+
opacity: 0.7;
43+
}

plugins/command-line/prism-command-line.js

+42-18
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,16 @@
1212
? function (s, p) { return s.startsWith(p); }
1313
: function (s, p) { return s.indexOf(p) === 0; };
1414

15-
/**
16-
* Repeats the given string some number of times.
17-
*
18-
* This is just a polyfill for `String.prototype.repeat`.
19-
*
20-
* @param {string} str
21-
* @param {number} times
22-
* @returns {string}
23-
*/
24-
function repeat(str, times) {
25-
var s = '';
26-
for (var i = 0; i < times; i++) {
27-
s += str;
15+
// Support for IE11 that has no endsWith()
16+
/** @type {(str: string, suffix: string) => boolean} */
17+
var endsWith = ''.endsWith
18+
? function (str, suffix) {
19+
return str.endsWith(suffix);
2820
}
29-
return s;
30-
}
21+
: function (str, suffix) {
22+
var len = str.length;
23+
return str.substring(len - suffix.length, len) === suffix;
24+
};
3125

3226
/**
3327
* Returns whether the given hook environment has a command line info object.
@@ -79,6 +73,22 @@
7973
}
8074

8175
var codeLines = env.code.split('\n');
76+
77+
var continuationLineIndicies = commandLine.continuationLineIndicies = new Set();
78+
var lineContinuationStr = pre.getAttribute('data-continuation-str');
79+
80+
// Identify code lines that are a continuation line and thus don't need
81+
// a prompt
82+
if (lineContinuationStr && codeLines.length > 1) {
83+
for (var j = 1; j < codeLines.length; j++) {
84+
if (codeLines.hasOwnProperty(j - 1)
85+
&& endsWith(codeLines[j - 1], lineContinuationStr)) {
86+
// Mark this line as being a continuation line
87+
continuationLineIndicies.add(j);
88+
}
89+
}
90+
}
91+
8292
commandLine.numberOfLines = codeLines.length;
8393
/** @type {string[]} */
8494
var outputLines = commandLine.outputLines = [];
@@ -168,15 +178,29 @@
168178
}
169179

170180
// Create the "rows" that will become the command-line prompts. -- cwells
171-
var promptLines;
181+
var promptLines = '';
172182
var rowCount = commandLine.numberOfLines || 0;
173183
var promptText = getAttribute('data-prompt', '');
184+
var promptLine;
174185
if (promptText !== '') {
175-
promptLines = repeat('<span data-prompt="' + promptText + '"></span>', rowCount);
186+
promptLine = '<span data-prompt="' + promptText + '"></span>';
176187
} else {
177188
var user = getAttribute('data-user', 'user');
178189
var host = getAttribute('data-host', 'localhost');
179-
promptLines = repeat('<span data-user="' + user + '" data-host="' + host + '"></span>', rowCount);
190+
promptLine = '<span data-user="' + user + '" data-host="' + host + '"></span>';
191+
}
192+
193+
var continuationLineIndicies = commandLine.continuationLineIndicies || new Set();
194+
var continuationPromptText = getAttribute('data-continuation-prompt', '>');
195+
var continuationPromptLine = '<span data-continuation-prompt="' + continuationPromptText + '"></span>';
196+
197+
// Assemble all the appropriate prompt/continuation lines
198+
for (var j = 0; j < rowCount; j++) {
199+
if (continuationLineIndicies.has(j)) {
200+
promptLines += continuationPromptLine;
201+
} else {
202+
promptLines += promptLine;
203+
}
180204
}
181205

182206
// Create the wrapper element. -- cwells

plugins/command-line/prism-command-line.min.css

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/command-line/prism-command-line.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)