Module: Oktest::Util

Defined in:
lib/oktest.rb

Defined Under Namespace

Classes: PartialRegexp

Constant Summary collapse

PARTIAL_REGEXP_CACHE =

:nodoc:

{}

Class Method Summary collapse

Class Method Details

._text2lines(text, no_newline_msg = nil) ⇒ Object



2296
2297
2298
2299
2300
2301
# File 'lib/oktest.rb', line 2296

def _text2lines(text, no_newline_msg=nil)
  lines = []
  text.each_line {|line| line.chomp!; lines << line }
  lines[-1] << no_newline_msg if no_newline_msg && text[-1] && text[-1] != ?\n
  return lines
end

.diff_unified(text_old, text_new, label = "--- old\n+++ new\n", context = 3) ⇒ Object

platform depend, but not require extra library



2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
# File 'lib/oktest.rb', line 2330

def diff_unified(text_old, text_new, label="--- old\n+++ new\n", context=3)
  #; [!ulyq5] returns unified diff string of two text strings.
  #; [!6tgum] detects whether char at end of file is newline or not.
  tmp_old = "_tmp.old.#{rand()}"
  tmp_new = "_tmp.new.#{rand()}"
  File.open(tmp_old, 'w') {|f| f.write(text_old) }
  File.open(tmp_new, 'w') {|f| f.write(text_new) }
  begin
    #diff = `diff -u #{tmp_old} #{tmp_new}`
    diff = `diff --unified=#{context} #{tmp_old} #{tmp_new}`
  ensure
    File.unlink(tmp_old)
    File.unlink(tmp_new)
  end
  diff.sub!(/\A\-\-\-.*\n\+\+\+.*\n/, label.to_s)
  return diff
end

.file_line(filename, linenum) ⇒ Object



2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
# File 'lib/oktest.rb', line 2225

def file_line(filename, linenum)
  #; [!4z65g] returns nil if file not exist or not a file.
  return nil unless File.file?(filename)
  #; [!4a2ji] caches recent file content for performance reason.
  @__cache ||= [nil, []]
  if @__cache[0] != filename
    #; [!wtrl5] recreates cache data if other file requested.
    @__cache[0] = filename
    @__cache[1].clear
    @__cache[1] = lines = File.open(filename, 'rb') {|f| f.to_a }
  else
    lines = @__cache[1]
  end
  #; [!162e1] returns line string.
  return lines[linenum-1]
end

.hhmmss(n) ⇒ Object



2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
# File 'lib/oktest.rb', line 2279

def hhmmss(n)
  h, n = n.divmod(60*60)
  m, s = n.divmod(60)
  #; [!shyl1] converts 400953.444 into '111:22:33.4'.
  #; [!vyi2v] converts 5025.678 into '1:23:45.7'.
  return "%d:%02d:%04.1f" % [h, m, s] if h > 0
  #; [!pm4xf] converts 754.888 into '12:34.9'.
  #; [!lwewr] converts 83.444 into '1:23.4'.
  return "%d:%04.1f" % [m, s]         if m > 0
  #; [!ijx52] converts 56.8888 into '56.9'.
  return "%.1f" % s                   if s >= 10
  #; [!2kra2] converts 9.777 into '9.78'.
  return "%.2f" % s                   if s >= 1
  #; [!4aomb] converts 0.7777 into '0.778'.
  return "%.3f" % s
end

.keyword_param_names_of_block(block) ⇒ Object



2255
2256
2257
2258
2259
2260
# File 'lib/oktest.rb', line 2255

def keyword_param_names_of_block(block)
  #; [!p6qqp] returns keyword param names of proc object.
  names = []
  block.parameters.each {|kind, name| names << name if kind == :key }
  return names
end

.partial_regexp(pattern, begin_ = '\A', end_ = '\z', mark = "{== ==}") ⇒ Object



2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
# File 'lib/oktest.rb', line 2396

