( ...
+ pattern: /\w+\s*<\w+>(?=\()/,
+ inside: {
+ 'function': /^\w+/,
+ 'generic': {
+ pattern: /<\w+>/,
+ inside: Prism.languages.v.generic.inside
+ }
+ }
+ }
+ });
+})(Prism);
\ No newline at end of file
diff --git a/components/prism-v.min.js b/components/prism-v.min.js
new file mode 100644
index 0000000000..0c6b4d52cf
--- /dev/null
+++ b/components/prism-v.min.js
@@ -0,0 +1 @@
+!function(e){var n={pattern:/[\s\S]+/,inside:null};e.languages.v=e.languages.extend("clike",{string:[{pattern:/`(?:\\\`|\\?[^\`]{1,2})`/,alias:"rune"},{pattern:/r?(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,alias:"quoted-string",greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\{[^{}]*\}|\w+(?:\.\w+(?:\([^\(\)]*\))?|\[[^\[\]]+\])*)/,lookbehind:!0,inside:{"interpolation-variable":{pattern:/^\$\w[\s\S]*$/,alias:"variable"},"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},"interpolation-expression":n}}}}],"class-name":{pattern:/(\b(?:enum|interface|struct|type)\s+)(?:C\.)?[\w]+/,lookbehind:!0},keyword:/(?:\b(?:as|asm|assert|atomic|break|chan|const|continue|defer|else|embed|enum|fn|for|__global|go(?:to)?|if|import|in|interface|is|lock|match|module|mut|none|or|pub|return|rlock|select|shared|sizeof|static|struct|type(?:of)?|union|unsafe)|\$(?:if|else|for)|#(?:include|flag))\b/,number:/\b(?:0x[a-f\d]+(?:_[a-f\d]+)*|0b[01]+(?:_[01]+)*|0o[0-7]+(?:_[0-7]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?)\b/i,operator:/~|\?|[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\.?/,builtin:/\b(?:any(?:_int|_float)?|bool|byte(?:ptr)?|charptr|f(?:32|64)|i(?:8|16|nt|64|128)|rune|size_t|string|u(?:16|32|64|128)|voidptr)\b/}),n.inside=e.languages.v,e.languages.insertBefore("v","operator",{attribute:{pattern:/^\s*\[(?:deprecated|unsafe_fn|typedef|live|inline|flag|ref_only|windows_stdcall|direct_array_access)\]/m,alias:"annotation",inside:{punctuation:/[\[\]]/,keyword:/\w+/}},generic:{pattern:/\<\w+\>(?=\s*[\)\{])/,inside:{punctuation:/[<>]/,"class-name":/\w+/}}}),e.languages.insertBefore("v","function",{"generic-function":{pattern:/\w+\s*<\w+>(?=\()/,inside:{function:/^\w+/,generic:{pattern:/<\w+>/,inside:e.languages.v.generic.inside}}}})}(Prism);
\ No newline at end of file
diff --git a/examples/prism-v.html b/examples/prism-v.html
new file mode 100644
index 0000000000..1ddb018263
--- /dev/null
+++ b/examples/prism-v.html
@@ -0,0 +1,91 @@
+Comments
+// This is a comment
+/* This is a comment
+on multiple lines */
+
+Numbers
+123
+0x7B
+0b01111011
+0o173
+170141183460469231731687303715884105727
+1_000_000
+0b0_11
+3_122.55
+0xF_F
+0o17_3
+72.40
+072.40
+2.71828
+
+
+Runes and strings
+'\t'
+'\000'
+'\x07'
+'\u12e4'
+'\U00101234'
+`abc`
+`multi-line
+string`
+"Hello, world!"
+"multi-line
+string"
+
+String interpolation
+'Hello, $name!'
+"age = $user.age"
+'can register = ${user.age > 13}'
+'x = ${x:4.2f}'
+'[${x:10}]'
+'[${int(x):-10}]'
+
+
+Struct
+struct Foo {
+ a int // private immutable (default)
+mut:
+ b int // private mutable
+ c int // (you can list multiple fields with the same access modifier)
+pub:
+ d int // public immutable (readonly)
+pub mut:
+ e int // public, but mutable only in parent module
+__global:
+ f int // public and mutable both inside and outside parent module
+} // (not recommended to use, that's why the 'global' keyword
+ // starts with __)
+
+
+Functions
+func(a, b int, z float64) bool { return a*b < int(z) }
+
+Full example
+
+module mymodule
+
+import external_module
+
+fn sqr(n int) int {
+ return n * n
+}
+
+fn run(value int, op fn (int) int) int {
+ return op(value)
+}
+
+fn main() {
+ println(run(5, sqr)) // "25"
+ // Anonymous functions can be declared inside other functions:
+ double_fn := fn (n int) int {
+ return n + n
+ }
+ println(run(5, double_fn)) // "10"
+ // Functions can be passed around without assigning them to variables:
+ res := run(5, fn (n int) int {
+ return n + n
+ })
+
+ external_module.say_hi()
+}
+
diff --git a/plugins/autoloader/prism-autoloader.js b/plugins/autoloader/prism-autoloader.js
index 48b90c390f..c90ee6b3ba 100644
--- a/plugins/autoloader/prism-autoloader.js
+++ b/plugins/autoloader/prism-autoloader.js
@@ -141,6 +141,7 @@
"textile": "markup",
"twig": "markup",
"typescript": "javascript",
+ "v": "clike",
"vala": "clike",
"vbnet": "basic",
"velocity": "markup",
diff --git a/plugins/autoloader/prism-autoloader.min.js b/plugins/autoloader/prism-autoloader.min.js
index dd5b4113ce..1012adf6c5 100644
--- a/plugins/autoloader/prism-autoloader.min.js
+++ b/plugins/autoloader/prism-autoloader.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&document.createElement){var l={javascript:"clike",actionscript:"javascript",apex:["clike","sql"],arduino:"cpp",aspnet:["markup","csharp"],birb:"clike",bison:"c",c:"clike",csharp:"clike",cpp:"c",coffeescript:"javascript",crystal:"ruby","css-extras":"css",d:"clike",dart:"clike",django:"markup-templating",ejs:["javascript","markup-templating"],etlua:["lua","markup-templating"],erb:["ruby","markup-templating"],fsharp:"clike","firestore-security-rules":"clike",flow:"javascript",ftl:"markup-templating",gml:"clike",glsl:"c",go:"clike",groovy:"clike",haml:"ruby",handlebars:"markup-templating",haxe:"clike",hlsl:"c",java:"clike",javadoc:["markup","java","javadoclike"],jolie:"clike",jsdoc:["javascript","javadoclike","typescript"],"js-extras":"javascript",json5:"json",jsonp:"json","js-templates":"javascript",kotlin:"clike",latte:["clike","markup-templating","php"],less:"css",lilypond:"scheme",markdown:"markup","markup-templating":"markup",mongodb:"javascript",n4js:"javascript",nginx:"clike",objectivec:"c",opencl:"c",parser:"markup",php:"markup-templating",phpdoc:["php","javadoclike"],"php-extras":"php",plsql:"sql",processing:"clike",protobuf:"clike",pug:["markup","javascript"],purebasic:"clike",purescript:"haskell",qml:"javascript",qore:"clike",racket:"scheme",jsx:["markup","javascript"],tsx:["jsx","typescript"],reason:"clike",ruby:"clike",sass:"css",scss:"css",scala:"java","shell-session":"bash",smarty:"markup-templating",solidity:"clike",soy:"markup-templating",sparql:"turtle",sqf:"clike",swift:"clike","t4-cs":["t4-templating","csharp"],"t4-vb":["t4-templating","vbnet"],tap:"yaml",tt2:["clike","markup-templating"],textile:"markup",twig:"markup",typescript:"javascript",vala:"clike",vbnet:"basic",velocity:"markup",wiki:"markup",xeora:"markup","xml-doc":"markup",xquery:"markup"},n={html:"markup",xml:"markup",svg:"markup",mathml:"markup",ssml:"markup",atom:"markup",rss:"markup",js:"javascript",g4:"antlr4",adoc:"asciidoc",shell:"bash",shortcode:"bbcode",rbnf:"bnf",oscript:"bsl",cs:"csharp",dotnet:"csharp",coffee:"coffeescript",conc:"concurnas",jinja2:"django","dns-zone":"dns-zone-file",dockerfile:"docker",eta:"ejs",xlsx:"excel-formula",xls:"excel-formula",gamemakerlanguage:"gml",hs:"haskell",gitignore:"ignore",hgignore:"ignore",npmignore:"ignore",webmanifest:"json",kt:"kotlin",kts:"kotlin",tex:"latex",context:"latex",ly:"lilypond",emacs:"lisp",elisp:"lisp","emacs-lisp":"lisp",md:"markdown",moon:"moonscript",n4jsd:"n4js",nani:"naniscript",objc:"objectivec",objectpascal:"pascal",px:"pcaxis",pcode:"peoplecode",pq:"powerquery",mscript:"powerquery",pbfasm:"purebasic",purs:"purescript",py:"python",rkt:"racket",rpy:"renpy",robot:"robotframework",rb:"ruby","sh-session":"shell-session",shellsession:"shell-session",smlnj:"sml",sol:"solidity",sln:"solution-file",rq:"sparql",t4:"t4-cs",trig:"turtle",ts:"typescript",tsconfig:"typoscript",uscript:"unrealscript",uc:"unrealscript",vb:"visual-basic",vba:"visual-basic",xeoracube:"xeora",yml:"yaml"},p={},e="components/",a=Prism.util.currentScript();if(a){var r=/\bplugins\/autoloader\/prism-autoloader\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i,s=/(^|\/)[\w-]+\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i,t=a.getAttribute("data-autoloader-path");if(null!=t)e=t.trim().replace(/\/?$/,"/");else{var i=a.src;r.test(i)?e=i.replace(r,"components/"):s.test(i)&&(e=i.replace(s,"$1components/"))}}var o=Prism.plugins.autoloader={languages_path:e,use_minified:!0,loadLanguages:m};Prism.hooks.add("complete",function(e){var a=e.element,r=e.language;if(a&&r&&"none"!==r){var s=function(e){var a=(e.getAttribute("data-dependencies")||"").trim();if(!a){var r=e.parentElement;r&&"pre"===r.tagName.toLowerCase()&&(a=(r.getAttribute("data-dependencies")||"").trim())}return a?a.split(/\s*,\s*/g):[]}(a);/^diff-./i.test(r)?(s.push("diff"),s.push(r.substr("diff-".length))):s.push(r),s.every(u)||m(s,function(){Prism.highlightElement(a)})}})}function u(e){if(0<=e.indexOf("!"))return!1;if((e=n[e]||e)in Prism.languages)return!0;var a=p[e];return a&&!a.error&&!1===a.loading}function m(e,a,r){"string"==typeof e&&(e=[e]);var s=e.length,t=0,i=!1;function c(){i||++t===s&&a&&a(e)}0!==s?e.forEach(function(e){!function(a,r,s){var t=0<=a.indexOf("!");function e(){var e=p[a];e||(e=p[a]={callbacks:[]}),e.callbacks.push({success:r,error:s}),!t&&u(a)?k(a,"success"):!t&&e.error?k(a,"error"):!t&&e.loading||(e.loading=!0,e.error=!1,function(e,a,r){var s=document.createElement("script");s.src=e,s.async=!0,s.onload=function(){document.body.removeChild(s),a&&a()},s.onerror=function(){document.body.removeChild(s),r&&r()},document.body.appendChild(s)}(function(e){return o.languages_path+"prism-"+e+(o.use_minified?".min":"")+".js"}(a),function(){e.loading=!1,k(a,"success")},function(){e.loading=!1,e.error=!0,k(a,"error")}))}a=a.replace("!",""),a=n[a]||a;var i=l[a];i&&i.length?m(i,e,s):e()}(e,c,function(){i||(i=!0,r&&r(e))})}):a&&setTimeout(a,0)}function k(e,a){if(p[e]){for(var r=p[e].callbacks,s=0,t=r.length;s { }
+
+----------------------------------------------------
+
+[
+ ["keyword", "struct"],
+ ["class-name", "Abc"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "type"],
+ ["class-name", "Alphabet"],
+ ["operator", "="],
+ " Abc ",
+ ["operator", "|"],
+ " Xyz\r\n",
+
+ ["keyword", "enum"],
+ ["class-name", "Token"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "interface"],
+ ["class-name", "Speaker"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "struct"],
+ ["class-name", "Repo"],
+ ["generic", [
+ ["punctuation", "<"],
+ ["class-name", "T"],
+ ["punctuation", ">"]
+ ]],
+ ["punctuation", "{"],
+ ["punctuation", "}"]
+]
\ No newline at end of file
diff --git a/tests/languages/v/function_feature.test b/tests/languages/v/function_feature.test
new file mode 100644
index 0000000000..41e1749c30
--- /dev/null
+++ b/tests/languages/v/function_feature.test
@@ -0,0 +1,120 @@
+fn init() { }
+fn add(x int, y int) int { }
+fn sum(a ...int) int { }
+fn (mut t MyTime) century() int { }
+fn (d Dog) speak() string { }
+fn (r Repo) find_user_by_id(id int) ?User { }
+fn new_repo(db DB) Repo { }
+fn (r Repo) find_by_id(id int) ?T { }
+
+----------------------------------------------------
+
+[
+ ["keyword", "fn"],
+ ["function", "init"],
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "fn"],
+ ["function", "add"],
+ ["punctuation", "("],
+ "x ",
+ ["builtin", "int"],
+ ["punctuation", ","],
+ " y ",
+ ["builtin", "int"],
+ ["punctuation", ")"],
+ ["builtin", "int"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "fn"],
+ ["function", "sum"],
+ ["punctuation", "("],
+ "a ",
+ ["operator", "..."],
+ ["builtin", "int"],
+ ["punctuation", ")"],
+ ["builtin", "int"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "fn"],
+ ["punctuation", "("],
+ ["keyword", "mut"],
+ " t MyTime",
+ ["punctuation", ")"],
+ ["function", "century"],
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["builtin", "int"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "fn"],
+ ["punctuation", "("],
+ "d Dog",
+ ["punctuation", ")"],
+ ["function", "speak"],
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["builtin", "string"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "fn"],
+ ["punctuation", "("],
+ "r Repo",
+ ["punctuation", ")"],
+ ["function", "find_user_by_id"],
+ ["punctuation", "("],
+ "id ",
+ ["builtin", "int"],
+ ["punctuation", ")"],
+ ["operator", "?"],
+ "User ",
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "fn"],
+ ["generic-function", [
+ ["function", "new_repo"],
+ ["generic", [
+ ["punctuation", "<"],
+ ["class-name", "T"],
+ ["punctuation", ">"]
+ ]]
+ ]],
+ ["punctuation", "("],
+ "db DB",
+ ["punctuation", ")"],
+ " Repo",
+ ["generic", [
+ ["punctuation", "<"],
+ ["class-name", "T"],
+ ["punctuation", ">"]
+ ]],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "fn"],
+ ["punctuation", "("],
+ "r Repo",
+ ["generic", [
+ ["punctuation", "<"],
+ ["class-name", "T"],
+ ["punctuation", ">"]
+ ]],
+ ["punctuation", ")"],
+ ["function", "find_by_id"],
+ ["punctuation", "("],
+ "id ",
+ ["builtin", "int"],
+ ["punctuation", ")"],
+ ["operator", "?"],
+ "T ",
+ ["punctuation", "{"],
+ ["punctuation", "}"]
+]
\ No newline at end of file
diff --git a/tests/languages/v/keyword_feature.test b/tests/languages/v/keyword_feature.test
new file mode 100644
index 0000000000..279ed0d8da
--- /dev/null
+++ b/tests/languages/v/keyword_feature.test
@@ -0,0 +1,93 @@
+as;
+asm;
+assert;
+atomic;
+break;
+const;
+continue;
+defer;
+else;
+embed;
+enum;;
+fn;
+for;
+__global;
+go;
+goto;
+if;
+import;
+in;
+interface;
+is;
+lock;
+match;
+module;
+mut;
+none;
+or;
+pub;
+return;
+rlock;
+select;
+shared;
+sizeof;
+static;
+struct;
+type;;
+typeof;
+union;
+unsafe;
+$if;
+$else;
+$for;
+#include;
+#flag;
+
+----------------------------------------------------
+
+[
+ ["keyword", "as"], ["punctuation", ";"],
+ ["keyword", "asm"], ["punctuation", ";"],
+ ["keyword", "assert"], ["punctuation", ";"],
+ ["keyword", "atomic"], ["punctuation", ";"],
+ ["keyword", "break"], ["punctuation", ";"],
+ ["keyword", "const"], ["punctuation", ";"],
+ ["keyword", "continue"], ["punctuation", ";"],
+ ["keyword", "defer"], ["punctuation", ";"],
+ ["keyword", "else"], ["punctuation", ";"],
+ ["keyword", "embed"], ["punctuation", ";"],
+ ["keyword", "enum"], ["punctuation", ";"], ["punctuation", ";"],
+ ["keyword", "fn"], ["punctuation", ";"],
+ ["keyword", "for"], ["punctuation", ";"],
+ ["keyword", "__global"], ["punctuation", ";"],
+ ["keyword", "go"], ["punctuation", ";"],
+ ["keyword", "goto"], ["punctuation", ";"],
+ ["keyword", "if"], ["punctuation", ";"],
+ ["keyword", "import"], ["punctuation", ";"],
+ ["keyword", "in"], ["punctuation", ";"],
+ ["keyword", "interface"], ["punctuation", ";"],
+ ["keyword", "is"], ["punctuation", ";"],
+ ["keyword", "lock"], ["punctuation", ";"],
+ ["keyword", "match"], ["punctuation", ";"],
+ ["keyword", "module"], ["punctuation", ";"],
+ ["keyword", "mut"], ["punctuation", ";"],
+ ["keyword", "none"], ["punctuation", ";"],
+ ["keyword", "or"], ["punctuation", ";"],
+ ["keyword", "pub"], ["punctuation", ";"],
+ ["keyword", "return"], ["punctuation", ";"],
+ ["keyword", "rlock"], ["punctuation", ";"],
+ ["keyword", "select"], ["punctuation", ";"],
+ ["keyword", "shared"], ["punctuation", ";"],
+ ["keyword", "sizeof"], ["punctuation", ";"],
+ ["keyword", "static"], ["punctuation", ";"],
+ ["keyword", "struct"], ["punctuation", ";"],
+ ["keyword", "type"], ["punctuation", ";"], ["punctuation", ";"],
+ ["keyword", "typeof"], ["punctuation", ";"],
+ ["keyword", "union"], ["punctuation", ";"],
+ ["keyword", "unsafe"], ["punctuation", ";"],
+ ["keyword", "$if"], ["punctuation", ";"],
+ ["keyword", "$else"], ["punctuation", ";"],
+ ["keyword", "$for"], ["punctuation", ";"],
+ ["keyword", "#include"], ["punctuation", ";"],
+ ["keyword", "#flag"], ["punctuation", ";"]
+]
\ No newline at end of file
diff --git a/tests/languages/v/number_feature.test b/tests/languages/v/number_feature.test
new file mode 100644
index 0000000000..06820c7115
--- /dev/null
+++ b/tests/languages/v/number_feature.test
@@ -0,0 +1,25 @@
+123
+0x7B
+0b01111011
+0o173
+1_000_000
+0xF_F
+072.40
+2.71828
+
+----------------------------------------------------
+
+[
+ ["number", "123"],
+ ["number", "0x7B"],
+ ["number", "0b01111011"],
+ ["number", "0o173"],
+ ["number", "1_000_000"],
+ ["number", "0xF_F"],
+ ["number", "072.40"],
+ ["number", "2.71828"]
+]
+
+----------------------------------------------------
+
+Check for numbers
\ No newline at end of file
diff --git a/tests/languages/v/operator_feature.test b/tests/languages/v/operator_feature.test
new file mode 100644
index 0000000000..f7744026cb
--- /dev/null
+++ b/tests/languages/v/operator_feature.test
@@ -0,0 +1,67 @@
++
+-
+*
+/
+%
+~
+&
+|
+^
+!
+&&
+||
+!=
+<<
+>>
+==
+<
+<=
+>
+>=
++=
+-=
+*=
+/=
+%=
+&=
+|=
+^=
+>>=
+<<=
+:=
+
+----------------------------------------------------
+
+[
+ ["operator", "+"],
+ ["operator", "-"],
+ ["operator", "*"],
+ ["operator", "/"],
+ ["operator", "%"],
+ ["operator", "~"],
+ ["operator", "&"],
+ ["operator", "|"],
+ ["operator", "^"],
+ ["operator", "!"],
+ ["operator", "&&"],
+ ["operator", "||"],
+ ["operator", "!="],
+ ["operator", "<<"],
+ ["operator", ">>"],
+ ["operator", "=="],
+ ["operator", "<"],
+ ["operator", "<="],
+ ["operator", ">"],
+ ["operator", ">="],
+ ["operator", "+="],
+ ["operator", "-="],
+ ["operator", "*="],
+ ["operator", "/="],
+ ["operator", "%="],
+ ["operator", "&="],
+ ["operator", "|="],
+ ["operator", "^="],
+ ["operator", ">>="],
+ ["operator", "<<="],
+ ["operator", ":="]
+]
\ No newline at end of file
diff --git a/tests/languages/v/string_feature.test b/tests/languages/v/string_feature.test
new file mode 100644
index 0000000000..3040a7fc0d
--- /dev/null
+++ b/tests/languages/v/string_feature.test
@@ -0,0 +1,47 @@
+"https://example.com"
+'single quote'
+'age = $user.age'
+'[${int(x):-10}]'
+r'hello\nworld'
+`🚀`
+`\``
+`Not a Rune`
+
+----------------------------------------------------
+
+[
+ ["string", ["\"https://example.com\""]],
+ ["string", ["'single quote'"]],
+ ["string", [
+ "'age = ",
+ ["interpolation", [
+ ["interpolation-variable", "$user.age"]
+ ]],
+ "'"
+ ]],
+ ["string", [
+ "'[",
+ ["interpolation", [
+ ["interpolation-punctuation", "${"],
+ ["interpolation-expression", [
+ ["function", "int"],
+ ["punctuation", "("],
+ "x",
+ ["punctuation", ")"],
+ ["punctuation", ":"],
+ ["operator", "-"],
+ ["number", "10"]
+ ]],
+ ["interpolation-punctuation", "}"]
+ ]],
+ "]'"
+ ]],
+ ["string", ["r'hello\\nworld'"]],
+ ["string", "`🚀`"],
+ ["string", "`\\``"],
+ "\r\n`Not a Rune`"
+]
+
+----------------------------------------------------
+
+Check for strings and string interpolation
\ No newline at end of file