diff --git a/components.js b/components.js index 51ee723bec..f35bd076b6 100644 --- a/components.js +++ b/components.js @@ -97,6 +97,10 @@ var components = { "title": "BASIC", "owner": "Golmote" }, + "batch": { + "title": "Batch", + "owner": "Golmote" + }, "bison": { "title": "Bison", "require": "c", diff --git a/components/prism-batch.js b/components/prism-batch.js new file mode 100644 index 0000000000..c7ca9ca60d --- /dev/null +++ b/components/prism-batch.js @@ -0,0 +1,99 @@ +(function (Prism) { + var variable = /%%?[~:\w]+%?|!\S+!/; + var parameter = { + pattern: /\/[a-z?]+(?=[ :]|$):?|-[a-z]\b|--[a-z-]+\b/im, + alias: 'attr-name', + inside: { + 'punctuation': /:/ + } + }; + var string = /"[^"]*"/; + var number = /(?:\b|-)\d+\b/; + + Prism.languages.batch = { + 'comment': [ + /^::.*/m, + { + pattern: /((?:^|[&(])[ \t]*)rem\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im, + lookbehind: true + } + ], + 'label': { + pattern: /^:.*/m, + alias: 'property' + }, + 'command': [ + { + // FOR command + pattern: /((?:^|[&(])[ \t]*)for(?: ?\/[a-z?](?:[ :](?:"[^"]*"|\S+))?)* \S+ in \([^)]+\) do/im, + lookbehind: true, + inside: { + 'keyword': /^for\b|\b(?:in|do)\b/i, + 'string': string, + 'parameter': parameter, + 'variable': variable, + 'number': number, + 'punctuation': /[()',]/ + } + }, + { + // IF command + pattern: /((?:^|[&(])[ \t]*)if(?: ?\/[a-z?](?:[ :](?:"[^"]*"|\S+))?)* (?:not )?(?:cmdextversion \d+|defined \w+|errorlevel \d+|exist \S+|(?:"[^"]*"|\S+)?(?:==| (?:equ|neq|lss|leq|gtr|geq) )(?:"[^"]*"|\S+))/im, + lookbehind: true, + inside: { + 'keyword': /^if\b|\b(?:not|cmdextversion|defined|errorlevel|exist)\b/i, + 'string': string, + 'parameter': parameter, + 'variable': variable, + 'number': number, + 'operator': /\^|==|\b(?:equ|neq|lss|leq|gtr|geq)\b/i + } + }, + { + // ELSE command + pattern: /((?:^|[&()])[ \t]*)else\b/im, + lookbehind: true, + inside: { + 'keyword': /^else\b/i + } + }, + { + // SET command + pattern: /((?:^|[&(])[ \t]*)set(?: ?\/[a-z](?:[ :](?:"[^"]*"|\S+))?)* (?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im, + lookbehind: true, + inside: { + 'keyword': /^set\b/i, + 'string': string, + 'parameter': parameter, + 'variable': [ + variable, + /\w+(?=(?:[*\/%+\-&^|]|<<|>>)?=)/ + ], + 'number': number, + 'operator': /[*\/%+\-&^|]=?|<<=?|>>=?|[!~_=]/, + 'punctuation': /[()',]/ + } + }, + { + // Other commands + pattern: /((?:^|[&(])[ \t]*@?)\w+\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im, + lookbehind: true, + inside: { + 'keyword': /^\w+\b/i, + 'string': string, + 'parameter': parameter, + 'label': { + pattern: /(^\s*):\S+/m, + lookbehind: true, + alias: 'property' + }, + 'variable': variable, + 'number': number, + 'operator': /\^/ + } + } + ], + 'operator': /[&@]/, + 'punctuation': /[()']/ + }; +}(Prism)); \ No newline at end of file diff --git a/components/prism-batch.min.js b/components/prism-batch.min.js new file mode 100644 index 0000000000..6ce5085710 --- /dev/null +++ b/components/prism-batch.min.js @@ -0,0 +1 @@ +!function(e){var r=/%%?[~:\w]+%?|!\S+!/,t={pattern:/\/[a-z?]+(?=[ :]|$):?|-[a-z]\b|--[a-z-]+\b/im,alias:"attr-name",inside:{punctuation:/:/}},n=/"[^"]*"/,i=/(?:\b|-)\d+\b/;e.languages.batch={comment:[/^::.*/m,{pattern:/((?:^|[&(])[ \t]*)rem\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0}],label:{pattern:/^:.*/m,alias:"property"},command:[{pattern:/((?:^|[&(])[ \t]*)for(?: ?\/[a-z?](?:[ :](?:"[^"]*"|\S+))?)* \S+ in \([^)]+\) do/im,lookbehind:!0,inside:{keyword:/^for\b|\b(?:in|do)\b/i,string:n,parameter:t,variable:r,number:i,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*)if(?: ?\/[a-z?](?:[ :](?:"[^"]*"|\S+))?)* (?:not )?(?:cmdextversion \d+|defined \w+|errorlevel \d+|exist \S+|(?:"[^"]*"|\S+)?(?:==| (?:equ|neq|lss|leq|gtr|geq) )(?:"[^"]*"|\S+))/im,lookbehind:!0,inside:{keyword:/^if\b|\b(?:not|cmdextversion|defined|errorlevel|exist)\b/i,string:n,parameter:t,variable:r,number:i,operator:/\^|==|\b(?:equ|neq|lss|leq|gtr|geq)\b/i}},{pattern:/((?:^|[&()])[ \t]*)else\b/im,lookbehind:!0,inside:{keyword:/^else\b/i}},{pattern:/((?:^|[&(])[ \t]*)set(?: ?\/[a-z](?:[ :](?:"[^"]*"|\S+))?)* (?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^set\b/i,string:n,parameter:t,variable:[r,/\w+(?=(?:[*\/%+\-&^|]|<<|>>)?=)/],number:i,operator:/[*\/%+\-&^|]=?|<<=?|>>=?|[!~_=]/,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*@?)\w+\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^\w+\b/i,string:n,parameter:t,label:{pattern:/(^\s*):\S+/m,lookbehind:!0,alias:"property"},variable:r,number:i,operator:/\^/}}],operator:/[&@]/,punctuation:/[()']/}}(Prism); \ No newline at end of file diff --git a/examples/prism-batch.html b/examples/prism-batch.html new file mode 100644 index 0000000000..5a3ba7e9df --- /dev/null +++ b/examples/prism-batch.html @@ -0,0 +1,20 @@ +
To use this language, use the class "language-batch".
+ +::
+:: Foo bar
+REM This is a comment too
+REM Multi-line ^
+comment
+
+:foobar
+GOTO :EOF
+
+@ECHO OFF
+FOR /l %%a in (5,-1,1) do (TITLE %title% -- closing in %%as)
+SET title=%~n0
+if /i "%InstSize:~0,1%"=="M" set maxcnt=3
+ping -n 2 -w 1 127.0.0.1
\ No newline at end of file
diff --git a/tests/languages/batch/command_feature.test b/tests/languages/batch/command_feature.test
new file mode 100644
index 0000000000..350788a8bd
--- /dev/null
+++ b/tests/languages/batch/command_feature.test
@@ -0,0 +1,103 @@
+FOR /l %%a in (5,-1,1) do (TITLE %title% -- closing in %%as)
+SET title=%~n0
+echo.Hello World
+@ECHO OFF
+if not defined ProgressFormat set "ProgressFormat=[PPPP]"
+EXIT /b
+set /a ProgressCnt+=1
+IF "%~1" NEQ "" (SET %~1=%new%) ELSE (echo.%new%)
+
+----------------------------------------------------
+
+[
+ ["command", [
+ ["keyword", "FOR"],
+ ["parameter", ["/l"]],
+ ["variable", "%%a"],
+ ["keyword", "in"],
+ ["punctuation", "("],
+ ["number", "5"], ["punctuation", ","],
+ ["number", "-1"], ["punctuation", ","],
+ ["number", "1"], ["punctuation", ")"],
+ ["keyword", "do"]
+ ]],
+ ["punctuation", "("],
+ ["command", [
+ ["keyword", "TITLE"],
+ ["variable", "%title%"],
+ " -- closing in ",
+ ["variable", "%%as"]
+ ]],
+ ["punctuation", ")"],
+
+ ["command", [
+ ["keyword", "SET"],
+ ["variable", "title"],
+ ["operator", "="],
+ ["variable", "%~n0"]
+ ]],
+
+ ["command", [
+ ["keyword", "echo"],
+ ".Hello World"
+ ]],
+
+ ["operator", "@"],
+ ["command", [
+ ["keyword", "ECHO"],
+ " OFF"
+ ]],
+
+ ["command", [
+ ["keyword", "if"],
+ ["keyword", "not"],
+ ["keyword", "defined"],
+ " ProgressFormat"
+ ]],
+ ["command", [
+ ["keyword", "set"],
+ ["string", "\"ProgressFormat=[PPPP]\""]
+ ]],
+
+ ["command", [
+ ["keyword", "EXIT"],
+ ["parameter", ["/b"]]
+ ]],
+
+ ["command", [
+ ["keyword", "set"],
+ ["parameter", ["/a"]],
+ ["variable", "ProgressCnt"],
+ ["operator", "+="],
+ ["number", "1"]
+ ]],
+
+ ["command", [
+ ["keyword", "IF"],
+ ["string", "\"%~1\""],
+ ["operator", "NEQ"],
+ ["string", "\"\""]
+ ]],
+ ["punctuation", "("],
+ ["command", [
+ ["keyword", "SET"],
+ ["variable", "%~1"],
+ ["operator", "="],
+ ["variable", "%new%"]
+ ]],
+ ["punctuation", ")"],
+ ["command", [
+ ["keyword", "ELSE"]
+ ]],
+ ["punctuation", "("],
+ ["command", [
+ ["keyword", "echo"],
+ ".",
+ ["variable", "%new%"]
+ ]],
+ ["punctuation", ")"]
+]
+
+----------------------------------------------------
+
+Checks for commands.
\ No newline at end of file
diff --git a/tests/languages/batch/comment_feature.test b/tests/languages/batch/comment_feature.test
new file mode 100644
index 0000000000..83759d8e86
--- /dev/null
+++ b/tests/languages/batch/comment_feature.test
@@ -0,0 +1,18 @@
+::
+:: Foobar
+REM Foobar
+rem foo^
+bar
+
+----------------------------------------------------
+
+[
+ ["comment", "::"],
+ ["comment", ":: Foobar"],
+ ["comment", "REM Foobar"],
+ ["comment", "rem foo^\r\nbar"]
+]
+
+----------------------------------------------------
+
+Checks for comments.
\ No newline at end of file
diff --git a/tests/languages/batch/label_feature.test b/tests/languages/batch/label_feature.test
new file mode 100644
index 0000000000..a672ba0cc3
--- /dev/null
+++ b/tests/languages/batch/label_feature.test
@@ -0,0 +1,13 @@
+:foo
+:Foo_Bar
+
+----------------------------------------------------
+
+[
+ ["label", ":foo"],
+ ["label", ":Foo_Bar"]
+]
+
+----------------------------------------------------
+
+Checks for labels.
\ No newline at end of file