Created
June 1, 2020 14:42
-
-
Save bpj/091b7ad514e7d17a83fa8b2a4c669579 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- DWIM selective table item copying for Moonscript (and Lua) | |
import_select = (target, source, ...) -> | |
names = {...} | |
-- allow passing a table of names, | |
-- possibly with renames | |
if 1 == #names and 'table' == type names[1] | |
names = names[1] | |
-- map keys are "new" names | |
-- map vals are "old" names | |
for tgt, src in pairs names | |
-- array items are not renamed | |
if 'number' == type tgt | |
tgt = tostring(src)\gsub "^[%+%-]+", "" | |
else | |
tgt = tostring tgt | |
if 'table' != type src | |
src = {src} | |
for _src in *src | |
_src = tostring _src | |
flags, _name = _src\match '^([%+%-]*)(.+)$' | |
_src = _name or | |
error "Invalid source name: #{_src}", 2 | |
keep = flags\match "%+" | |
lax = flags\match "%-" | |
-- an `*` in tgt is replaced with _src | |
_tgt = tgt\gsub '%*', _src | |
if keep and nil != target[_tgt] | |
continue | |
if nil == source[_src] | |
if lax | |
continue | |
else | |
error "Field '#{_src}' (for '#{_tgt}') not found", 2 | |
target[_tgt] = source[_src] | |
return target | |
-- f = import_select {}, table, 'pack', 'unpack', 'sort' | |
-- import_select f, string, { | |
-- 'match', 'gsub', | |
-- fmt: 'format', | |
-- 's_*': {'pack', 'unpack'}, | |
-- } | |
-- import_select f, require"moon", { | |
-- pprint: 'p', | |
-- 'moon_*': 'type', | |
-- } | |
-- import_select f, math, { 'm_*': {'floor', 'type'}} | |
-- -- This won't overwritev(un)pack from table | |
-- -- nor error because string.title doesn't exist! | |
-- import_select f, string, '+pack', '+unpack', '-title' | |
-- moon = require"moon" | |
-- moon.p f | |
-- moon.p { | |
-- pack: (f.pack == table.pack), | |
-- unpack: (f.unpack == table.unpack), | |
-- sort: (f.sort == table.sort), | |
-- match: (f.match == string.match), | |
-- gsub: (f.gsub == string.gsub), | |
-- fmt: (f.fmt == string.format), | |
-- s_pack: (f.s_pack == string.pack), | |
-- s_unpack: (f.s_unpack == string.unpack), | |
-- pprint: (f.pprint == moon.p), | |
-- moon_type: (f.moon_type == moon.type), | |
-- m_floor: (f.m_floor == math.floor), | |
-- m_type: (f.m_type == math.type), | |
-- } | |
-- -- Don't do this at work! | |
-- -- Not at home either! | |
-- _ENV = import_select( | |
-- import_select( | |
-- {k,v for k,v in pairs _ENV}, | |
-- table, { | |
-- 't_*': {'pack', 'unpack', 'sort', 'insert'}, | |
-- } | |
-- ) | |
-- string, { | |
-- 's_*': { | |
-- 'match','gsub', 'gmatch','sub', 'rep', | |
-- }, | |
-- sprintf: 'format', | |
-- } | |
-- ) | |
-- g = {k,true for k in pairs _G} | |
-- for name in *[k for k in pairs _ENV] | |
-- unless g[name] | |
-- print name | |
-- print "xxx" == s_rep "x", 3 | |
-- print "(foo)" == sprintf "(%s)", "foo" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
DWIM selective table item copying for Moonscript (and Lua)
import_select(target, source, {name, ..., target_name: source_name, ...}|name, ...)
Import selected names and their values from the table
source
into the tabletarget
. Returnstarget
so you can pass an anonymous table astarget
and assign the return value to a variable.If only three arguments are passed and argument #3 is a table, fields in that table with a numeric key are taken as simple imports where both the source name and the target name are equal to the value. Otherwise the key is taken to be the target name and the value is taken to be the source name. Thus these three invocations are equivalent:
If the target name contains any
*
(asterisk/star)character the source name will be substituted for it (or them!), so that these two invocations are equivalent:Additionally the "source name" may itself be an array of names. This is only really useful when the key contains a star, since else the imports will overwrite each other, but these three invocations are equivalent:
Naturally you can mix all these in a single table:
An error is thrown if the name doesn't exist in the source table, i.e. if
nil == source[source_name]
, except if the source name is prefixed with a-
(minus) character (and if so make sure you typed the rest correctly!), and an existing field in the import table is not overwritten if the source name starts with a+
(plus) character:If you like you can do shenanigans with
_ENV
so that you can type the import names as bare names, but remember I didn't tell you to do so!Last but not least the type of the imports are not checked in any way. Did you notice that a string,
charpattern
, was imported fromutf8
above?