Module: RedQuilt::Indentation

Defined in:
lib/red_quilt/indentation.rb

Overview

Stateless CommonMark indentation / column arithmetic, shared by the block parser and its collaborator parsers (List, Blockquote, Footnote). Tabs expand to the next multiple of 4 columns.

Class Method Summary collapse

Class Method Details

.leading_columns(text) ⇒ Object

Leading-whitespace width of ‘text` in columns (tabs expanded to the next tab stop of 4).



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/red_quilt/indentation.rb', line 12

def leading_columns(text)
  col = 0
  i = 0
  bytes = text.bytesize
  while i < bytes
    b = text.getbyte(i)
    if b == 0x20
      col += 1
    elsif b == 0x09
      col = ((col / 4) + 1) * 4
    else
      break
    end
    i += 1
  end
  col
end

.leading_ws_bytes(text) ⇒ Object

Bytes of literal leading 0x20 / 0x09 in ‘text`.



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/red_quilt/indentation.rb', line 61

def leading_ws_bytes(text)
  i = 0
  bytes = text.bytesize
  while i < bytes
    b = text.getbyte(i)
    break unless b == 0x20 || b == 0x09

    i += 1
  end
  i
end

.strip_columns(text, n) ⇒ Object

Strips up to ‘n` columns of leading whitespace from `text` and returns the rest. Leading whitespace is normalised to spaces in the returned string so subsequent strips compose correctly regardless of where they land relative to the original tab stops.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/red_quilt/indentation.rb', line 34

def strip_columns(text, n)
  return text if n <= 0

  col = 0
  i = 0
  bytes = text.bytesize
  while i < bytes
    b = text.getbyte(i)
    if b == 0x20
      col += 1
    elsif b == 0x09
      col = ((col / 4) + 1) * 4
    else
      break
    end
    i += 1
  end
  # text[0...i] is all leading whitespace representing `col` cols.
  if n >= col
    i.zero? ? text : text.byteslice(i..)
  else
    # Keep the unstripped portion as a run of spaces.
    (" " * (col - n)) + text.byteslice(i..)
  end
end