Class: ShVars::String
- Inherits:
-
Object
- Object
- ShVars::String
- Extended by:
- Forwardable
- Defined in:
- lib/sh_vars/string.rb
Constant Summary collapse
- KEY =
%r([^\s=]+)
- WORD =
%r((\\.|(?!\s|"|'|`|\${|\$\().))
- SPACE =
%r(\s+)
- EQUAL =
%r(=)
- OPEN =
%r(\$\(|\$\{)
- CLOSE =
{ '$(' => %r(\)), '${' => %r(\}) }
Instance Attribute Summary collapse
-
#str ⇒ Object
readonly
Returns the value of attribute str.
Class Method Summary collapse
Instance Method Summary collapse
- #double_quoted ⇒ Object
- #double_quoted_pair ⇒ Object
- #empty_pair ⇒ Object
- #err(char) ⇒ Object
-
#initialize(str) ⇒ String
constructor
A new instance of String.
- #level ⇒ Object
- #open ⇒ Object
- #pair ⇒ Object
- #paren? ⇒ Boolean
- #parens ⇒ Object
- #parse ⇒ Object
- #quote? ⇒ Boolean
- #quoted ⇒ Object
- #quotes ⇒ Object
- #scan_quote(quote) ⇒ Object
- #scan_unquote(quote) ⇒ Object
- #single_quoted(char) ⇒ Object
- #space ⇒ Object
- #space? ⇒ Boolean
- #unquote ⇒ Object
- #unquoted_pair ⇒ Object
- #value ⇒ Object
- #values ⇒ Object
- #word ⇒ Object
Constructor Details
#initialize(str) ⇒ String
Returns a new instance of String.
25 26 27 |
# File 'lib/sh_vars/string.rb', line 25 def initialize(str) @str = StringScanner.new(str.to_s.strip) end |
Instance Attribute Details
#str ⇒ Object (readonly)
Returns the value of attribute str.
23 24 25 |
# File 'lib/sh_vars/string.rb', line 23 def str @str end |
Class Method Details
.unquote_pair(str) ⇒ Object
7 8 9 10 |
# File 'lib/sh_vars/string.rb', line 7 def unquote_pair(str) str = new(str).unquote new(str).pair end |
Instance Method Details
#double_quoted ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/sh_vars/string.rb', line 109 def double_quoted pattern = /^#{'\\' * level * 4}"/ return unless quote = scan(pattern) quotes << quote parts, part = [], nil parts << part while part = scan_quote(quote) parts << values parts << part while part = scan_quote(quote) quotes.pop err(quote) unless scan(pattern) == quote [quote, *parts, quote].join end |
#double_quoted_pair ⇒ Object
39 40 41 42 |
# File 'lib/sh_vars/string.rb', line 39 def double_quoted_pair return unless var = double_quoted self.class.unquote_pair(var) end |
#empty_pair ⇒ Object
52 53 54 55 56 57 |
# File 'lib/sh_vars/string.rb', line 52 def empty_pair return if peek(1) == '=' key = word pair = [key, ''] if key pair end |
#err(char) ⇒ Object
173 174 175 |
# File 'lib/sh_vars/string.rb', line 173 def err(char) raise ParseError, "expected #{char} at position #{pos} in: #{string.inspect}" end |
#level ⇒ Object
165 166 167 |
# File 'lib/sh_vars/string.rb', line 165 def level quotes.size end |
#open ⇒ Object
69 70 71 |
# File 'lib/sh_vars/string.rb', line 69 def open @open ||= [] end |
#pair ⇒ Object
35 36 37 |
# File 'lib/sh_vars/string.rb', line 35 def pair double_quoted_pair || unquoted_pair || empty_pair end |
#paren? ⇒ Boolean
157 158 159 |
# File 'lib/sh_vars/string.rb', line 157 def paren? open.any? && peek(open.last.size) == open.last end |
#parens ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/sh_vars/string.rb', line 73 def parens return unless paren = scan(OPEN) open << paren str = yield open.pop close = CLOSE[paren] if paren close = scan(close) if close [paren, str, close].join end |
#parse ⇒ Object
29 30 31 32 33 |
# File 'lib/sh_vars/string.rb', line 29 def parse pairs = [pair] pairs << pair while space pairs.tap { err('end of string') unless eos? } end |
#quote? ⇒ Boolean
161 162 163 |
# File 'lib/sh_vars/string.rb', line 161 def quote? quotes.any? && peek(quotes.last.size) == quotes.last end |
#quoted ⇒ Object
85 86 87 |
# File 'lib/sh_vars/string.rb', line 85 def quoted double_quoted || single_quoted("'") || single_quoted("`") end |
#quotes ⇒ Object
169 170 171 |
# File 'lib/sh_vars/string.rb', line 169 def quotes @quotes ||= [] end |
#scan_quote(quote) ⇒ Object
124 125 126 127 128 |
# File 'lib/sh_vars/string.rb', line 124 def scan_quote(quote) str = scan(/[^#{quote}\\]+/) str ||= scan(/#{'\\' * level * 2}#{quote}/) str end |
#scan_unquote(quote) ⇒ Object
146 147 148 149 150 151 |
# File 'lib/sh_vars/string.rb', line 146 def scan_unquote(quote) str = scan(/[^#{quote}\\]+/) return str if str str = scan(/#{'\\' * level * 2}#{quote}/) ['\\' * (level - 1), quote].join if str end |
#single_quoted(char) ⇒ Object
99 100 101 102 103 104 105 106 107 |
# File 'lib/sh_vars/string.rb', line 99 def single_quoted(char) pattern = /#{char}/ return unless quote = scan(pattern) quotes << quote str = scan(/[^#{char}]*/) # how about nested double quoted strs in here quote = quotes.pop err(quote) unless scan(pattern) == quote [quote, str, quote].join end |
#space ⇒ Object
95 96 97 |
# File 'lib/sh_vars/string.rb', line 95 def space scan(SPACE) end |
#space? ⇒ Boolean
153 154 155 |
# File 'lib/sh_vars/string.rb', line 153 def space? peek(1) =~ SPACE end |
#unquote ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/sh_vars/string.rb', line 130 def unquote pattern = /^#{'\\' * level * 4}"/ return unless quote = scan(pattern) quotes << quote parts, part = [], nil parts << part while part = scan_unquote(quote) parts << unquote parts << part while part = scan_unquote(quote) quote = quotes.pop err(quote) unless scan(pattern) == quote unquote = level == 0 ? '' : %(#{'\\' * (level)}") [unquote, *parts, unquote].join end |
#unquoted_pair ⇒ Object
44 45 46 47 48 49 50 |
# File 'lib/sh_vars/string.rb', line 44 def unquoted_pair return unless key = scan(KEY) return [key, ''] unless scan(EQUAL) parts, part = [], nil parts << part while part = value [key, parts.join] end |
#value ⇒ Object
65 66 67 |
# File 'lib/sh_vars/string.rb', line 65 def value parens { values } || quoted || word end |
#values ⇒ Object
59 60 61 62 63 |
# File 'lib/sh_vars/string.rb', line 59 def values parts, part = [], nil parts << part while part = value || space parts.join if parts.any? end |
#word ⇒ Object
89 90 91 92 93 |
# File 'lib/sh_vars/string.rb', line 89 def word chars, char = [], nil chars << char while !quote? && char = scan(WORD) chars.join if chars.any? end |