Skip to content

Instantly share code, notes, and snippets.

@JoshCheek

JoshCheek/example.rb

Created Feb 25, 2021
Embed
What would you like to do?
Example of making an arg parser from a lambda signature https://twitter.com/josh_cheek/status/1364729672492277762
# Example works if done in args instead of local var assignment:
-> a, b=nil, c { {a: a, b: b, c: c} }[1, 2] # => {:a=>1, :b=>nil, :c=>2}
# Lib could, eg reflect on param types
def arg_parser(&block)
lambda do |argv|
argv, args = argv.dup, []
keywords = block.parameters.filter_map { |t, n| [n, false] if t == :keyreq }.to_h
while (arg = argv.shift)
next args << arg unless /^--?(.*)/ =~ arg
keywords[$1.intern] = argv[0] !~ /^[^-]/ || argv.shift
end
block.call(*args, **keywords)
end
end
parse = arg_parser &-> a, b='_', *ords, d: '_', e:, bool:, **keys do
{a:a, b:b, d:d, e:e, bool:bool, ords:ords, keyrest: keys}
end
parse.call %w[a -e e] # => {:a=>"a", :b=>"_", :d=>"_", :e=>"e", :bool=>false, :ords=>[], :keyrest=>{}}
parse.call %w[a b -e e] # => {:a=>"a", :b=>"b", :d=>"_", :e=>"e", :bool=>false, :ords=>[], :keyrest=>{}}
parse.call %w[a b c1 -e e] # => {:a=>"a", :b=>"b", :d=>"_", :e=>"e", :bool=>false, :ords=>["c1"], :keyrest=>{}}
parse.call %w[a b c1 c2 -e e] # => {:a=>"a", :b=>"b", :d=>"_", :e=>"e", :bool=>false, :ords=>["c1", "c2"], :keyrest=>{}}
parse.call %w[a -d d -e e] # => {:a=>"a", :b=>"_", :d=>"d", :e=>"e", :bool=>false, :ords=>[], :keyrest=>{}}
parse.call %w[a -e e -d d] # => {:a=>"a", :b=>"_", :d=>"d", :e=>"e", :bool=>false, :ords=>[], :keyrest=>{}}
parse.call %w[a -e e --bool] # => {:a=>"a", :b=>"_", :d=>"_", :e=>"e", :bool=>true, :ords=>[], :keyrest=>{}}
parse.call %w[a -e e -x -y Y] # => {:a=>"a", :b=>"_", :d=>"_", :e=>"e", :bool=>false, :ords=>[], :keyrest=>{:x=>true, :y=>"Y"}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment