defmodule RustledSyntect do alias RustledSyntect.Nif @doc ~S''' Creates a new syntax set with the default languages and all language files at the path specified. This can be used to load additional syntax definitions not included in the default Syntect release. iex> RustledSyntect.new_syntax_set([:code.priv_dir(:rustled_syntect), "packages"] |> Path.join) ''' @spec new_syntax_set(String.Chars.t()) :: Reference def new_syntax_set(extra_syntaxes_path) when is_binary(extra_syntaxes_path) do Nif.new_syntax_set(extra_syntaxes_path) end @spec hilite_stream(Enumerable.t(), [{:lang, String.Chars.t()}]) :: Enumerable.t() def hilite_stream(stream, lang: lang) do hilite_stream(stream, lang: lang, syntax_set: RustledSyntect.Nif.new_syntax_set()) end @doc ~S''' Syntax hilight an enumerable/stream of lines producing an iolist. iex> Enum.join(RustledSyntect.hilite_stream(["(0..69).each do |x|", " puts x", "end"], lang: "Ruby"), "") <> "\n" """ (0..69).each do |x| puts x end """ iex> Enum.into(RustledSyntect.hilite_stream(["(0..69).each do |x|", " puts x", "end"], lang: "Ruby"), []) [ "(0..69).each do |x|", "\n", " puts x", "\n", "end", [""] ] You may optionally specify a folder of syntax sets to be added to the default set. # Assuming the priv/packages directory includes an Elixir.sublime-syntax syntax set: iex> ss = RustledSyntect.new_syntax_set([:code.priv_dir(:rustled_syntect), "packages"] |> Path.join) iex> RustledSyntect.hilite_stream(["defmodule Foo do", "end"], lang: "Elixir", syntax_set: ss) |> Enum.into([]) [ "defmodule Foo do", "\n", "end", [""] ] ''' @spec hilite_stream(Enumerable.t(), [{:lang, String.Chars.t(), syntax_set: Reference}]) :: Enumerable.t() def hilite_stream(stream, lang: lang, syntax_set: ss) do hl = Nif.new_highlighter(ss, lang) stream |> Stream.map(fn line -> Nif.highlight_line(hl, line) end) |> Stream.intersperse("\n") |> Stream.concat( Stream.unfold(true, fn true -> {Nif.finalize(hl), false} false -> nil end) ) end def supported_langs, do: Nif.langs() end