Packages

plymio_codi: Generating Quoted Forms for Common Code Patterns

Current section

Files

Jump to
plymio_codi lib codi utility getset.ex
Raw

lib/codi/utility/getset.ex

defmodule Plymio.Codi.Utility.GetSet do
@moduledoc false
require Plymio.Fontais.Option.Macro, as: PFOM
require Plymio.Fontais.Option, as: POU
use Plymio.Fontais.Attribute
use Plymio.Codi.Attribute
# cpo = codi pattern opts
import Plymio.Fontais.Guard,
only: [
is_value_unset: 1,
is_value_unset_or_nil: 1
]
import Plymio.Codi.Error,
only: [
new_error_result: 1
]
import Plymio.Fontais.Form,
only: [
opts_forms_normalise: 2,
opts_forms_reduce: 2
]
import Plymio.Fontais.Option,
only: [
opts_normalise: 1,
opts_validate: 1,
opts_get: 3,
opts_put: 3,
opts_fetch: 2,
opts_drop: 2
]
@type error :: Plymio.Codi.error()
@plymio_codi_cpo_kvs_aliases [
{@plymio_codi_key_pattern, nil},
{@plymio_codi_key_status, nil},
{@plymio_codi_key_form, nil},
{@plymio_codi_key_since, nil},
{@plymio_codi_key_fun_module, nil},
{@plymio_codi_key_fun_name, nil},
{@plymio_codi_key_fun_args, nil},
{@plymio_codi_key_fun_sig, nil},
{@plymio_codi_key_fun_arity, nil},
{@plymio_codi_key_fun_doc, nil},
{@plymio_codi_key_fun_default, nil},
{@plymio_codi_key_bang_module, nil},
{@plymio_codi_key_bang_name, nil},
{@plymio_codi_key_bang_doc, nil},
{@plymio_codi_key_bang_arity, nil},
{@plymio_codi_key_bang_args, nil},
{@plymio_codi_key_delegate_module, nil},
{@plymio_codi_key_delegate_name, nil},
{@plymio_codi_key_delegate_args, nil},
{@plymio_codi_key_delegate_arity, nil},
{@plymio_codi_key_delegate_doc, nil},
{@plymio_codi_key_proxy_name, nil},
{@plymio_codi_key_typespec_spec_name, nil},
{@plymio_codi_key_typespec_spec_args, nil},
{@plymio_codi_key_typespec_spec_arity, nil},
{@plymio_codi_key_typespec_spec_result, nil},
{@plymio_codi_key_take, nil},
{@plymio_codi_key_drop, nil},
{@plymio_codi_key_filter, nil},
{@plymio_codi_key_reject, nil},
{@plymio_codi_key_postwalk, nil},
{@plymio_codi_key_transform, nil}
]
@plymio_codi_cpo_dict_aliases @plymio_codi_cpo_kvs_aliases
|> POU.opts_create_aliases_dict()
def cpo_canonical_opts(cpo, dict \\ @plymio_codi_cpo_dict_aliases) do
cpo |> POU.opts_canonical_keys(dict)
end
defdelegate cpo_normalise(cpo), to: __MODULE__, as: :cpo_canonical_opts
defdelegate cpo_normalise(cpo, dict), to: __MODULE__, as: :cpo_canonical_opts
def cpo_take_normalise(cpo, dict \\ @plymio_codi_cpo_dict_aliases) do
with {:ok, cpo} <- cpo |> POU.opts_take_canonical_keys(dict) do
{:ok, cpo |> Keyword.new()}
else
{:error, %{__exception__: true}} = result -> result
end
end
@plymio_codi_patterns_aliases @plymio_codi_pattern_types
|> Enum.map(fn k -> {k, nil} end)
@plymio_codi_patterns_dict_aliases @plymio_codi_patterns_aliases
|> POU.opts_create_aliases_dict()
def canonical_cpo_pattern(pattern, dict \\ @plymio_codi_patterns_dict_aliases) do
pattern |> POU.canonical_key(dict)
end
[
cpo_get_delegate_name: @plymio_codi_key_delegate_name,
cpo_get_delegate_doc: %{
key: @plymio_codi_key_delegate_doc,
default: @plymio_codi_key_delegate
},
cpo_get_fun_doc: %{
key: @plymio_codi_key_fun_doc,
default: nil
},
cpo_get_type_result: %{
key: @plymio_codi_key_typespec_spec_result,
default: @plymio_fontais_the_unset_value
},
cpo_get_bang_module: %{
key: @plymio_codi_key_bang_module,
default: nil
},
cpo_get_bang_name: %{
key: @plymio_codi_key_bang_name,
default: nil
},
cpo_get_bang_doc: %{key: @plymio_codi_key_bang_doc, default: @plymio_codi_key_bang},
cpo_get_type_name: %{
key: @plymio_codi_key_typespec_spec_name,
default: nil
},
cpo_get_patterns: %{
key: @plymio_codi_field_patterns,
default: []
},
cpo_get_pattern: %{
key: @plymio_codi_key_pattern,
default: @plymio_fontais_the_unset_value
},
cpo_get_status: %{
key: @plymio_codi_key_status,
default: @plymio_fontais_the_unset_value
},
cpo_get_form: %{
key: @plymio_codi_key_form,
default: @plymio_fontais_the_unset_value
},
cpo_get_since: %{
key: @plymio_codi_key_since,
default: @plymio_fontais_the_unset_value
}
]
|> PFOM.def_custom_opts_get()
[
cpo_fetch_patterns: @plymio_codi_field_patterns,
cpo_fetch_pattern: @plymio_codi_key_pattern,
cpo_fetch_status: @plymio_codi_key_status,
cpo_fetch_form: @plymio_codi_key_form,
cpo_fetch_since: @plymio_codi_key_since,
cpo_fetch_fun_module: @plymio_codi_key_fun_module,
cpo_fetch_delegate_module: @plymio_codi_key_delegate_module,
cpo_fetch_bang_module: @plymio_codi_key_bang_module
]
|> PFOM.def_custom_opts_fetch()
[
cpo_put_patterns: @plymio_codi_field_patterns,
cpo_put_pattern: @plymio_codi_key_pattern,
cpo_put_status: @plymio_codi_key_status,
cpo_put_fun_module: @plymio_codi_key_fun_module,
cpo_put_fun_name: @plymio_codi_key_fun_name,
cpo_put_fun_doc: @plymio_codi_key_fun_doc,
cpo_put_fun_args: @plymio_codi_key_fun_args,
cpo_put_fun_arity: @plymio_codi_key_fun_arity,
cpo_put_form: @plymio_codi_key_form,
cpo_put_bang_name: @plymio_codi_key_bang_name,
cpo_put_bang_arity: @plymio_codi_key_bang_arity,
cpo_put_delegate_name: @plymio_codi_key_delegate_name,
cpo_put_delegate_arity: @plymio_codi_key_delegate_arity,
cpo_put_type_arity: @plymio_codi_key_typespec_spec_arity
]
|> PFOM.def_custom_opts_put()
[
cpo_drop_fun_args: @plymio_codi_key_fun_args
]
|> PFOM.def_custom_opts_drop()
# These take an opts and get the value of a key that will be used
# with e.g. opts_get on a cpo.
# Note the default is usually the same as the key itself.
[
ctrl_get_key_fun_module: %{
key: @plymio_codi_key_fun_module,
default: @plymio_codi_key_fun_module
},
ctrl_get_key_fun_name: %{
key: @plymio_codi_key_fun_name,
default: @plymio_codi_key_fun_name
},
ctrl_get_key_fun_args: %{
key: @plymio_codi_key_fun_args,
default: @plymio_codi_key_fun_args
},
ctrl_get_key_fun_arity: %{
key: @plymio_codi_key_fun_arity,
default: @plymio_codi_key_fun_arity
},
ctrl_get_key_fun_doc: %{
key: @plymio_codi_key_fun_doc,
default: @plymio_codi_key_fun_doc
},
ctrl_get_default: %{
key: @plymio_codi_key_default,
default: nil
},
ctrl_get_validate_fun: %{
key: @plymio_codi_key_validate_fun,
default: quote(do: fn v -> v end)
}
]
|> PFOM.def_custom_opts_get()
[
ctrl_fetch_key: @plymio_codi_key_key
]
|> PFOM.def_custom_opts_fetch()
[
ctrl_put_key: @plymio_codi_key_key,
ctrl_put_default: @plymio_codi_key_default,
ctrl_put_validate_fun: @plymio_codi_key_validate_fun
]
|> PFOM.def_custom_opts_put()
def cpo_new(opts \\ [])
def cpo_new(opts) do
with {:ok, _cpo} = result <- opts |> cpo_canonical_opts do
result
else
{:error, %{__exception__: true}} = result -> result
end
end
def cpo_update(cpo, opts \\ [])
def cpo_update(cpo, opts) do
with {:ok, cpo} <- cpo |> opts_validate,
{:ok, opts} <- opts |> opts_normalise,
{:ok, _cpo} = result <- (cpo ++ opts) |> cpo_canonical_opts do
result
else
{:error, %{__exception__: true}} = result -> result
end
end
def cpo_done_with_form(cpo) do
cpo |> cpo_mark_status_done
end
def cpo_done_with_form(cpo, form) do
with {:ok, cpo} <- cpo |> cpo_done_with_form,
{:ok, _cpo} = result <- cpo |> cpo_put_form(form) do
result
else
{:error, %{__exception__: true}} = result -> result
end
end
def cpo_maybe_put_status(cpo, status)
def cpo_maybe_put_status(cpo, new_status)
when new_status in @plymio_codi_statuses do
with {:ok, status} <- cpo |> cpo_get_status do
status
|> is_value_unset_or_nil
|> case do
true -> cpo |> cpo_put_status(new_status)
_ -> {:ok, cpo}
end
else
{:error, %{__exception__: true}} = result -> result
end
end
def cpo_maybe_put_status(_cpo, status) do
new_error_result(m: "pattern status invalid", v: status)
end
def cpo_mark_status_done(cpo) do
with {:ok, cpo} <- cpo |> cpo_put_status(@plymio_codi_status_done),
{:ok, _} = result <- cpo |> cpo_tidy do
result
else
{:error, %{__exception__: true}} = result -> result
end
end
def cpo_mark_status_active(cpo) do
with {:ok, cpo} <- cpo |> cpo_put_status(@plymio_codi_status_active),
{:ok, _} = result <- cpo |> cpo_tidy do
result
else
{:error, %{__exception__: true}} = result -> result
end
end
def cpo_mark_status_dormant(cpo) do
with {:ok, cpo} <- cpo |> cpo_put_status(@plymio_codi_status_dormant),
{:ok, _} = result <- cpo |> cpo_tidy do
result
else
{:error, %{__exception__: true}} = result -> result
end
end
def cpo_active?(cpo) do
with {:ok, status} <- cpo |> cpo_get_status do
@plymio_codi_status_active == status
else
{:error, %{__struct__: _} = error} -> raise error
end
end
def cpo_done?(cpo) do
with {:ok, status} <- cpo |> cpo_get_status do
@plymio_codi_status_done == status
else
{:error, %{__struct__: _} = error} -> raise error
end
end
# form field is populated? (note nil is a valid form)
def cpo_form?(cpo) do
with {:ok, form} <- cpo |> cpo_get_form do
is_value_unset(form)
else
{:error, %{__struct__: _} = error} -> raise error
end
end
# delete dup keys, sort keys
def cpo_tidy(cpo) do
with {:ok, cpo} <- cpo |> cpo_normalise do
{:ok, cpo |> Keyword.new() |> Enum.sort_by(fn {k, _v} -> k end) |> Enum.reverse()}
else
{:error, %{__struct__: _} = error} -> raise error
end
end
# vacant => done and no form
def cpo_done_no_form?(cpo) do
cpo
|> cpo_done?
|> case do
true -> cpo |> cpo_form?
_ -> false
end
end
def cpo_normalise_forms(cpo \\ [])
def cpo_normalise_forms(cpo) do
cpo |> opts_forms_normalise(@plymio_codi_key_form)
end
def cpo_reduce_forms(cpo \\ [])
def cpo_reduce_forms(cpo) do
cpo |> opts_forms_reduce(@plymio_codi_key_form)
end
end