lib/tcl/ruby/commands/list.rb in tcl-ruby-0.1.0 vs lib/tcl/ruby/commands/list.rb in tcl-ruby-0.1.1

- old
+ new

@@ -1,72 +1,116 @@ module Tcl module Ruby class Interpreter private - def ___llength(arg) - raise(CommandError, 'llength list') if arg.size != 1 - parse(arg[0], true).size + def ___concat(*arg) + arg.map(&:strip).join(' ') end - def ___list(arg) - arg.join(' ').to_s + def ___llength(list) + parse(list, true).size.to_s end - def ___lindex(arg) - if arg[1].nil? - arg[0] - elsif arg[1] == '' - arg[0] - else - l = arg[0] - arg[1..-1].each do |as| - parse(as, true).each do |a| - l = parse(l, true) - a.gsub!(/end/, (l.size - 1).to_s) - pos = eval(a) - if (0...l.size).cover?(pos) - l = l[pos] - else - return '' - end - end + def ___list(*arg) + ListArray.new(arg).to_list + end + + def ___lindex(list, *indexes) + return list if indexes.nil? || indexes.empty? + l = list + indexes.each do |as| + parse(as, true).each do |a| + l = parse(l, true) + pos = parse_index_format(a) + l = l[pos] end - l end + l || '' end - def ___join(arg) - raise(CommandError, 'join list joinString?') unless (1..2).cover? arg.size - separator = arg[1] || ' ' - parse(arg[0], true).join(separator) + def ___join(list, separator = ' ') + parse(list, true).join(separator) end - def ___linsert(arg) - raise(CommandError, 'linsert list insertposition elements') unless arg.size >= 3 - l = parse(arg[0], true) - l.insert(arg[1].to_i, *arg[2..-1]) - # "{#{l.join(' ')}}" + def ___linsert(list, index, element, *elements) + l = parse(list, true) + l.insert(parse_index_format(index), element, *elements) l.to_list end - def ___lrange(arg) - raise(CommandError, 'lrange list first last') unless arg.size == 3 - first = arg[1].to_i - first = 0 if first < 0 - last = arg[2].to_i - l = parse(arg[0], true) - if first <= last - l[first..last].to_list + def ___lrange(list, first, last) + first = parse_index_format first + last = parse_index_format last + l = parse(list, true) + l[first..last].to_list + end + + def ___lappend(var_name, *values) + l = parse(variables(var_name), true) + l.push(*values) + @variables[var_name] = l.to_list + end + + def ___lsort(*args) + opts = {} + if args.size > 1 + opts = OptionParser.parse( + ['ascii', 'dictionary', 'integer', 'real', 'command?', 'increasing', + 'decreasing', 'index?', 'unique'], args) + end + __lsort_body(*args, opts) + end + + def __lsort_body(list, opts) + l = parse(list, true) + func = if opts['directionary'] then :upcase + elsif opts['integer'] then :to_i + elsif opts['real'] then :to_f + else :to_s + end + if opts['index'] + index = parse_index_format(opts['index']) + sort_func = -> (x) { parse(x, true)[index].send(func) } else - '' + sort_func = func end + l.uniq!(&sort_func) if opts['unique'] + l.sort_by!(&sort_func) + l.reverse! if opts['decreasing'] + ListArray.new(l).to_list end - def ___lappend(arg) - l = parse(variables(arg[0]), true) - l.push(*arg[1..-1]) - @variables[arg[0]] = l.to_list + def ___lsearch(*args) + opts = {} + if args.size > 2 + opts = OptionParser.parse( + ['all', 'ascii', 'decreasing', 'dictionary', 'exact', 'glob', + 'increasing', 'inline', 'integer', 'not', 'real', 'regexp', + 'sorted', 'start?'], args) + end + __lsearch_body(*args, opts) + end + + def __lsearch_body(list, pattern, opts) + l = parse(list, true) + func = case [opts['all'], opts['inline']] + when [true, true] then :select + when [true, nil] then :find_index_all + when [nil, true] then :find + else :index + end + block = if opts['regexp'] then -> (b, x) { !!(x =~ /#{pattern}/) == b } + elsif opts['exact'] then -> (b, x) { (x == pattern) == b } + else + pattern.gsub!(/\*/, '.*') + pattern.tr!('?', '.') + pattern.gsub!(/\\(.)/) { Regexp.last_match(1) } + -> (b, x) { !!(x =~ /\A#{pattern}\z/) == b } + end.curry + + v = l.send(func, &block.call(!opts['not'])) + ListArray.new(v).to_list end end end end