lib/tcl/ruby/commands/string.rb
require 'strscan'
module Tcl
module Ruby
class Interpreter
private
def ___string(*arg)
send("___string_#{arg[0]}", *arg[1..-1])
rescue ArgumentError => e
raise(TclArgumentError, "string #{arg[0]}: #{e.message}")
end
def ___string_length(str)
str.length
end
def ___string_equal(*arg)
opts = {}
if arg.size != 2
opts = OptionParser.parse(['nocase', 'length?'], arg)
raise(TclArgumentError, 'string equal ?-nocase? ?-length int? string1 string2') unless arg.size == 2
end
__string_equal_body(*arg, opts)
end
def __string_equal_body(str1, str2, opts = {})
if opts.key?('nocase')
str1 = str1.upcase
str2 = str2.upcase
end
if opts.key?('length')
range = (0...opts['length'].to_i)
(str1[range] == str2[range]) ? '1' : '0'
else
(str1 == str2) ? '1' : '0'
end
end
def ___string_index(str, index)
str[parse_index_format(index)]
end
def ___string_map(*arg)
opts = {}
if arg.size != 2
opts = OptionParser.parse(['nocase'], arg)
raise(TclArgumentError, 'string map ?-nocase? charMap string') unless arg.size == 2
end
__string_map_body(*arg, opts)
end
def __string_map_body(char_map, str, opts = {})
h = parse(char_map, true).to_h
scan = StringScanner.new str
rstr = ''
until scan.empty?
r = h.each do |k, v|
next unless (opts['nocase'] && scan.scan(/#{k}/i)) ||
scan.scan(/#{k}/)
rstr << v
break false
end
rstr << scan.scan(/./) if r
end
rstr
end
def ___string_range(str, first, last)
first = parse_index_format first
last = parse_index_format last
str[first..last]
end
def ___string_repeat(str, count)
str * count.to_i
end
def ___string_tolower(str, first = 0, last = nil)
last ||= str.size
__string_tosomething(str, first, last, :downcase)
end
def __string_tosomething(str, first, last, modifier)
first = parse_index_format first
last = parse_index_format last
str[first..last] = str[first..last].send(modifier)
str
end
def ___string_totitle(str, first = 0, last = -1)
__string_tosomething(str, first, last, :capitalize)
end
def ___string_toupper(str, first = 0, last = -1)
__string_tosomething(str, first, last, :upcase)
end
def ___string_trim(str, chars = '\s')
__string_trimmer(str, chars, 3)
end
def ___string_trimleft(str, chars = '\s')
__string_trimmer(str, chars, 1)
end
def ___string_trimright(str, chars = '\s')
__string_trimmer(str, chars, 2)
end
def __string_trimmer(str, chars, mode)
str.sub!(/\A[#{chars}]+/, '') if mode & 1 != 0
str.sub!(/[#{chars}]+\z/, '') if mode & 2 != 0
str
end
end
end
end