Created
May 3, 2017 22:20
-
-
Save toddnestor/392ea5ff194e0b0d74cf6682c827a366 to your computer and use it in GitHub Desktop.
class for extracting arguments from a string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This class is solely used for extracting arguments from a string | |
# It is used to process the arguments input to template_methods in the CMS content areas | |
# It handles arguments that are comma separated, inside or outside of quotes | |
# Like normal arguments to a programming function if something is inside a quote it will | |
# all be part of the same argument and commas inside of quotes are part of that argument | |
# rather than used to separate it from another argument. It also takes into account backslashes | |
# so 'I\'m an argument' will properly be processed | |
# | |
# For example link("http://google.com", 'Google is fun to use, really it is') | |
# It will result in the arguments: | |
# [ | |
# "http://google.com", | |
# 'Google is fun to use, really it is, isn\'t it?' | |
# ] | |
class TemplateMethodArguments | |
def self.extract(str) | |
new(str).extract | |
end | |
def initialize(str) | |
@str = strip_parens(str) | |
end | |
def extract | |
@quotation_start = nil | |
@args = [] | |
@current_arg = '' | |
@str.each_char.with_index do |char, i| | |
if @quotation_start.nil? | |
handle_non_quoted_argument(char, i) | |
else | |
handle_quoted_argument(char, i) | |
end | |
end | |
add_current_arg | |
@args | |
end | |
private | |
def strip_parens(str) | |
str = str.strip | |
str = str[1..-1] if str[0] == '(' | |
str = str[0..-2] if str[-1] == ')' | |
str | |
end | |
def handle_non_quoted_argument(char, i) | |
if non_escaped_quote?(char, i) | |
begin_quoted_argument(char) | |
else | |
handle_non_quoted_char(char, i) | |
end | |
end | |
def handle_non_quoted_char(char, i) | |
if char == ',' | |
add_current_arg(strip_arg: true) | |
elsif char != '\\' || escaped_char?(i) | |
@current_arg << char | |
end | |
end | |
def begin_quoted_argument(char) | |
@current_arg = '' | |
@quotation_start = char | |
end | |
def end_quoted_argument | |
add_current_arg(add_empty: true) | |
@quotation_start = nil | |
end | |
def handle_quoted_argument(char, i) | |
if char == @quotation_start && non_escaped_char?(i) | |
end_quoted_argument | |
elsif char != '\\' || escaped_char?(i) | |
@current_arg << char | |
end | |
end | |
def add_current_arg(strip_arg: false, add_empty: false) | |
@current_arg = @current_arg.strip if strip_arg | |
@args << @current_arg if @current_arg.present? || add_empty | |
@current_arg = '' | |
end | |
def non_escaped_quote?(char, i) | |
['\'', '"'].include?(char) && non_escaped_char?(i) | |
end | |
def non_escaped_char?(i) | |
i.zero? || @str[i - 1] != '\\' | |
end | |
def escaped_char?(i) | |
!i.zero? && @str[i - 1] == '\\' | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment