Skip to content

Commit a3ef71c

Browse files
committed
Add the language Bash
1 parent 0694496 commit a3ef71c

File tree

10 files changed

+171
-5
lines changed

10 files changed

+171
-5
lines changed

assets/common.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ ul {
213213
background-color: #d9534f !important;
214214
}
215215

216+
.bash { background: svg(bash#000) 7px / 26px no-repeat }
216217
.javascript { background: svg(javascript#000) 7px / 26px no-repeat }
217218
.perl { background: svg(perl#000) 7px / 26px no-repeat }
218219
.perl6 { background: svg(perl6#000) 7px / 26px no-repeat }
@@ -386,6 +387,7 @@ ul {
386387
border-bottom: 1px solid #219a00;
387388
}
388389

390+
[href="#bash"] { background: #ccc svg(bash#fff) 7px / 26px no-repeat }
389391
[href="#javascript"] { background: #ccc svg(javascript#fff) 7px / 26px no-repeat }
390392
[href="#perl"] { background: #ccc svg(perl#fff) 7px / 26px no-repeat }
391393
[href="#perl6"] { background: #ccc svg(perl6#fff) 7px / 26px no-repeat }

assets/hole.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* include codemirror.js */
2+
/* include codemirror-bash.js */
23
/* include codemirror-clike.js */
34
/* include codemirror-javascript.js */
45
/* include codemirror-perl6.js */
@@ -12,7 +13,7 @@ onload = function() {
1213
let article = document.getElementsByTagName('article')[0];
1314
let editors = [];
1415

15-
for (let lang of ['javascript', 'perl', 'perl6', 'php', 'python', 'ruby']) {
16+
for (let lang of ['bash', 'javascript', 'perl', 'perl6', 'php', 'python', 'ruby']) {
1617
let code = article.dataset.hasOwnProperty(lang) ? article.dataset[lang] : '';
1718

1819
let editor = CodeMirror(article, {
@@ -41,7 +42,7 @@ onload = function() {
4142

4243
( onhashchange = function() {
4344
// Kick 'em to Perl 6 if we don't know the chosen language.
44-
if (!/^#(?:javascript|perl6?|php|python|ruby)$/.exec(location.hash))
45+
if (!/^#(?:bash|javascript|perl6?|php|python|ruby)$/.exec(location.hash))
4546
location.hash = 'perl6';
4647

4748
let lang = location.hash.slice(1);

assets/includes/bash.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/includes/codemirror-bash.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2+
// Distributed under an MIT license: http://codemirror.net/LICENSE
3+
4+
(function(mod) {
5+
mod(CodeMirror);
6+
})(function(CodeMirror) {
7+
"use strict";
8+
9+
CodeMirror.defineMode('bash', function() {
10+
11+
var words = {};
12+
function define(style, string) {
13+
var split = string.split(' ');
14+
for(var i = 0; i < split.length; i++) {
15+
words[split[i]] = style;
16+
}
17+
};
18+
19+
// Atoms
20+
define('atom', 'true false');
21+
22+
// Keywords
23+
define('keyword', 'if then do else elif while until for in esac fi fin ' +
24+
'fil done exit set unset export function');
25+
26+
// Commands
27+
define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' +
28+
'curl cut diff echo find gawk gcc get git grep hg kill killall ln ls make ' +
29+
'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' +
30+
'shopt shred source sort sleep ssh start stop su sudo svn tee telnet top ' +
31+
'touch vi vim wall wc wget who write yes zsh');
32+
33+
function tokenBase(stream, state) {
34+
if (stream.eatSpace()) return null;
35+
36+
var sol = stream.sol();
37+
var ch = stream.next();
38+
39+
if (ch === '\\') {
40+
stream.next();
41+
return null;
42+
}
43+
if (ch === '\'' || ch === '"' || ch === '`') {
44+
state.tokens.unshift(tokenString(ch, ch === "`" ? "quote" : "string"));
45+
return tokenize(stream, state);
46+
}
47+
if (ch === '#') {
48+
if (sol && stream.eat('!')) {
49+
stream.skipToEnd();
50+
return 'meta'; // 'comment'?
51+
}
52+
stream.skipToEnd();
53+
return 'comment';
54+
}
55+
if (ch === '$') {
56+
state.tokens.unshift(tokenDollar);
57+
return tokenize(stream, state);
58+
}
59+
if (ch === '+' || ch === '=') {
60+
return 'operator';
61+
}
62+
if (ch === '-') {
63+
stream.eat('-');
64+
stream.eatWhile(/\w/);
65+
return 'attribute';
66+
}
67+
if (/\d/.test(ch)) {
68+
stream.eatWhile(/\d/);
69+
if(stream.eol() || !/\w/.test(stream.peek())) {
70+
return 'number';
71+
}
72+
}
73+
stream.eatWhile(/[\w-]/);
74+
var cur = stream.current();
75+
if (stream.peek() === '=' && /\w+/.test(cur)) return 'def';
76+
return words.hasOwnProperty(cur) ? words[cur] : null;
77+
}
78+
79+
function tokenString(quote, style) {
80+
var close = quote == "(" ? ")" : quote == "{" ? "}" : quote
81+
return function(stream, state) {
82+
var next, end = false, escaped = false;
83+
while ((next = stream.next()) != null) {
84+
if (next === close && !escaped) {
85+
end = true;
86+
break;
87+
}
88+
if (next === '$' && !escaped && quote !== "'") {
89+
escaped = true;
90+
stream.backUp(1);
91+
state.tokens.unshift(tokenDollar);
92+
break;
93+
}
94+
if (!escaped && next === quote && quote !== close) {
95+
state.tokens.unshift(tokenString(quote, style))
96+
return tokenize(stream, state)
97+
}
98+
escaped = !escaped && next === '\\';
99+
}
100+
if (end) state.tokens.shift();
101+
return style;
102+
};
103+
};
104+
105+
var tokenDollar = function(stream, state) {
106+
if (state.tokens.length > 1) stream.eat('$');
107+
var ch = stream.next()
108+
if (/['"({]/.test(ch)) {
109+
state.tokens[0] = tokenString(ch, ch == "(" ? "quote" : ch == "{" ? "def" : "string");
110+
return tokenize(stream, state);
111+
}
112+
if (!/\d/.test(ch)) stream.eatWhile(/\w/);
113+
state.tokens.shift();
114+
return 'def';
115+
};
116+
117+
function tokenize(stream, state) {
118+
return (state.tokens[0] || tokenBase) (stream, state);
119+
};
120+
121+
return {
122+
startState: function() {return {tokens:[]};},
123+
token: function(stream, state) {
124+
return tokenize(stream, state);
125+
},
126+
closeBrackets: "()[]{}''\"\"``",
127+
lineComment: '#',
128+
fold: "brace"
129+
};
130+
});
131+
});

build-langs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#!/bin/bash -e
22

3-
docker pull alpine:edge
3+
#docker pull alpine:edge
44

55
cd containers
66

7-
for name in JavaScript Perl Perl\ 6 PHP Python Ruby; do
7+
for name in Bash JavaScript Perl Perl\ 6 PHP Python Ruby; do
88
lang=${name,,} # lowercase
99
lang=${lang// /} # trim space
1010

containers/bash/.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*

containers/bash/Dockerfile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
FROM alpine:edge
2+
3+
RUN apk add --no-cache curl gcc make musl-dev
4+
5+
RUN curl https://ftp.gnu.org/gnu/bash/bash-4.4.12.tar.gz | tar xzf -
6+
7+
RUN cd bash-4.4.12 \
8+
&& ./configure \
9+
--disable-command-timing \
10+
--disable-debugger \
11+
--disable-directory-stack \
12+
--disable-help-builtin \
13+
--disable-job-control \
14+
--disable-net-redirections \
15+
--disable-progcomp \
16+
--disable-select \
17+
--enable-static-link \
18+
--without-bash-malloc \
19+
&& make \
20+
&& strip bash
21+
22+
FROM scratch
23+
24+
COPY --from=0 /bash-4.4.12/bash /usr/bin/
25+
26+
ENTRYPOINT ["/usr/bin/bash", "-c", "echo ${BASH_VERSION%\\([0-9]\\)-release}"]

routes/hole.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func hole(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
7979

8080
w.Write([]byte(
8181
">" + preambles[hole] +
82+
"<a class=tab href=#bash>Bash<span></span></a>" +
8283
"<a class=tab href=#javascript>JS<span></span></a>" +
8384
"<a class=tab href=#perl>Perl<span></span></a>" +
8485
"<a class=tab href=#perl6>Perl 6<span></span></a>" +

routes/scores.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func scores(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
4141

4242
// TODO Find a better way to do this.
4343
switch lang {
44-
case "all", "javascript", "perl", "perl6", "php", "python", "ruby":
44+
case "all", "bash", "javascript", "perl", "perl6", "php", "python", "ruby":
4545
default:
4646
print404(w, r)
4747
return
@@ -87,6 +87,7 @@ func scores(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
8787

8888
for _, v := range [][]string{
8989
{"all", "All Langs"},
90+
{"bash", "Bash"},
9091
{"javascript", "JavaScript"},
9192
{"perl", "Perl"},
9293
{"perl6", "Perl 6"},

routes/solution.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ func runCode(hole, lang, code string, args []string) (string, string) {
134134
}
135135

136136
switch lang {
137+
case "bash":
138+
cmd.Args = []string{"/usr/bin/bash", "-s", "-"}
137139
case "javascript":
138140
cmd.Args = []string{"/usr/bin/js", "-f", "-", "--"}
139141
// The perls seems to show -- in @ARGV :-(

0 commit comments

Comments
 (0)