lib/planter/string.rb in planter-cli-0.0.3 vs lib/planter/string.rb in planter-cli-0.0.4
- old
+ new
@@ -21,11 +21,11 @@
## @example "planter-string".to_class_name #=> PlanterString
##
## @return Class name representation of the object.
##
def to_class_name
- strip.no_ext.split(/[-_ ]/).map(&:capitalize).join('').gsub(/[^a-z0-9]/i, '')
+ strip.no_ext.title_case.gsub(/[^a-z0-9]/i, '').sub(/^\S/, &:upcase)
end
##
## Convert a class name to a file slug
##
@@ -64,11 +64,11 @@
## @example "A title string".snake_case #=> a-title-string
##
## @return [String] Snake-cased version of string
##
def snake_case
- strip.gsub(/\S[A-Z]/) { |pair| pair.split('').join('_') }
+ strip.gsub(/\S(?=[A-Z])/, '\0_')
.gsub(/[ -]+/, '_')
.gsub(/[^a-z0-9_]+/i, '')
.gsub(/_+/, '_')
.gsub(/(^_|_$)/, '').downcase
end
@@ -80,11 +80,11 @@
## @example "A title string".camel_case #=> aTitleString
##
## @return [String] Snake-cased version of string
##
def camel_case
- strip.gsub(/[ _]+(\S)/) { Regexp.last_match(1).upcase }
+ strip.gsub(/(?<=[^a-z0-9])(\S)/) { Regexp.last_match(1).upcase }
.gsub(/[^a-z0-9]+/i, '')
.sub(/^(\w)/) { Regexp.last_match(1).downcase }
end
##
@@ -94,24 +94,15 @@
## @example "a title string".title_case #=> A Title String
##
## @return [String] title cased string
##
def title_case
- gsub(/\b(\w)/) { Regexp.last_match(1).upcase }
+ split(/\b(\w+)/).map(&:capitalize).join('')
end
- ##
- ## Apply key/value substitutions to a string. Variables are represented as
- ## %%key%%, and the hash passed to the function is { key: value }
- ##
- ## @param last_only [Boolean] Only replace the last instance of %%key%%
- ##
- ## @return [String] string with variables substituted
- ##
- def apply_variables(last_only: false)
- content = dup.clean_encode
- mod_rx = '(?<mod>
+ # @return [String] Regular expression for matching variable modifiers
+ MOD_RX = '(?<mod>
(?::
(
l(?:ow(?:er)?)?)?|
u(?:p(?:per)?)?|
c(?:ap(?:ital(?:ize)?)?)?|
@@ -119,52 +110,151 @@
snake|camel|slug|
f(?:ile(?:name)?
)?
)*
)'
+ # @return [String] regular expression string for default values
+ DEFAULT_RX = '(?:%(?<default>[^%]+))?'
- Planter.variables.each do |k, v|
+ #
+ # Apply default values to a string
+ #
+ # Default values are applied to variables that are not present in the variables hash,
+ # or whose value matches the default value
+ #
+ # @param variables [Hash] Hash of variable values
+ #
+ # @return [String] string with default values applied
+ #
+ def apply_defaults(variables)
+ # Perform an in-place substitution on the content string for default values
+ gsub(/%%(?<varname>[^%:]+)(?<mods>(?::[^%]+)*)%(?<default>[^%]+)%%/) do
+ # Capture the last match object
+ m = Regexp.last_match
+
+ # Check if the variable is not present in the variables hash
+ if !variables.key?(m['varname'].to_var)
+ # If the variable is not present, use the default value from the match
+ m['default'].apply_var_names
+ else
+ # Retrieve the default value for the variable from the configuration
+ vars = Planter.config[:variables].filter { |v| v[:key] == m['varname'] }
+ default = vars.first[:default] if vars.count.positive?
+ if default.nil?
+ m[0]
+ elsif variables[m['varname'].to_var] == default
+ # If the variable's value matches the default value, use the default value from the match
+ m['default'].apply_var_names
+ else
+ m[0]
+ end
+ end
+ end
+ end
+
+ #
+ # Destructive version of #apply_defaults
+ #
+ # @param variables [Hash] hash of variables to apply
+ #
+ # @return [String] string with defaults applied
+ #
+ def apply_defaults!(variables)
+ replace apply_defaults(variables)
+ end
+
+ ##
+ ## Apply key/value substitutions to a string. Variables are represented as
+ ## %%key%%, and the hash passed to the function is { key: value }
+ ##
+ ## @param last_only [Boolean] Only replace the last instance of %%key%%
+ ##
+ ## @return [String] string with variables substituted
+ ##
+ def apply_variables(variables: nil, last_only: false)
+ variables = variables.nil? ? Planter.variables : variables
+
+ content = dup.clean_encode
+
+ content = content.apply_defaults(variables)
+
+ variables.each do |k, v|
if last_only
pattern = "%%#{k.to_var}"
- content = content.reverse.sub(/(?mix)%%(?:(?<mod>.*?):)*(?<key>#{pattern.reverse})/) do
+ content = content.reverse.sub(/(?mix)%%(?:(?<mod>.*?):)*(?<key>#{pattern.reverse})/i) do
m = Regexp.last_match
if m['mod']
m['mod'].reverse.split(/:/).each do |mod|
v = v.apply_mod(mod.normalize_mod)
end
end
v.reverse
end.reverse
else
- rx = /(?mix)%%(?<key>#{k.to_var})#{mod_rx}%%/
+ rx = /(?mix)%%(?<key>#{k.to_var})#{MOD_RX}#{DEFAULT_RX}%%/
content.gsub!(rx) do
m = Regexp.last_match
- mods = m['mod']&.split(/:/)
- mods&.each do |mod|
- v = v.apply_mod(mod.normalize_mod)
+ if m['mod']
+ mods = m['mod']&.split(/:/)
+ mods&.each do |mod|
+ v = v.apply_mod(mod.normalize_mod)
+ end
end
v
end
end
end
content
end
+ #
+ # Handle $varname and ${varname} variable substitutions
+ #
+ # @return [String] String with variables substituted
+ #
+ def apply_var_names
+ sub(/\$\{?(?<varname>\w+)(?<mods>(?::\w+)+)?\}?/) do
+ m = Regexp.last_match
+ if Planter.variables.key?(m['varname'].to_var)
+ Planter.variables[m['varname'].to_var].apply_mods(m['mods'])
+ else
+ m
+ end
+ end
+ end
+
+ #
+ # Apply modifiers to a string
+ #
+ # @param mods [String] Colon separated list of modifiers to apply
+ #
+ # @return [String] string with modifiers applied
+ #
+ def apply_mods(mods)
+ content = dup
+ mods.split(/:/).each do |mod|
+ content.apply_mod!(mod.normalize_mod)
+ end
+ content
+ end
+
##
## Apply regex replacements from @config[:replacements]
##
## @return [String] string with regexes applied
##
- def apply_regexes
+ def apply_regexes(regexes = nil)
content = dup.clean_encode
- return self unless Planter.config.key?(:replacements)
+ regexes = regexes.nil? && Planter.config.key?(:replacements) ? Planter.config[:replacements] : regexes
- Planter.config[:replacements].stringify_keys.each do |pattern, replacement|
+ return self unless regexes
+
+ regexes.stringify_keys.each do |pattern, replacement|
pattern = Regexp.new(pattern) unless pattern.is_a?(Regexp)
replacement = replacement.gsub(/\$(\d)/, '\\\1').apply_variables
content.gsub!(pattern, replacement)
end
content
@@ -175,21 +265,21 @@
##
## @param last_only [Boolean] Only replace the last instance of %%key%%
##
## @return [String] string with variables substituted
##
- def apply_variables!(last_only: false)
- replace apply_variables(last_only: last_only)
+ def apply_variables!(variables: nil, last_only: false)
+ replace apply_variables(variables: variables, last_only: last_only)
end
##
## Destructive version of #apply_regexes
##
## @return [String] string with variables substituted
##
- def apply_regexes!
- replace apply_regexes
+ def apply_regexes!(regexes = nil)
+ replace apply_regexes(regexes)
end
##
## Remove any file extension
##
@@ -220,10 +310,12 @@
##
## Apply a modification to string
##
## @param mod [Symbol] The modifier to apply
##
+ ## @return [String] modified string
+ ##
def apply_mod(mod)
case mod
when :slug
to_slug
when :title_case
@@ -239,10 +331,21 @@
else
self
end
end
+ #
+ # Destructive version of #apply_mod
+ #
+ # @param mod [String] modified string
+ #
+ # @return [<Type>] <description>
+ #
+ def apply_mod!(mod)
+ replace apply_mod(mod)
+ end
+
##
## Convert mod string to symbol
##
## @example "snake" => :snake_case
## @example "cap" => :title_case
@@ -332,12 +435,14 @@
##
## @param type [Symbol] The type
##
##
def coerce(type)
+ type = type.normalize_type
+
case type
when :date
- Chronic.parse(self)
+ Chronic.parse(self).strftime('%Y-%m-%d %H:%M')
when :integer || :number
to_i
when :float
to_f
when :class || :module