From f05b4ea4b75761a72a985b4cb68979b291fe4dce Mon Sep 17 00:00:00 2001 From: ndwarshuis Date: Sat, 23 Jul 2022 23:52:13 -0400 Subject: [PATCH] REF make color module more functional --- config/schema.yml | 2 ++ src/color.lua | 64 +++++++++++++++++++++-------------------------- src/pure.lua | 12 +++++++-- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/config/schema.yml b/config/schema.yml index 4c2d07a..5a07b27 100644 --- a/config/schema.yml +++ b/config/schema.yml @@ -293,6 +293,7 @@ properties: properties: color: type: integer + maximum: 0xffffff alpha: &alpha type: number minimum: 0 @@ -311,6 +312,7 @@ properties: maximum: 1 color: type: integer + maximum: 0xffffff gradient_alpha: type: array diff --git a/src/color.lua b/src/color.lua index bedbded..69a2b35 100644 --- a/src/color.lua +++ b/src/color.lua @@ -1,4 +1,5 @@ local err = require 'err' +local pure = require 'pure' -------------------------------------------------------------------------------- -- colors @@ -17,9 +18,7 @@ local rgba = function(hex, alpha) return err.set_type(obj, "color") end -local rgb = function(hex) - return rgba(hex, 1.0) -end +local rgb = pure.partial(pure.flip(rgba), 1.0) -------------------------------------------------------------------------------- -- Gradients @@ -27,30 +26,35 @@ end -- these are tables like {[stop] :: color} where stop is a float between 0 and 1 -- and color is a color as defined above -local _make_gradient = function(colorstops, f) - local c = {} - for stop, spec in pairs(colorstops) do - assert( - stop <= 1 and stop >= 0, - "ERROR: color stop must be between 0 and 1; got " .. stop - ) - c[stop] = f(spec) - end - return err.set_type(err.safe_table(c), "gradient") +local _make_gradient = function(f) + return pure.compose( + pure.partial(pure.flip(err.set_type), "gradient"), + err.safe_table, + pure.array_to_map, + pure.partial(pure.kmap, function(stop, spec) return {stop, f(spec)} end) + ) end -- {[stop] :: hex} -> Gradient -local gradient_rgb = function(colorstops) - return _make_gradient(colorstops, rgb) -end +local gradient_rgb = _make_gradient(rgb) -- {[stop] :: {hex, alpha}} -> Gradient -local gradient_rgba = function(colorstops) - return _make_gradient( - colorstops, - function(spec) return rgba(spec[1], spec[2]) end - ) -end +local gradient_rgba = _make_gradient(function(spec) return rgba(spec[1], spec[2]) end) + +-------------------------------------------------------------------------------- +-- Yaml config to pattern tree + +local compile_gradient = pure.compose( + gradient_rgb, + pure.array_to_map, + pure.partial(pure.map, function(g) return {g.stop, g.color} end) +) + +local compile_gradient_alpha = pure.compose( + gradient_rgba, + pure.array_to_map, + pure.partial(pure.map, function(g) return {g.stop, {g.color, g.alpha}} end) +) local compile_patterns @@ -62,21 +66,9 @@ compile_patterns = function(patterns) elseif v.color ~= nil then r[k] = rgba(v.color, v.alpha) elseif v.gradient ~= nil then - local p = {} - local g = v.gradient - for i = 1, #g do - local _g = g[i] - p[_g.stop] = _g.color - end - r[k] = gradient_rgb(p) + r[k] = compile_gradient(v.gradient) elseif v.gradient_alpha ~= nil then - local p = {} - local g = v.gradient_alpha - for i = 1, #g do - local _g = g[i] - p[_g.stop] = {_g.color, _g.alpha} - end - r[k] = gradient_rgba(p) + r[k] = compile_gradient_alpha(v.gradient_alpha) else r[k] = compile_patterns(v) end diff --git a/src/pure.lua b/src/pure.lua index 471f2c1..6c91ff9 100644 --- a/src/pure.lua +++ b/src/pure.lua @@ -77,6 +77,14 @@ M.imap = function(f, seq) return r end +M.kmap = function(f, seq) + local r = {} + for k, v in pairs(seq) do + r[k] = f(k, v) + end + return r +end + M.map_keys = function(key, tbls) local r = {} for i = 1, #tbls do @@ -119,8 +127,8 @@ end M.array_to_map = function(arr) local r = {} - for i = 1, #arr do - r[arr[i][1]] = arr[i][2] + for _, v in pairs(arr) do + r[v[1]] = v[2] end return r end