Current section
Files
Jump to
Current section
Files
lib/cliex_map/builtins.ex
defmodule CliexMap.Builtins do
use CliexMap.Types
alias CliexMap.Context
@moduledoc ~S"""
Built in functions which can be called in pattern modfifers `(reverse)(downcase)`
"""
@spec _add(Context.t, list(integer())) :: integer()
def _add(_context, numbers) do
numbers
|> Enum.reduce(0, fn n, result -> n + result end)
end
@spec _div(Context.t, list(integer())) :: integer()
def _div(_context, [head|numbers]) do
numbers
|> Enum.reduce(head, fn n, result -> result / n end)
end
@spec _idiv(Context.t, list(integer())) :: integer()
def _idiv(_context, [head|numbers]) do
numbers
|> Enum.reduce(head, fn n, result -> div(result, n) end)
end
@spec _mul(Context.t, list(integer())) :: integer()
def _mul(_context, numbers) do
numbers
|> Enum.reduce(1, fn n, result -> n * result end)
end
@spec _sub(Context.t, list(integer())) :: integer()
def _sub(_context, [head|numbers]) do
numbers
|> Enum.reduce(head, fn n, result -> result - n end)
end
@spec abs(Context.t, list(integer())) :: integer()
def abs(_context, [n]), do: abs(n)
@spec at(Context.t, list()) :: any()
def at(_context, [list, n]), do: list |> Enum.at(n)
def at(_context, [list, n, default]), do: list |> Enum.at(n, default)
@spec downcase(Context.t, list()) :: binary()
def downcase(_context, args), do: args |> Enum.map(&String.downcase/1) |> Enum.join
@extension_rgx ~r{\.([^.]*)\z}
@spec ext(Context.t, list()) :: binary()
def ext(_context, args) do
case args do
[fname] -> _get_ext(fname)
[fname, ext] -> Regex.replace(@extension_rgx, fname, "#{ext}")
end
end
@spec join(Context.t, list()) :: binary()
def join(_context, args) do
apply(Enum, :join, args)
end
@spec lpad(Context.t, list()) :: binary()
def lpad(_context, args) do
case args do
[subj, len] -> String.pad_leading(to_string(subj), len)
[subj, len, wth] -> String.pad_leading(to_string(subj), len, to_string(wth))
end
end
@spec reverse(Context.t, list()) :: binary()
def reverse(_context, args), do: args |> Enum.map(&String.reverse/1) |> Enum.join
@spec revlist(Context.t, list()) :: list()
def revlist(_context, [list]), do: Enum.reverse(list)
@spec rnd(Context.t, list()) :: binary()
def rnd(_context, args) do
case args do
[_, max] -> max |> _rnd(0)
[_, max, padsize] -> max |> _rnd(padsize)
end
end
@spec rpad(Context.t, list()) :: binary()
def rpad(_context, args) do
case args do
[subj, len] -> String.pad_trailing(to_string(subj), len)
[subj, len, wth] -> String.pad_trailing(to_string(subj), len, to_string(wth))
end
end
@spec segment(Context.t, list()) :: binary()
def segment(context, args)
def segment(_context, [path]) do
path
|> String.split("/")
|> Enum.reverse
|> Enum.drop(1)
|> Enum.reverse
|> Enum.join("/")
end
def segment(_context, [path, index]) do
path
|> String.split("/")
|> _slice(index, index)
|> List.first
end
@spec segments(Context.t, list()) :: binary()
def segments(_context, [subject|args]) do
segs = String.split(subject, "/")
case args do
[start] -> _slice(segs, start, -1)
[start, stop] -> _slice(segs, start, stop)
end
|> Enum.join("/")
end
@spec slice(Context.t, list()|binary()) :: list()
def slice(_context, args) do
case args do
[list, index] -> _slice(list, index, -1)
[list, index, end_index] -> _slice(list, index, end_index)
end
end
@spec splice_join(Context.t, list()) :: binary()
def splice_join(_context, args) do
with [subject, sep | rest] <- args do
splitted = String.split(subject, sep)
case rest do
[start] -> _slice_join(splitted, start, -1, sep)
[start, stop] -> _slice_join(splitted, start, stop, sep)
[start, stop, joiner] -> _slice_join(splitted, start, stop, joiner)
end
end
end
@spec splicej(Context.t, list()) :: binary()
defdelegate splicej(context, args), to: __MODULE__, as: :splice_join
@spec split(Context.t, list()) :: list()
def split(_context, args), do: apply(String, :split, args)
@spec sub(maybe(Context.t), list()) :: binary()
def sub(context, args)
def sub(_context, [subject, pattern]), do: sub(nil, [subject, pattern, ""])
def sub(_context, [subject, pattern, replacement]), do: String.replace(subject, pattern, replacement)
@spec upcase(Context.t, list()) :: binary()
def upcase(_context, args), do: args |> Enum.map(&String.upcase/1) |> Enum.join
@spec to_s(Context.t, list()) :: binary()
def to_s(_context, args) do
case args do
[subj] -> Integer.to_string(subj)
[subj, base] -> Integer.to_string(subj, base)
end
|> String.downcase
end
@spec _get_ext(binary()) :: binary()
defp _get_ext(fname) do
case Regex.run(@extension_rgx, fname) do
[_, ext] -> ext
_ -> ""
end
end
@spec _rnd(non_neg_integer(), non_neg_integer()) :: binary()
defp _rnd(max, padsize) do
max
|> :rand.uniform
|> to_string()
|> String.pad_leading(padsize, "0")
end
@spec _slice(list()|binary(), integer(), integer()) :: list()
defp _slice(list, sidx, eidx)
defp _slice(list, sidx, eidx) when is_list(list) do
l = Enum.count(list)
e = if sidx < 0 do
if eidx < 0 do
eidx - sidx + 1
else
eidx - (l + sidx) + 1
end
else
if eidx < 0 do
(l + eidx) - sidx + 1
else
eidx - sidx + 1
end
end
Enum.slice(list, sidx, e)
end
defp _slice(string, sidx, eidx) when is_binary(string) do
l = String.length(string)
e = if sidx < 0 do
if eidx < 0 do
eidx - sidx + 1
else
eidx - (l + sidx) + 1
end
else
if eidx < 0 do
(l + eidx) - sidx + 1
else
eidx - sidx + 1
end
end
String.slice(string, sidx, max(e, 0))
end
@spec _slice_join(list(), integer(), integer(), binary()) :: binary()
defp _slice_join(list, start, stop, joiner) do
list
|> _slice(start, stop)
|> Enum.join(joiner)
end
end
# SPDX-License-Identifier: Apache-2.0