class ShVars::String

Constants

CLOSE
EQUAL
KEY
OPEN
SPACE
WORD

Attributes

str[R]

Public Class Methods

new(str) click to toggle source
# File lib/sh_vars/string.rb, line 25
def initialize(str)
  @str = StringScanner.new(str.to_s.strip)
end
unquote_pair(str) click to toggle source
# File lib/sh_vars/string.rb, line 7
def unquote_pair(str)
  str = new(str).unquote
  new(str).pair
end

Public Instance Methods

double_quoted() click to toggle source
# 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() click to toggle source
# 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() click to toggle source
# 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) click to toggle source
# File lib/sh_vars/string.rb, line 173
def err(char)
  raise ParseError, "expected #{char} at position #{pos} in: #{string.inspect}"
end
level() click to toggle source
# File lib/sh_vars/string.rb, line 165
def level
  quotes.size
end
open() click to toggle source
# File lib/sh_vars/string.rb, line 69
def open
  @open ||= []
end
pair() click to toggle source
# File lib/sh_vars/string.rb, line 35
def pair
  double_quoted_pair || unquoted_pair || empty_pair
end
paren?() click to toggle source
# File lib/sh_vars/string.rb, line 157
def paren?
  open.any? && peek(open.last.size) == open.last
end
parens() { || ... } click to toggle source
# 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() click to toggle source
# 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?() click to toggle source
# File lib/sh_vars/string.rb, line 161
def quote?
  quotes.any? && peek(quotes.last.size) == quotes.last
end
quoted() click to toggle source
# File lib/sh_vars/string.rb, line 85
def quoted
  double_quoted || single_quoted("'") || single_quoted("`")
end
quotes() click to toggle source
# File lib/sh_vars/string.rb, line 169
def quotes
  @quotes ||= []
end
scan_quote(quote) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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() click to toggle source
# File lib/sh_vars/string.rb, line 95
def space
  scan(SPACE)
end
space?() click to toggle source
# File lib/sh_vars/string.rb, line 153
def space?
  peek(1) =~ SPACE
end
unquote() click to toggle source
# 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() click to toggle source
# 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() click to toggle source
# File lib/sh_vars/string.rb, line 65
def value
  parens { values } || quoted || word
end
values() click to toggle source
# 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() click to toggle source
# 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