Formatter Rules
View SourceThe Funx library exports formatter rules for its DSLs, allowing projects that depend on Funx to automatically format DSL code without extra parentheses.
Exported Rules
Either DSL
The following Either DSL functions are configured to format without parentheses:
either/2- DSL entry pointbind/1- Chain operations that return Either or result tuplesmap/1- Transform values with plain functionsap/1- Apply function in Either to value in Eithervalidate/1- Collect all errors from validatorsfilter_or_else/2- Filter with predicate, fallback if failsor_else/1- Provide fallback on errormap_left/1- Transform error valuestap- Run a side-effecting function inside the chain without changing the data
Note that flip/0 - Swap Left and Right still requires parentheses.
Maybe DSL
The following Maybe DSL functions are configured to format without parentheses:
maybe/2- DSL entry pointbind/1- Chain operations that return Maybe, Either, result tuples, or nil (shared with Either DSL)map/1- Transform values with plain functions (shared with Either DSL)ap/1- Apply function in Maybe to value in Maybe (shared with Either DSL)or_else/1- Provide fallback on Nothing (shared with Either DSL)tap/1- Run a side-effecting function inside the chain without changing the data (shared with Either DSL)filter/1- Filter with a predicate, returns Nothing if predicate failsfilter_map/2- Filter and transform in one stepguard/1- Guard with a boolean condition
Ord DSL
The following Ord DSL functions are configured to format without parentheses:
asc/1- Ascending order for a projectionasc/2- Ascending order with options (e.g.,default:)desc/1- Descending order for a projectiondesc/2- Descending order with options (e.g.,default:)
Eq DSL
The following Eq DSL functions are configured to format without parentheses:
on/1- Compare on a projectionon/2- Compare on a projection with optionsnot_on/1- Exclude a projection from comparisonnot_on/2- Exclude a projection from comparison with optionsany/1- Match any of the given comparisons (shared with Predicate DSL)all/1- Match all of the given comparisons (shared with Predicate DSL)
Predicate DSL
The following Predicate DSL functions are configured to format without parentheses:
pred/1- DSL entry point for defining predicatescheck/2- Project and test a value (e.g.,check :field, predicate)negate/1- Negate a predicate or blocknegate_all/1- Negate an AND block (applies De Morgan's Laws)negate_any/1- Negate an OR block (applies De Morgan's Laws)any/1- OR logic - at least one predicate must pass (shared with Eq DSL)all/1- AND logic - all predicates must pass (shared with Eq DSL)
Usage in Dependent Projects
Step 1: Add to Dependencies
Make sure your mix.exs includes Funx as a dependency:
def deps do
[
{:funx, "~> 0.2"}
]
endStep 2: Update .formatter.exs
In your project's .formatter.exs, add :funx to import_deps:
[
import_deps: [:funx],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]Examples
Either DSL
With this configuration, your DSL code will format cleanly:
either user_input do
bind ParseUser
map ValidateEmail
validate [CheckLength, CheckFormat]
bind SaveToDatabase
or_else default_user()
endInstead of:
either(user_input) do
bind(ParseUser)
map(ValidateEmail)
validate([CheckLength, CheckFormat])
bind(SaveToDatabase)
or_else(default_user())
endMaybe DSL
Your Maybe pipelines will format cleanly:
maybe user_input do
bind ParseInt
filter PositiveNumber
map Double
or_else default_value()
endInstead of:
maybe(user_input) do
bind(ParseInt)
filter(PositiveNumber)
map(Double)
or_else(default_value())
endOrd DSL
Your ordering definitions will format cleanly:
ord do
asc :name
desc :age
asc :score, default: 0
endInstead of:
ord do
asc(:name)
desc(:age)
asc(:score, default: 0)
endPredicate DSL
Your predicate definitions will format cleanly:
pred do
check :age, fn age -> age >= 18 end
negate check :banned, fn b -> b == true end
any do
check :role, fn r -> r == :admin end
check :verified, fn v -> v == true end
end
negate_all do
check :suspended, fn s -> s == true end
check :deleted, fn d -> d == true end
end
endInstead of:
pred do
check(:age, fn age -> age >= 18 end)
negate(check(:banned, fn b -> b == true end))
any do
check(:role, fn r -> r == :admin end)
check(:verified, fn v -> v == true end)
end
negate_all do
check(:suspended, fn s -> s == true end)
check(:deleted, fn d -> d == true end)
end
endVerification
To verify the formatter rules are being imported correctly, you can run:
mix format --check-formatted
Your DSL code should format without adding parentheses.