def partial_regexp(pattern, begin_='\A', end_='\z', mark="{== ==}")
  mark_rexp = PARTIAL_REGEXP_CACHE[mark]
  if mark_rexp.nil?
    #; [!ostkw] raises error if mark has no space or has more than two spaces.
    pair = mark.split()
    pair.length == 2  or
      raise ArgumentError.new("#{mark.inspect}: mark should contain only one space (ex: `{== ==}`).")
    open  = Regexp.escape(pair[0])
    close = Regexp.escape(pair[1])
    mark_rexp = Regexp.compile("#{open}(.*?)#{close}")
    PARTIAL_REGEXP_CACHE[mark] = mark_rexp
  end
  #; [!wn524] returns PartialRegexp object which inspect string is regexp literal style.
  pos = 0
  buf = []
  buf << begin_ if begin_
  pattern.scan(mark_rexp) do
    m = Regexp.last_match
    text = pattern[pos, m.begin(0) - pos]
    buf << Regexp.escape(text) << $1.strip()
    pos = m.end(0)
  end
  rest = pos == 0 ? pattern : pattern[pos..-1]
  buf << Regexp.escape(rest) unless rest.empty?
  buf << end_ if end_
  return PartialRegexp.compile(buf.join())
end

.partial_regexp!(pattern, begin_ = '\A', end_ = '\z', mark = "{== ==}") ⇒ Object



2388
2389
2390
2391
2392
2393
2394
# File 'lib/oktest.rb', line 2388

def partial_regexp!(pattern, begin_='\A', end_='\z', mark="{== ==}")
  #; [!peyu4] returns PartialRegexp object which inspect string is function call styel.
  regexp = partial_regexp(pattern, begin_, end_, mark)
  regexp.pattern_string = pattern
  regexp.begin = begin_; regexp.end = end_; regexp.mark = mark
  return regexp
end

.required_param_names_of_block(block) ⇒ Object



2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
# File 'lib/oktest.rb', line 2242

def required_param_names_of_block(block)
  #; [!a9n46] returns nil if argument is nil.
  return nil unless block
  #; [!7m81p] returns empty array if block has no parameters.
  n = block.arity
  n = - n - 1 if n < 0
  return [] if n == 0
  #; [!n3g63] returns parameter names of block.
  #; [!d5kym] collects only normal parameter names.
  param_names = block.parameters[0...n].collect {|pair| pair[1] }
  return param_names
end

.strfold(str, width = 80, mark = '...') ⇒ Object



2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
# File 'lib/oktest.rb', line 2262

def strfold(str, width=80, mark='...')
  #; [!wb7m8] returns string as it is if string is not long.
  return str if str.bytesize <= width
  #; [!a2igb] shorten string if it is enough long.
  return str[0, width - mark.length] + mark if str.ascii_only?
  #; [!0gjye] supports non-ascii characters.
  limit = width - mark.length
  w = len = 0
  str.each_char do |ch|
    w += ch.bytesize == 1 ? 1 : 2
    break if w >= limit
    len += 1
  end
  str = str[0, len] + mark if w >= limit
  return str
end

.unified_diff(text_old, text_new, label = "--- old\n+++ new\n", context = 3) ⇒ Object

platform independent, but requires ‘diff-lcs’ gem



2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
# File 'lib/oktest.rb', line 2305

def unified_diff(text_old, text_new, label="--- old\n+++ new\n", context=3)
  #; [!rnx4f] checks whether text string ends with newline char.
  msg = "\\ No newline at end of string"
  lines_old = _text2lines(text_old, msg)
  lines_new = _text2lines(text_new, msg)
  #; [!wf4ns] calculates unified diff from two text strings.
  buf = [label]
  len = 0
  prevhunk = hunk = nil
  diffs = Diff::LCS.diff(lines_old, lines_new)
  diffs.each do |diff|
    hunk = Diff::LCS::Hunk.new(lines_old, lines_new, diff, context, len)
    if hunk.overlaps?(prevhunk)
      hunk.unshift(prevhunk)
    else
      buf << prevhunk.diff(:unified) << "\n"
    end if prevhunk
    len = hunk.file_length_difference
    prevhunk = hunk
  end
  buf << prevhunk.diff(:unified) << "\n" if prevhunk
  return buf.join()
end