diff --git a/components.js b/components.js index 9130d4f607..b35762e2a4 100644 --- a/components.js +++ b/components.js @@ -127,6 +127,10 @@ var components = { "title": "Eiffel", "owner": "Conaclos" }, + "elixir": { + "title": "elixir", + "owner": "Golmote" + }, "erlang": { "title": "Erlang", "owner": "Golmote" diff --git a/components/prism-elixir.js b/components/prism-elixir.js new file mode 100644 index 0000000000..66268d3818 --- /dev/null +++ b/components/prism-elixir.js @@ -0,0 +1,84 @@ +Prism.languages.elixir = { + // Negative look-ahead is needed for string interpolation + 'comment': /#(?!\{).*/, + // ~r"""foo""", ~r'''foo''', ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r + 'regex': /~[rR](?:("""|'''|[\/|"'])(?:\\.|(?!\1)[^\\])+\1|\((?:\\\)|[^)])+\)|\[(?:\\\]|[^\]])+\]|\{(?:\\\}|[^}])+\}|<(?:\\>|[^>])+>)[uismxfr]*/, + 'string': [ + { + // ~s"""foo""", ~s'''foo''', ~s/foo/, ~s|foo|, ~s"foo", ~s'foo', ~s(foo), ~s[foo], ~s{foo}, ~s + pattern: /~[cCsSwW](?:("""|'''|[\/|"'])(?:\\.|(?!\1)[^\\])+\1|\((?:\\\)|[^)])+\)|\[(?:\\\]|[^\]])+\]|\{(?:\\\}|#\{[^}]+\}|[^}])+\}|<(?:\\>|[^>])+>)[csa]?/, + inside: { + // See interpolation below + } + }, + { + pattern: /("""|''')[\s\S]*?\1/, + inside: { + // See interpolation below + } + }, + { + // Multi-line strings are allowed + pattern: /("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/, + inside: { + // See interpolation below + } + } + ], + 'atom': { + // Look-behind prevents bad highlighting of the :: operator + pattern: /(^|[^:]):\w+/, + lookbehind: true, + alias: 'symbol' + }, + // Look-ahead prevents bad highlighting of the :: operator + 'attr-name': /\w+:(?!:)/, + 'capture': { + // Look-behind prevents bad highlighting of the && operator + pattern: /(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/, + lookbehind: true, + alias: 'function' + }, + 'argument': { + // Look-behind prevents bad highlighting of the && operator + pattern: /(^|[^&])&\d+/, + lookbehind: true, + alias: 'variable' + }, + 'attribute': { + pattern: /@[\S]+/, + alias: 'variable' + }, + 'number': /\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i, + 'keyword': /\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/, + 'boolean': /\b(?:true|false|nil)\b/, + 'operator': [ + /\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/, + { + // We don't want to match << + pattern: /([^<])<(?!<)/, + lookbehind: true + }, + { + // We don't want to match >> + pattern: /([^>])>(?!>)/, + lookbehind: true + } + ], + 'punctuation': /<<|>>|[.,%\[\]{}()]/ +}; + +Prism.languages.elixir.string.forEach(function(o) { + o.inside = { + 'interpolation': { + pattern: /#\{[^}]+\}/, + inside: { + 'delimiter': { + pattern: /^#\{|\}$/, + alias: 'punctuation' + }, + rest: Prism.util.clone(Prism.languages.elixir) + } + } + }; +}); \ No newline at end of file diff --git a/components/prism-elixir.min.js b/components/prism-elixir.min.js new file mode 100644 index 0000000000..4773981ce1 --- /dev/null +++ b/components/prism-elixir.min.js @@ -0,0 +1 @@ +Prism.languages.elixir={comment:/#(?!\{).*/,regex:/~[rR](?:("""|'''|[\/|"'])(?:\\.|(?!\1)[^\\])+\1|\((?:\\\)|[^)])+\)|\[(?:\\\]|[^\]])+\]|\{(?:\\\}|[^}])+\}|<(?:\\>|[^>])+>)[uismxfr]*/,string:[{pattern:/~[cCsSwW](?:("""|'''|[\/|"'])(?:\\.|(?!\1)[^\\])+\1|\((?:\\\)|[^)])+\)|\[(?:\\\]|[^\]])+\]|\{(?:\\\}|#\{[^}]+\}|[^}])+\}|<(?:\\>|[^>])+>)[csa]?/,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,inside:{}},{pattern:/("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},"attr-name":/\w+:(?!:)/,capture:{pattern:/(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/,lookbehind:!0,alias:"function"},argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@[\S]+/,alias:"variable"},number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/,"boolean":/\b(?:true|false|nil)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.elixir.string.forEach(function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.util.clone(Prism.languages.elixir)}}}}); \ No newline at end of file diff --git a/examples/prism-elixir.html b/examples/prism-elixir.html new file mode 100644 index 0000000000..7868f02ed8 --- /dev/null +++ b/examples/prism-elixir.html @@ -0,0 +1,474 @@ +

Elixir

+

To use this language, use the class "language-elixir".

+ +

Comments

+
# This is a comment
+ +

Atoms

+
:foo
+:bar
+ +

Numbers

+
42
+0b1010
+0o777
+0x1F
+3.14159
+5.2e10
+100_000
+ +

Strings and heredoc

+
'A string with \'quotes\'!'
+"A string with \"quotes\"!"
+"Multi-line
+strings are supported"
+""" "Heredoc" strings are
+also supported.
+"""
+ +

Sigils

+
~s"""This is a sigil
+using heredoc delimiters"""
+~r/a [reg]exp/
+~r(another|regexp)
+~w[some words]s
+~c<a char list>
+ +

Interpolation

+
"This is an #{:atom}"
+~s/#{40+2} is the answer/
+ +

Function capturing

+
fun = &Math.zero?/1
+(&is_function/1).(fun)
+fun = &(&1 + 1)
+fun.(1)
+fun = &List.flatten(&1, &2)
+fun.([1, [[2], 3]], [4, 5])
+ +

Module attributes

+
defmodule MyServer do
+  @vsn 2
+end
+
+defmodule Math do
+  @moduledoc """
+  Provides math-related functions.
+
+  ## Examples
+
+      iex> Math.sum(1, 2)
+      3
+
+  """
+
+  @doc """
+  Calculates the sum of two numbers.
+  """
+  def sum(a, b), do: a + b
+end
+ +

Full example

+
# Example from http://learnxinyminutes.com/docs/elixir/
+
+# Single line comments start with a number symbol.
+
+# There's no multi-line comment,
+# but you can stack multiple comments.
+
+# To use the elixir shell use the `iex` command.
+# Compile your modules with the `elixirc` command.
+
+# Both should be in your path if you installed elixir correctly.
+
+## ---------------------------
+## -- Basic types
+## ---------------------------
+
+# There are numbers
+3    # integer
+0x1F # integer
+3.0  # float
+
+# Atoms, that are literals, a constant with name. They start with `:`.
+:hello # atom
+
+# Tuples that are stored contiguously in memory.
+{1,2,3} # tuple
+
+# We can access a tuple element with the `elem` function:
+elem({1, 2, 3}, 0) #=> 1
+
+# Lists that are implemented as linked lists.
+[1,2,3] # list
+
+# We can access the head and tail of a list as follows:
+[head | tail] = [1,2,3]
+head #=> 1
+tail #=> [2,3]
+
+# In elixir, just like in Erlang, the `=` denotes pattern matching and
+# not an assignment.
+#
+# This means that the left-hand side (pattern) is matched against a
+# right-hand side.
+#
+# This is how the above example of accessing the head and tail of a list works.
+
+# A pattern match will error when the sides don't match, in this example
+# the tuples have different sizes.
+# {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
+
+# There are also binaries
+<<1,2,3>> # binary
+
+# Strings and char lists
+"hello" # string
+'hello' # char list
+
+# Multi-line strings
+"""
+I'm a multi-line
+string.
+"""
+#=> "I'm a multi-line\nstring.\n"
+
+# Strings are all encoded in UTF-8:
+"héllò" #=> "héllò"
+
+# Strings are really just binaries, and char lists are just lists.
+<<?a, ?b, ?c>> #=> "abc"
+[?a, ?b, ?c]   #=> 'abc'
+
+# `?a` in elixir returns the ASCII integer for the letter `a`
+?a #=> 97
+
+# To concatenate lists use `++`, for binaries use `<>`
+[1,2,3] ++ [4,5]     #=> [1,2,3,4,5]
+'hello ' ++ 'world'  #=> 'hello world'
+
+<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
+"hello " <> "world"  #=> "hello world"
+
+# Ranges are represented as `start..end` (both inclusive)
+1..10 #=> 1..10
+lower..upper = 1..10 # Can use pattern matching on ranges as well
+[lower, upper] #=> [1, 10]
+
+## ---------------------------
+## -- Operators
+## ---------------------------
+
+# Some math
+1 + 1  #=> 2
+10 - 5 #=> 5
+5 * 2  #=> 10
+10 / 2 #=> 5.0
+
+# In elixir the operator `/` always returns a float.
+
+# To do integer division use `div`
+div(10, 2) #=> 5
+
+# To get the division remainder use `rem`
+rem(10, 3) #=> 1
+
+# There are also boolean operators: `or`, `and` and `not`.
+# These operators expect a boolean as their first argument.
+true and true #=> true
+false or true #=> true
+# 1 and true    #=> ** (ArgumentError) argument error
+
+# Elixir also provides `||`, `&&` and `!` which accept arguments of any type.
+# All values except `false` and `nil` will evaluate to true.
+1 || true  #=> 1
+false && 1 #=> false
+nil && 20  #=> nil
+!true #=> false
+
+# For comparisons we have: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` and `>`
+1 == 1 #=> true
+1 != 1 #=> false
+1 < 2  #=> true
+
+# `===` and `!==` are more strict when comparing integers and floats:
+1 == 1.0  #=> true
+1 === 1.0 #=> false
+
+# We can also compare two different data types:
+1 < :hello #=> true
+
+# The overall sorting order is defined below:
+# number < atom < reference < functions < port < pid < tuple < list < bit string
+
+# To quote Joe Armstrong on this: "The actual order is not important,
+# but that a total ordering is well defined is important."
+
+## ---------------------------
+## -- Control Flow
+## ---------------------------
+
+# `if` expression
+if false do
+  "This will never be seen"
+else
+  "This will"
+end
+
+# There's also `unless`
+unless true do
+  "This will never be seen"
+else
+  "This will"
+end
+
+# Remember pattern matching? Many control-flow structures in elixir rely on it.
+
+# `case` allows us to compare a value against many patterns:
+case {:one, :two} do
+  {:four, :five} ->
+    "This won't match"
+  {:one, x} ->
+    "This will match and bind `x` to `:two`"
+  _ ->
+    "This will match any value"
+end
+
+# It's common to bind the value to `_` if we don't need it.
+# For example, if only the head of a list matters to us:
+[head | _] = [1,2,3]
+head #=> 1
+
+# For better readability we can do the following:
+[head | _tail] = [:a, :b, :c]
+head #=> :a
+
+# `cond` lets us check for many conditions at the same time.
+# Use `cond` instead of nesting many `if` expressions.
+cond do
+  1 + 1 == 3 ->
+    "I will never be seen"
+  2 * 5 == 12 ->
+    "Me neither"
+  1 + 2 == 3 ->
+    "But I will"
+end
+
+# It is common to set the last condition equal to `true`, which will always match.
+cond do
+  1 + 1 == 3 ->
+    "I will never be seen"
+  2 * 5 == 12 ->
+    "Me neither"
+  true ->
+    "But I will (this is essentially an else)"
+end
+
+# `try/catch` is used to catch values that are thrown, it also supports an
+# `after` clause that is invoked whether or not a value is caught.
+try do
+  throw(:hello)
+catch
+  message -> "Got #{message}."
+after
+  IO.puts("I'm the after clause.")
+end
+#=> I'm the after clause
+# "Got :hello"
+
+## ---------------------------
+## -- Modules and Functions
+## ---------------------------
+
+# Anonymous functions (notice the dot)
+square = fn(x) -> x * x end
+square.(5) #=> 25
+
+# They also accept many clauses and guards.
+# Guards let you fine tune pattern matching,
+# they are indicated by the `when` keyword:
+f = fn
+  x, y when x > 0 -> x + y
+  x, y -> x * y
+end
+
+f.(1, 3)  #=> 4
+f.(-1, 3) #=> -3
+
+# Elixir also provides many built-in functions.
+# These are available in the current scope.
+is_number(10)    #=> true
+is_list("hello") #=> false
+elem({1,2,3}, 0) #=> 1
+
+# You can group several functions into a module. Inside a module use `def`
+# to define your functions.
+defmodule Math do
+  def sum(a, b) do
+    a + b
+  end
+
+  def square(x) do
+    x * x
+  end
+end
+
+Math.sum(1, 2)  #=> 3
+Math.square(3) #=> 9
+
+# To compile our simple Math module save it as `math.ex` and use `elixirc`
+# in your terminal: elixirc math.ex
+
+# Inside a module we can define functions with `def` and private functions with `defp`.
+# A function defined with `def` is available to be invoked from other modules,
+# a private function can only be invoked locally.
+defmodule PrivateMath do
+  def sum(a, b) do
+    do_sum(a, b)
+  end
+
+  defp do_sum(a, b) do
+    a + b
+  end
+end
+
+PrivateMath.sum(1, 2)    #=> 3
+# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
+
+# Function declarations also support guards and multiple clauses:
+defmodule Geometry do
+  def area({:rectangle, w, h}) do
+    w * h
+  end
+
+  def area({:circle, r}) when is_number(r) do
+    3.14 * r * r
+  end
+end
+
+Geometry.area({:rectangle, 2, 3}) #=> 6
+Geometry.area({:circle, 3})       #=> 28.25999999999999801048
+# Geometry.area({:circle, "not_a_number"})
+#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
+
+# Due to immutability, recursion is a big part of elixir
+defmodule Recursion do
+  def sum_list([head | tail], acc) do
+    sum_list(tail, acc + head)
+  end
+
+  def sum_list([], acc) do
+    acc
+  end
+end
+
+Recursion.sum_list([1,2,3], 0) #=> 6
+
+# Elixir modules support attributes, there are built-in attributes and you
+# may also add custom ones.
+defmodule MyMod do
+  @moduledoc """
+  This is a built-in attribute on a example module.
+  """
+
+  @my_data 100 # This is a custom attribute.
+  IO.inspect(@my_data) #=> 100
+end
+
+## ---------------------------
+## -- Structs and Exceptions
+## ---------------------------
+
+# Structs are extensions on top of maps that bring default values,
+# compile-time guarantees and polymorphism into Elixir.
+defmodule Person do
+  defstruct name: nil, age: 0, height: 0
+end
+
+joe_info = %Person{ name: "Joe", age: 30, height: 180 }
+#=> %Person{age: 30, height: 180, name: "Joe"}
+
+# Access the value of name
+joe_info.name #=> "Joe"
+
+# Update the value of age
+older_joe_info = %{ joe_info | age: 31 }
+#=> %Person{age: 31, height: 180, name: "Joe"}
+
+# The `try` block with the `rescue` keyword is used to handle exceptions
+try do
+  raise "some error"
+rescue
+  RuntimeError -> "rescued a runtime error"
+  _error -> "this will rescue any error"
+end
+
+# All exceptions have a message
+try do
+  raise "some error"
+rescue
+  x in [RuntimeError] ->
+    x.message
+end
+
+## ---------------------------
+## -- Concurrency
+## ---------------------------
+
+# Elixir relies on the actor model for concurrency. All we need to write
+# concurrent programs in elixir are three primitives: spawning processes,
+# sending messages and receiving messages.
+
+# To start a new process we use the `spawn` function, which takes a function
+# as argument.
+f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
+spawn(f) #=> #PID<0.40.0>
+
+# `spawn` returns a pid (process identifier), you can use this pid to send
+# messages to the process. To do message passing we use the `send` operator.
+# For all of this to be useful we need to be able to receive messages. This is
+# achieved with the `receive` mechanism:
+defmodule Geometry do
+  def area_loop do
+    receive do
+      {:rectangle, w, h} ->
+        IO.puts("Area = #{w * h}")
+        area_loop()
+      {:circle, r} ->
+        IO.puts("Area = #{3.14 * r * r}")
+        area_loop()
+    end
+  end
+end
+
+# Compile the module and create a process that evaluates `area_loop` in the shell
+pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
+
+# Send a message to `pid` that will match a pattern in the receive statement
+send pid, {:rectangle, 2, 3}
+#=> Area = 6
+#   {:rectangle,2,3}
+
+send pid, {:circle, 2}
+#=> Area = 12.56000000000000049738
+#   {:circle,2}
+
+# The shell is also a process, you can use `self` to get the current pid
+self() #=> #PID<0.27.0>
+ +

Known failures

+

There are certain edge cases where Prism will fail. + There are always such cases in every regex-based syntax highlighter. + However, Prism dares to be open and honest about them. + If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. +

+ +

Comments starting with an opening curly brace

+
#{ This is not highlighted properly.
+ +

Comment-like substrings

+
"foo # var"
+ +

String interpolation in single-quoted strings

+
'#{:atom} <- this should not be highligted'
+ diff --git a/plugins/show-language/prism-show-language.js b/plugins/show-language/prism-show-language.js index 449c9e046b..3cf13406a5 100644 --- a/plugins/show-language/prism-show-language.js +++ b/plugins/show-language/prism-show-language.js @@ -5,7 +5,7 @@ if (typeof self === 'undefined' || !self.Prism || !self.document) { } // The languages map is built automatically with gulp -var Languages = /*languages_placeholder[*/{"css":"CSS","clike":"C-like","javascript":"JavaScript","actionscript":"ActionScript","apacheconf":"Apache Configuration","apl":"APL","applescript":"AppleScript","aspnet":"ASP.NET (C#)","autohotkey":"AutoHotkey","csharp":"C#","cpp":"C++","coffeescript":"CoffeeScript","css-extras":"CSS Extras","fsharp":"F#","http":"HTTP","latex":"LaTeX","lolcode":"LOLCODE","matlab":"MATLAB","nasm":"NASM","nsis":"NSIS","objectivec":"Objective-C","php":"PHP","php-extras":"PHP Extras","powershell":"PowerShell","jsx":"React JSX","rest":"reST (reStructuredText)","sas":"SAS","sass":"Sass (Sass)","scss":"Sass (Scss)","sql":"SQL","typescript":"TypeScript","vhdl":"VHDL","wiki":"Wiki markup","yaml":"YAML"}/*]*/; +var Languages = /*languages_placeholder[*/{"css":"CSS","clike":"C-like","javascript":"JavaScript","actionscript":"ActionScript","apacheconf":"Apache Configuration","apl":"APL","applescript":"AppleScript","aspnet":"ASP.NET (C#)","autohotkey":"AutoHotkey","csharp":"C#","cpp":"C++","coffeescript":"CoffeeScript","css-extras":"CSS Extras","elixir":"elixir","fsharp":"F#","http":"HTTP","latex":"LaTeX","lolcode":"LOLCODE","matlab":"MATLAB","nasm":"NASM","nsis":"NSIS","objectivec":"Objective-C","php":"PHP","php-extras":"PHP Extras","powershell":"PowerShell","jsx":"React JSX","rest":"reST (reStructuredText)","sas":"SAS","sass":"Sass (Sass)","scss":"Sass (Scss)","sql":"SQL","typescript":"TypeScript","vhdl":"VHDL","wiki":"Wiki markup","yaml":"YAML"}/*]*/; Prism.hooks.add('before-highlight', function(env) { var pre = env.element.parentNode; if (!pre || !/pre/i.test(pre.nodeName)) { diff --git a/plugins/show-language/prism-show-language.min.js b/plugins/show-language/prism-show-language.min.js index 3b12881eb1..0acf80d673 100644 --- a/plugins/show-language/prism-show-language.min.js +++ b/plugins/show-language/prism-show-language.min.js @@ -1 +1 @@ -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e={css:"CSS",clike:"C-like",javascript:"JavaScript",actionscript:"ActionScript",apacheconf:"Apache Configuration",apl:"APL",applescript:"AppleScript",aspnet:"ASP.NET (C#)",autohotkey:"AutoHotkey",csharp:"C#",cpp:"C++",coffeescript:"CoffeeScript","css-extras":"CSS Extras",fsharp:"F#",http:"HTTP",latex:"LaTeX",lolcode:"LOLCODE",matlab:"MATLAB",nasm:"NASM",nsis:"NSIS",objectivec:"Objective-C",php:"PHP","php-extras":"PHP Extras",powershell:"PowerShell",jsx:"React JSX",rest:"reST (reStructuredText)",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)",sql:"SQL",typescript:"TypeScript",vhdl:"VHDL",wiki:"Wiki markup",yaml:"YAML"};Prism.hooks.add("before-highlight",function(s){var t=s.element.parentNode;if(t&&/pre/i.test(t.nodeName)){var a=e[s.language]||s.language.substring(0,1).toUpperCase()+s.language.substring(1);t.setAttribute("data-language",a)}})}}(); \ No newline at end of file +!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e={css:"CSS",clike:"C-like",javascript:"JavaScript",actionscript:"ActionScript",apacheconf:"Apache Configuration",apl:"APL",applescript:"AppleScript",aspnet:"ASP.NET (C#)",autohotkey:"AutoHotkey",csharp:"C#",cpp:"C++",coffeescript:"CoffeeScript","css-extras":"CSS Extras",elixir:"elixir",fsharp:"F#",http:"HTTP",latex:"LaTeX",lolcode:"LOLCODE",matlab:"MATLAB",nasm:"NASM",nsis:"NSIS",objectivec:"Objective-C",php:"PHP","php-extras":"PHP Extras",powershell:"PowerShell",jsx:"React JSX",rest:"reST (reStructuredText)",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)",sql:"SQL",typescript:"TypeScript",vhdl:"VHDL",wiki:"Wiki markup",yaml:"YAML"};Prism.hooks.add("before-highlight",function(s){var t=s.element.parentNode;if(t&&/pre/i.test(t.nodeName)){var a=e[s.language]||s.language.substring(0,1).toUpperCase()+s.language.substring(1);t.setAttribute("data-language",a)}})}}(); \ No newline at end of file diff --git a/tests/languages/elixir/atom_feature.test b/tests/languages/elixir/atom_feature.test new file mode 100644 index 0000000000..5b1c47d2f1 --- /dev/null +++ b/tests/languages/elixir/atom_feature.test @@ -0,0 +1,15 @@ +:true +:false +:FooBar42 + +---------------------------------------------------- + +[ + ["atom", ":true"], + ["atom", ":false"], + ["atom", ":FooBar42"] +] + +---------------------------------------------------- + +Checks for atoms. \ No newline at end of file diff --git a/tests/languages/elixir/attr-name_feature.test b/tests/languages/elixir/attr-name_feature.test new file mode 100644 index 0000000000..de7cadc898 --- /dev/null +++ b/tests/languages/elixir/attr-name_feature.test @@ -0,0 +1,24 @@ +[a: 1, b: 2] +do: :this, else: :that +where: foo, +select: bar + +---------------------------------------------------- + +[ + ["punctuation", "["], + ["attr-name", "a:"], + ["number", "1"], ["punctuation", ","], + ["attr-name", "b:"], + ["number", "2"], ["punctuation", "]"], + + ["attr-name", "do:"], ["atom", ":this"], + ["punctuation", ","], + ["attr-name", "else:"], ["atom", ":that"], + ["attr-name", "where:"], " foo", ["punctuation", ","], + ["attr-name", "select:"], " bar" +] + +---------------------------------------------------- + +Checks for keyword list keys. \ No newline at end of file diff --git a/tests/languages/elixir/attribute_feature.test b/tests/languages/elixir/attribute_feature.test new file mode 100644 index 0000000000..273c2a402f --- /dev/null +++ b/tests/languages/elixir/attribute_feature.test @@ -0,0 +1,19 @@ +@vsn 2 +@moduledoc """ +foobar +""" +@tag :external + +---------------------------------------------------- + +[ + ["attribute", "@vsn"], ["number", "2"], + ["attribute", "@moduledoc"], ["string", [ + "\"\"\"\r\nfoobar\r\n\"\"\"" + ]], + ["attribute", "@tag"], ["atom", ":external"] +] + +---------------------------------------------------- + +Checks for module attributes. \ No newline at end of file diff --git a/tests/languages/elixir/boolean_feature.test b/tests/languages/elixir/boolean_feature.test new file mode 100644 index 0000000000..aa949797d2 --- /dev/null +++ b/tests/languages/elixir/boolean_feature.test @@ -0,0 +1,15 @@ +true +false +nil + +---------------------------------------------------- + +[ + ["boolean", "true"], + ["boolean", "false"], + ["boolean", "nil"] +] + +---------------------------------------------------- + +Checks for booleans and nil. \ No newline at end of file diff --git a/tests/languages/elixir/capture_feature.test b/tests/languages/elixir/capture_feature.test new file mode 100644 index 0000000000..8a64b66154 --- /dev/null +++ b/tests/languages/elixir/capture_feature.test @@ -0,0 +1,28 @@ +fun = &Math.zero?/1 +(&is_function/1).(fun) +fun = &(&1 + 1) +&List.flatten(&1, &2) + +---------------------------------------------------- + +[ + "fun ", ["operator", "="], + ["capture", "&Math.zero?/1"], + ["punctuation", "("], + ["capture", "&is_function/1"], + ["punctuation", ")"], + ["punctuation", "."], + ["punctuation", "("], "fun", ["punctuation", ")"], + "\r\nfun ", ["operator", "="], + ["capture", "&"], + ["punctuation", "("], ["argument", "&1"], + ["operator", "+"], ["number", "1"], ["punctuation", ")"], + ["capture", "&List.flatten"], + ["punctuation", "("], ["argument", "&1"], + ["punctuation", ","], ["argument", "&2"], + ["punctuation", ")"] +] + +---------------------------------------------------- + +Checks for function capturing and arguments. \ No newline at end of file diff --git a/tests/languages/elixir/comment_feature.test b/tests/languages/elixir/comment_feature.test new file mode 100644 index 0000000000..09493ab581 --- /dev/null +++ b/tests/languages/elixir/comment_feature.test @@ -0,0 +1,13 @@ +# +# Foobar + +---------------------------------------------------- + +[ + ["comment", "#"], + ["comment", "# Foobar"] +] + +---------------------------------------------------- + +Checks for comments. \ No newline at end of file diff --git a/tests/languages/elixir/keyword_feature.test b/tests/languages/elixir/keyword_feature.test new file mode 100644 index 0000000000..e1b02a1ae3 --- /dev/null +++ b/tests/languages/elixir/keyword_feature.test @@ -0,0 +1,31 @@ +after alias and case +catch cond def +defcallback +defexception +defimpl defmodule +defp defprotocol +defstruct do else +end fn for if +import not or +require rescue try +unless use when + +---------------------------------------------------- + +[ + ["keyword", "after"], ["keyword", "alias"], ["keyword", "and"], ["keyword", "case"], + ["keyword", "catch"], ["keyword", "cond"], ["keyword", "def"], + ["keyword", "defcallback"], + ["keyword", "defexception"], + ["keyword", "defimpl"], ["keyword", "defmodule"], + ["keyword", "defp"], ["keyword", "defprotocol"], + ["keyword", "defstruct"], ["keyword", "do"], ["keyword", "else"], + ["keyword", "end"], ["keyword", "fn"], ["keyword", "for"], ["keyword", "if"], + ["keyword", "import"], ["keyword", "not"], ["keyword", "or"], + ["keyword", "require"], ["keyword", "rescue"], ["keyword", "try"], + ["keyword", "unless"], ["keyword", "use"], ["keyword", "when"] +] + +---------------------------------------------------- + +Checks for all keywords. \ No newline at end of file diff --git a/tests/languages/elixir/number_feature.test b/tests/languages/elixir/number_feature.test new file mode 100644 index 0000000000..ae06684b3e --- /dev/null +++ b/tests/languages/elixir/number_feature.test @@ -0,0 +1,27 @@ +0b1111_0000 +0o754_123 +0xBadFace +42 +42_000 +3.14159 +2e6 +3.241_753E-7 +0.7e+15 + +---------------------------------------------------- + +[ + ["number", "0b1111_0000"], + ["number", "0o754_123"], + ["number", "0xBadFace"], + ["number", "42"], + ["number", "42_000"], + ["number", "3.14159"], + ["number", "2e6"], + ["number", "3.241_753E-7"], + ["number", "0.7e+15"] +] + +---------------------------------------------------- + +Checks for binary, octal, hexadecimal and decimal numbers. \ No newline at end of file diff --git a/tests/languages/elixir/operator_feature.test b/tests/languages/elixir/operator_feature.test new file mode 100644 index 0000000000..c97dcce5ef --- /dev/null +++ b/tests/languages/elixir/operator_feature.test @@ -0,0 +1,41 @@ +in +\\ +:: +.. +... ++ ++ +- -- -> +* +/ +^ +& && +| || |> +< <= <> <- +> >= +! != !== += =~ == === => + +---------------------------------------------------- + +[ + ["operator", "in"], + ["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", "=>"] +] + +---------------------------------------------------- + +Checks for all operators. diff --git a/tests/languages/elixir/regex_feature.test b/tests/languages/elixir/regex_feature.test new file mode 100644 index 0000000000..81eb31a651 --- /dev/null +++ b/tests/languages/elixir/regex_feature.test @@ -0,0 +1,29 @@ +~r"""foobar"""im +~R'''foobar'''ux +~r/fo\/obar/smfr +~R|fo\|obar|uismxfr +~r"fo\"obar"x +~R'fo\'obar's +~r(fo\)obar) +~R[fo\]obar] +~r{fo\}obar} +~Robar> + +---------------------------------------------------- + +[ + ["regex", "~r\"\"\"foobar\"\"\"im"], + ["regex", "~R'''foobar'''ux"], + ["regex", "~r/fo\\/obar/smfr"], + ["regex", "~R|fo\\|obar|uismxfr"], + ["regex", "~r\"fo\\\"obar\"x"], + ["regex", "~R'fo\\'obar's"], + ["regex", "~r(fo\\)obar)"], + ["regex", "~R[fo\\]obar]"], + ["regex", "~r{fo\\}obar}"], + ["regex", "~Robar>"] +] + +---------------------------------------------------- + +Checks for regexes. \ No newline at end of file diff --git a/tests/languages/elixir/string_feature.test b/tests/languages/elixir/string_feature.test new file mode 100644 index 0000000000..ca54f4be82 --- /dev/null +++ b/tests/languages/elixir/string_feature.test @@ -0,0 +1,115 @@ +~s/foobar/ +~s/foo#{42}bar/ +~S|foobar| +~c"foobar" +~c"foo#{42}bar" +~C'foobar' +~w(foobar)c +~w(foo#{42}bar)s +~W[foobar]a +~s{foobar} +~s{foo#{42}bar} +~S + +""" +Foo bar +""" + +''' +Foo bar +''' + +~S""" +Foo bar +""" + +~c""" +Foo bar +""" + +~w""" +Foo bar +""" + +"" +"foo" +"fo\"o\ +#{42}bar" +'' +'foo' +'fo\'o\ +bar' + +---------------------------------------------------- + +[ + ["string", ["~s/foobar/"]], + ["string", [ + "~s/foo", + ["interpolation", [ + ["delimiter", "#{"], + ["number", "42"], + ["delimiter", "}"] + ]], + "bar/" + ]], + ["string", ["~S|foobar|"]], + ["string", ["~c\"foobar\""]], + ["string", [ + "~c\"foo", + ["interpolation", [ + ["delimiter", "#{"], + ["number", "42"], + ["delimiter", "}"] + ]], + "bar\"" + ]], + ["string", ["~C'foobar'"]], + ["string", ["~w(foobar)c"]], + ["string", [ + "~w(foo", + ["interpolation", [ + ["delimiter", "#{"], + ["number", "42"], + ["delimiter", "}"] + ]], + "bar)s" + ]], + ["string", ["~W[foobar]a"]], + ["string", ["~s{foobar}"]], + ["string", [ + "~s{foo", + ["interpolation", [ + ["delimiter", "#{"], + ["number", "42"], + ["delimiter", "}"] + ]], + "bar}" + ]], + ["string", ["~S"]], + + ["string", ["\"\"\"\r\nFoo bar\r\n\"\"\""]], + ["string", ["'''\r\nFoo bar\r\n'''"]], + ["string", ["~S\"\"\"\r\nFoo bar\r\n\"\"\""]], + ["string", ["~c\"\"\"\r\nFoo bar\r\n\"\"\""]], + ["string", ["~w\"\"\"\r\nFoo bar\r\n\"\"\""]], + + ["string", ["\"\""]], + ["string", ["\"foo\""]], + ["string", [ + "\"fo\\\"o\\\r\n", + ["interpolation", [ + ["delimiter", "#{"], + ["number", "42"], + ["delimiter", "}"] + ]], + "bar\"" + ]], + ["string", ["''"]], + ["string", ["'foo'"]], + ["string", ["'fo\\'o\\\r\nbar'"]] +] + +---------------------------------------------------- + +Checks for strings. \ No newline at end of file