Module: BBLib
- Defined in:
- lib/bblib.rb,
lib/os/bbos.rb,
lib/html/tag.rb,
lib/time/cron.rb,
lib/file/bbfile.rb,
lib/opal/bbopal.rb,
lib/time/bbtime.rb,
lib/html/builder.rb,
lib/html/tag_set.rb,
lib/mixins/attrs.rb,
lib/mixins/hooks.rb,
lib/string/cases.rb,
lib/string/roman.rb,
lib/array/bbarray.rb,
lib/bblib/version.rb,
lib/mixins/bridge.rb,
lib/mixins/logger.rb,
lib/string/regexp.rb,
lib/hash_path/proc.rb,
lib/number/bbnumber.rb,
lib/object/bbobject.rb,
lib/string/bbstring.rb,
lib/string/matching.rb,
lib/system/bbsystem.rb,
lib/time/task_timer.rb,
lib/class/effortless.rb,
lib/hash/hash_struct.rb,
lib/mixins/prototype.rb,
lib/mixins/type_init.rb,
lib/logging/bblogging.rb,
lib/mixins/serializer.rb,
lib/mixins/family_tree.rb,
lib/mixins/simple_init.rb,
lib/hash_path/hash_path.rb,
lib/hash_path/path_hash.rb,
lib/hash_path/processors.rb,
lib/string/fuzzy_matcher.rb,
lib/string/pluralization.rb
Overview
This module provides similar functionality as hash path, but instead generates a PathHash object which wraps a Hash or Array. Elements may be accessed via method calls rather than path strings.
Defined Under Namespace
Modules: Attrs, Bridge, Command, Durations, Effortless, FamilyTree, HTML, HashPathProcs, Hooks, Logger, OS, Prototype, Serializer, SimpleInit, TypeInit Classes: Cron, EffortlessClass, FuzzyMatcher, HashPathProc, HashStruct, PathHash, TaskTimer, WrongEngineError
Constant Summary collapse
- CONFIGS_PATH =
'config/'.freeze
- FILE_SIZES =
{ byte: { mult: 1, exp: %w(b byt byte), styles: { short: 'B', long: ' byte' } }, kilobyte: { mult: 1024, exp: %w(kb kilo k kbyte kilobyte), styles: { short: 'kB', long: ' kilobyte' } }, megabyte: { mult: 1024**2, exp: %w(mb mega m mib mbyte megabyte), styles: { short: 'MB', long: ' megabyte' } }, gigabyte: { mult: 1024**3, exp: %w(gb giga g gbyte gigabyte), styles: { short: 'GB', long: ' gigabyte' } }, terabyte: { mult: 1024**4, exp: %w(tb tera t tbyte terabyte), styles: { short: 'TB', long: ' terabyte' } }, petabyte: { mult: 1024**5, exp: %w(pb peta p pbyte petabyte), styles: { short: 'PB', long: ' petabyte' } }, exabyte: { mult: 1024**6, exp: %w(eb exa e ebyte exabyte), styles: { short: 'EB', long: ' exabyte' } }, zettabyte: { mult: 1024**7, exp: %w(zb zetta z zbyte zettabyte), styles: { short: 'ZB', long: ' zettabyte' } }, yottabyte: { mult: 1024**8, exp: %w(yb yotta y ybyte yottabyte), styles: { short: 'YB', long: ' yottabyte' } } }.freeze
- TIME_EXPS =
{ yocto: { mult: 0.000000000000000000001, styles: { long: ' yoctosecond', medium: ' yocto', short: 'ys' }, exp: %w(yoctosecond yocto yoctoseconds yoctos ys) }, zepto: { mult: 0.000000000000000001, styles: { long: ' zeptosecond', medium: ' zepto', short: 'zs' }, exp: %w(zeptosecond zepto zeptoseconds zeptos zs) }, atto: { mult: 0.000000000000001, styles: { long: ' attosecond', medium: ' atto', short: 'as' }, exp: %w(attoseconds atto attoseconds attos as) }, femto: { mult: 0.000000000001, styles: { long: ' femtosecond', medium: ' fempto', short: 'fs' }, exp: %w(femtosecond fempto femtoseconds femptos fs) }, pico: { mult: 0.000000001, styles: { long: ' picosecond', medium: ' pico', short: 'ps' }, exp: %w(picosecond pico picoseconds picos ps) }, nano: { mult: 0.000001, styles: { long: ' nanosecond', medium: ' nano', short: 'ns' }, exp: %w(nanosecond nano nanoseconds nanos ns) }, micro: { mult: 0.001, styles: { long: ' microsecond', medium: ' micro', short: 'μs' }, exp: %W(microsecond micro microseconds micros \u03BCs) }, milli: { mult: 1, styles: { long: ' millisecond', medium: ' mil', short: 'ms' }, exp: %w(ms mil mils milli millis millisecond milliseconds milsec milsecs msec msecs msecond mseconds) }, sec: { mult: 1000, styles: { long: ' second', medium: ' sec', short: 's' }, exp: %w(s sec secs second seconds) }, min: { mult: 60_000, styles: { long: ' minute', medium: ' min', short: 'm' }, exp: %w(m mn mns min mins minute minutes) }, hour: { mult: 3_600_000, styles: { long: ' hour', medium: ' hr', short: 'h' }, exp: %w(h hr hrs hour hours) }, day: { mult: 86_400_000, styles: { long: ' day', medium: ' day', short: 'd' }, exp: %w(d day days) }, week: { mult: 604_800_000, styles: { long: ' week', medium: ' wk', short: 'w' }, exp: %w(w wk wks week weeks) }, month: { mult: 2_592_000_000, styles: { long: ' month', medium: ' mo', short: 'mo' }, exp: %w(mo mon mons month months mnth mnths mth mths) }, year: { mult: 31_536_000_000, styles: { long: ' year', medium: ' yr', short: 'y' }, exp: %w(y yr yrs year years) } }.freeze
- ROMAN_NUMERALS =
{ 1000 => 'M', 900 => 'CM', 500 => 'D', 400 => 'CD', 100 => 'C', 90 => 'XC', 50 => 'L', 40 => 'XL', 10 => 'X', 9 => 'IX', 5 => 'V', 4 => 'IV', 3 => 'III', 2 => 'II', 1 => 'I' }.freeze
- VERSION =
'1.0.2'.freeze
- REGEXP_MODE_HASH =
{ i: Regexp::IGNORECASE, m: Regexp::MULTILINE, x: Regexp::EXTENDED }.freeze
- REGEXP_OPTIONS =
{ i: [:ignore_case, :ignorecase, :i, :case_insensitive, Regexp::IGNORECASE], m: [:multiline, :multi_line, :m, Regexp::MULTILINE], x: [:extended, :x, Regexp::EXTENDED] }.freeze
- NUMBER_WORDS =
{ special: { 0 => nil, 1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five', 6 => 'six', 7 => 'seven', 8 => 'eight', 9 => 'nine', 10 => 'ten', 11 => 'eleven', 12 => 'twleve', 13 => 'thirteen', 14 => 'fourteen', 15 => 'fifteen', 16 => 'sixteen', 17 => 'seventeen', 18 => 'eighteen', 19 => 'nineteen' }, double_range: { 2 => 'twenty', 3 => 'thirty', 4 => 'forty', 5 => 'fifty', 6 => 'sixty', 7 => 'seventy', 8 => 'eighty', 9 => 'ninety' }, ranges: [ nil, 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion' ] }
- SPECIAL_PROGRAMS =
['pry', 'irb.cmd', 'irb'].freeze
- HASH_PATH_PROC_TYPES =
{ evaluate: [:eval, :equation, :equate], debug: [:puts], append: [:suffix], prepend: [:prefix], split: [:delimit, :delim, :separate, :msplit], replace: [:swap], replace_with: [], extract: [:grab, :scan], extract_first: [:grab_first, :scan_first], extract_last: [:grab_last, :scan_last], parse_date: [:date, :parse_time, :time], parse_date_unix: [:unix_time, :unix_date], parse_duration: [:duration], parse_file_size: [:file_size], to_string: [:to_s, :stringify], downcase: [:lower, :lowercase, :to_lower], upcase: [:upper, :uppercase, :to_upper], roman: [:convert_roman, :roman_numeral, :parse_roman], remove_symbols: [:chop_symbols, :drop_symbols], format_articles: [:articles], reverse: [:invert], delete: [:del], remove: [:rem], custom: [:send], encapsulate: [], uncapsulate: [], extract_integers: [:extract_ints, :extract_i], extract_floats: [:extract_f], extract_numbers: [:extract_nums], max_number: [:max, :maximum, :maximum_number], min_number: [:min, :minimum, :minimum_number], avg_number: [:avg, :average, :average_number], sum_number: [:sum], strip: [:trim], concat: [:join, :concat_with], reverse_concat: [:reverse_join, :reverse_concat_with] }.freeze
- SPECIAL_PLURALS =
{ addendum: :addenda, alga: :algae, alumnus: :alumni, amoeba: :amoebae, analysis: :analyses, antenna: :antennae, appendix: :appendices, auto: :autos, axis: :axes, bacterium: :bacteria, barracks: :barracks, basis: :bases, cactus: :cacti, calf: :calves, crisis: :crises, curriculum: :curricula, datum: :data, deer: :deer, diagnosis: :diagnoses, echo: :echoes, elf: :elves, ellipsis: :ellipses, embargo: :embargoes, emphasis: :emphases, fish: :fish, foot: :feet, fungus: :fungi, gallows: :gallows, genus: :genera, goose: :geese, half: :halves, hero: :heroes, hoof: :hooves, hypothesis: :hypotheses, index: :indices, kangaroo: :kangaroos, kilo: :kilos, knife: :knives, larva: :larvae, leaf: :leaves, life: :lives, loaf: :loaves, louse: :lice, man: :men, matrix: :matrices, means: :means, memo: :memos, memorandum: :memoranda, mouse: :mice, neurosis: :neuroses, oasis: :oases, offspring: :offspring, paralysis: :paralyses, parenthesis: :parentheses, person: :people, photo: :photos, piano: :pianos, pimento: :pimentos, potato: :potatoes, pro: :pros, self: :selves, series: :series, sheep: :sheep, shelf: :shelves, solo: :solos, soprano: :sopranos, species: :species, stimulus: :stimuli, studio: :studios, syllabus: :syllabi, tattoo: :tattoos, thesis: :theses, thief: :thieves, tomato: :tomatoes, tooth: :teeth, torpedo: :torpedoes, vertebra: :vertebrae, veto: :vetoes, video: :videos, wife: :wives, wolf: :wolves, woman: :women, zoo: :zoos }
Class Method Summary collapse
- .are_all?(klass, *vars) ⇒ Boolean
-
.average(ary) ⇒ Object
Takes an array and averages all of the floats and integers within it.
- .camel_case(str, style = :lower) ⇒ Object
-
.chars_up_to(str, cap, too_long = '...', style: :front) ⇒ Object
Displays a portion of an object (as a string) with an ellipse displayed if the string is over a certain size.
- .class_case(str) ⇒ Object
-
.cmd_line(*args, include_args: true, include_ruby: true, prefix: nil, suffix: nil) ⇒ Object
A string representation of the command line that evoked this ruby instance (platform agnostic).
-
.composition_similarity(a, b) ⇒ Object
Calculates a percentage based match of two strings based on their character composition.
-
.copy_capitalization(str_a, str_b) ⇒ Object
Takes two strings and tries to apply the same capitalization from the first string to the second.
- .custom_pluralize(num, base, plural = 's', singular = nil) ⇒ Object
- .default_logger ⇒ Object
- .delimited_case(str, delimiter = '_') ⇒ Object
-
.drop_symbols(str) ⇒ Object
Quickly remove any symbols from a string leaving only alpha-numeric characters and white space.
- .enable_logger(enable = true) ⇒ Object
-
.extract_floats(str, convert: true) ⇒ Object
Extracts all integers or decimals from a string into an array.
-
.extract_integers(str, convert: true) ⇒ Object
Extract all integers from a string.
-
.extract_numbers(str, convert: true) ⇒ Object
Extracts any correctly formed integers or floats from a string.
- .from_roman(str) ⇒ Object
- .hash_args(*args) ⇒ Object
- .hash_path(hash, *paths, multi_path: false, multi_join: false, multi_join_hash: false) ⇒ Object
- .hash_path_copy(hash, *paths) ⇒ Object
- .hash_path_copy_to(from, to, *paths) ⇒ Object
- .hash_path_delete(hash, *paths) ⇒ Object
- .hash_path_key_for(hash, value) ⇒ Object
- .hash_path_keys(hash) ⇒ Object
- .hash_path_move(hash, *paths) ⇒ Object
- .hash_path_move_to(from, to, *paths) ⇒ Object
- .hash_path_proc(hash, *args) ⇒ Object
- .hash_path_set(hash, *paths) ⇒ Object
- .in_opal? ⇒ Boolean
- .interleave(ary_a, ary_b) ⇒ Object
- .is_any?(obj, *klasses) ⇒ Boolean
-
.keep_between(num, min, max) ⇒ Object
Used to keep any numeric number between a set of bounds.
-
.levenshtein_distance(a, b) ⇒ Object
A simple rendition of the levenshtein distance algorithm.
-
.levenshtein_similarity(a, b) ⇒ Object
Calculates a percentage based match using the levenshtein distance algorithm.
- .log_enabled? ⇒ Boolean
- .logger ⇒ Object
- .logger=(logger) ⇒ Object
-
.loop_between(num, min, max) ⇒ Object
Similar to keep between but when a number exceeds max or is less than min it is looped to the min or max value respectively.
- .method_case(str) ⇒ Object
-
.most_frequent(*args) ⇒ Object
Returns the element that occurs the most frequently in an array or.
-
.most_frequent_str(*args, case_insensitive: false) ⇒ Object
Returns the most commonly occurring string in an arrray of params.
-
.move_articles(str, position = :front, capitalize: true) ⇒ Object
Used to move the position of the articles ‘the’, ‘a’ and ‘an’ in strings for normalization.
- .named_args(*args) ⇒ Object
- .named_args!(*args) ⇒ Object
- .namespace_of(klass) ⇒ Object
- .number_spelled_out(number, range = 0, include_and: true) ⇒ Object
-
.numeric_similarity(a, b) ⇒ Object
Extracts all numbers from two strings and compares them and generates a percentage of match.
-
.parse_duration(str, output: :sec, min_interval: :sec) ⇒ Object
Parses known time based patterns out of a string to construct a numeric duration.
-
.parse_file_size(str, output: :byte) ⇒ Object
A file size parser for strings.
- .path_hash(hash) ⇒ Object
-
.pathify(*strings) ⇒ Object
Takes one or more strings and normalizes slashes to create a consistent file path Useful when concating two strings that when you don’t know if one or both will end or begin with a slash.
-
.pattern_render(text, context = {}, pattern: /\{{2}.*?\}{2}/, field_pattern: /(?<=^\{{2}).*(?=\}{2})/) ⇒ Object
Pattern render takes (by default) a mustache style template and then uses a context (either a Hash or Object) to then interpolate in placeholders.
-
.phrase_similarity(a, b) ⇒ Object
Calculates a percentage based match between two strings based on the similarity of word matches.
- .plural_string(num, string) ⇒ Object
- .pluralize(string, num = 2) ⇒ Object
-
.qwerty_distance(a, b) ⇒ Object
A simple character distance calculator that uses qwerty key positions to determine how similar two strings are.
- .recursive_send(obj, *methods) ⇒ Object
-
.reload(include_args: true) ⇒ Object
EXPERIMENTAL: Reloads the original file that was called Use at your own risk, this could cause some weird issues.
-
.restart(*args, include_args: true, stay_alive: 1) ⇒ Object
EXPERIMENTAL: Restart the ruby process that is currently running.
- .root_namespace_of(klass) ⇒ Object
-
.scan_dir(path, *filters, recursive: false, files: true, dirs: true, exclude: [], &block) ⇒ Object
Scan for files and directories.
-
.scan_dirs(path, *filters, recursive: false, exclude: [], &block) ⇒ Object
Uses BBLib.scan_dir but returns only directories.
-
.scan_files(path, *filters, recursive: false, exclude: [], &block) ⇒ Object
Uses BBLib.scan_dir but returns only files.
- .singularize(string) ⇒ Object
- .snake_case(str) ⇒ Object
- .special_program? ⇒ Boolean
- .spinal_case(str) ⇒ Object
- .start_case(str, first_only: false) ⇒ Object
-
.string_to_file(str, path, mkpath: true, mode: 'a') ⇒ Object
Shorthand method to write a string to disk.
- .string_to_roman(str) ⇒ Object
- .title_case(str, first_only: true) ⇒ Object
-
.to_duration(num, input: :sec, stop: :milli, style: :medium) ⇒ Object
Turns a numeric input into a time string.
-
.to_file_size(num, input: :byte, stop: :byte, style: :short) ⇒ Object
Takes an integer or float and converts it into a string that represents a file size (e.g. “5 MB 156 kB”).
- .to_hash(obj) ⇒ Object
- .to_nearest_duration(num, input: :sec, style: :medium) ⇒ Object
-
.to_roman(num) ⇒ Object
Converts any integer up to 1000 to a roman numeral.
- .train_case(str) ⇒ Object
Class Method Details
.are_all?(klass, *vars) ⇒ Boolean
2 3 4 |
# File 'lib/object/bbobject.rb', line 2 def self.are_all?(klass, *vars) vars.all? { |var| var.is_a?(klass) } end |
.average(ary) ⇒ Object
Takes an array and averages all of the floats and integers within it. Non numeric values are ignored.
31 32 33 34 35 36 |
# File 'lib/array/bbarray.rb', line 31 def self.average(ary) numbers = ary.select { |v| BBLib.is_any?(v, Integer, Float) } numbers.inject(0) do |sum, x| sum += x end / numbers.size.to_f end |
.camel_case(str, style = :lower) ⇒ Object
35 36 37 38 39 40 |
# File 'lib/string/cases.rb', line 35 def self.camel_case(str, style = :lower) regx = /[[:space:]]+|[^[[:alnum:]]]+/ words = str.split(regx).map(&:capitalize) words[0].downcase! if style == :lower words.join end |
.chars_up_to(str, cap, too_long = '...', style: :front) ⇒ Object
Displays a portion of an object (as a string) with an ellipse displayed if the string is over a certain size. Supported styles:
> front - “for exam…”
> back - “… example”
> middle - “… exam…”
> outter - “for e…ple”
The length of the too_long string is NOT factored into the cap
66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/string/bbstring.rb', line 66 def self.chars_up_to(str, cap, too_long = '...', style: :front) return str if str.to_s.size <= cap str = str.to_s case style when :back "#{too_long}#{str[(str.size - cap)..-1]}" when :outter "#{str[0...(cap / 2).to_i + (cap.odd? ? 1 : 0)]}#{too_long}#{str[-(cap / 2).to_i..-1]}" when :middle "#{too_long}#{str[(str.size / 2 - cap / 2 - (cap.odd? ? 1 : 0)).to_i...(str.size / 2 + cap / 2).to_i]}#{too_long}" else "#{str[0...cap]}#{too_long}" end end |
.class_case(str) ⇒ Object
55 56 57 |
# File 'lib/string/cases.rb', line 55 def self.class_case(str) str.gsub(/(?<=[^^])([A-Z])/, ' \1').gsub(/\s+/, ' ').title_case.gsub(/\s+|\_/, '') end |
.cmd_line(*args, include_args: true, include_ruby: true, prefix: nil, suffix: nil) ⇒ Object
A string representation of the command line that evoked this ruby instance (platform agnostic)
3 4 5 6 7 8 9 |
# File 'lib/system/bbsystem.rb', line 3 def self.cmd_line(*args, include_args: true, include_ruby: true, prefix: nil, suffix: nil) args = ARGV if args.empty? include_ruby = false if special_program? "#{prefix}#{include_ruby ? Command.quote(Gem.ruby) : nil} #{Command.quote($PROGRAM_NAME)}" \ " #{include_args ? args.map { |a| Command.quote(a) }.join(' ') : nil}#{suffix}" .strip end |
.composition_similarity(a, b) ⇒ Object
Calculates a percentage based match of two strings based on their character composition.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/string/matching.rb', line 28 def self.composition_similarity(a, b) if a.length <= b.length t = a a = b b = t end matches = 0 temp = b.dup a.chars.each do |c| if temp.chars.include? c matches+=1 temp = temp.sub(c, '') end end (matches / [a.length, b.length].max.to_f)* 100.0 end |
.copy_capitalization(str_a, str_b) ⇒ Object
Takes two strings and tries to apply the same capitalization from the first string to the second. Supports lower case, upper case and capital case
84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/string/bbstring.rb', line 84 def self.copy_capitalization(str_a, str_b) str_a = str_a.to_s str_b = str_b.to_s if str_a.upper? str_b.upcase elsif str_a.lower? str_b.downcase elsif str_a.capital? str_b.capitalize else str_b end end |
.custom_pluralize(num, base, plural = 's', singular = nil) ⇒ Object
128 129 130 |
# File 'lib/string/pluralization.rb', line 128 def self.custom_pluralize(num, base, plural = 's', singular = nil) num == 1 ? "#{base}#{singular}" : "#{base}#{plural}" end |
.default_logger ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/logging/bblogging.rb', line 9 def self.default_logger log = ::Logger.new(STDOUT) log.level = ::Logger::INFO log.formatter = proc do |severity, datetime, progname, msg| if msg.is_a?(Exception) msg = msg.inspect + "\n\t" + msg.backtrace.join("\n\t") end "[#{datetime}] #{severity} - #{msg.to_s.chomp}\n" end log.datetime_format = '%Y-%m-%d %H:%M:%S' log end |
.delimited_case(str, delimiter = '_') ⇒ Object
42 43 44 45 |
# File 'lib/string/cases.rb', line 42 def self.delimited_case(str, delimiter = '_') regx = /[[:space:]]+|\s+|[^\w\d]+|\#{delimiter}+/ str.split(regx).join(delimiter) end |
.drop_symbols(str) ⇒ Object
Quickly remove any symbols from a string leaving only alpha-numeric characters and white space.
12 13 14 |
# File 'lib/string/bbstring.rb', line 12 def self.drop_symbols(str) str.gsub(/[^\w\s\d]|_/, '') end |
.enable_logger(enable = true) ⇒ Object
27 28 29 |
# File 'lib/logging/bblogging.rb', line 27 def self.enable_logger(enable = true) @logger_on = enable end |
.extract_floats(str, convert: true) ⇒ Object
Extracts all integers or decimals from a string into an array.
23 24 25 26 |
# File 'lib/string/bbstring.rb', line 23 def self.extract_floats(str, convert: true) BBLib.extract_numbers(str, convert: false).reject { |r| !r.include?('.') } .map { |m| convert ? m.to_f : m } end |
.extract_integers(str, convert: true) ⇒ Object
Extract all integers from a string. Use extract_floats if numbers may contain decimal places.
17 18 19 20 |
# File 'lib/string/bbstring.rb', line 17 def self.extract_integers(str, convert: true) BBLib.extract_numbers(str, convert: false).reject { |r| r.include?('.') } .map { |m| convert ? m.to_i : m } end |
.extract_numbers(str, convert: true) ⇒ Object
Extracts any correctly formed integers or floats from a string
29 30 31 32 |
# File 'lib/string/bbstring.rb', line 29 def self.extract_numbers(str, convert: true) str.scan(/\d+\.\d+(?<=[^\.])|\d+(?<=[^\.])|\d+\.\d+$|\d+$/) .map { |f| convert ? (f.include?('.') ? f.to_f : f.to_i) : f } end |
.from_roman(str) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/string/roman.rb', line 30 def self.from_roman(str) sp = str.split(' ') (0..1000).each do |n| num = BBLib.to_roman n next if sp.select { |i| i[/#{num}/i] }.empty? (0..(sp.length-1)).each do |i| sp[i] = sp[i].sub(num, n.to_s) if sp[i].drop_symbols.upcase == num end end sp.join ' ' end |
.hash_args(*args) ⇒ Object
47 48 49 |
# File 'lib/object/bbobject.rb', line 47 def self.hash_args(*args) args.find_all { |a| a.is_a?(Hash) }.each_with_object({}) { |a, h| h.merge!(a) } end |
.hash_path(hash, *paths, multi_path: false, multi_join: false, multi_join_hash: false) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/hash_path/hash_path.rb', line 48 def self.hash_path(hash, *paths, multi_path: false, multi_join: false, multi_join_hash: false) tree = TreeHash.new(hash) if multi_path tree.find_multi(*paths).map { |r| r.map { |sr| sr.value } } elsif multi_join tree.find_join(*paths).map { |r| r.map { |sr| sr.value } } elsif multi_join_hash tree.find_join(*paths).map { |r| r.map { |sr| sr.value } }.to_h else tree.find(paths).map(&:value) end end |
.hash_path_copy(hash, *paths) ⇒ Object
75 76 77 78 79 |
# File 'lib/hash_path/hash_path.rb', line 75 def self.hash_path_copy(hash, *paths) tree = hash.is_a?(TreeHash) ? hash : TreeHash.new(hash) tree.copy(*paths) hash.replace(tree.value) end |
.hash_path_copy_to(from, to, *paths) ⇒ Object
81 82 83 84 |
# File 'lib/hash_path/hash_path.rb', line 81 def self.hash_path_copy_to(from, to, *paths) tree = from.is_a?(TreeHash) ? from : TreeHash.new(from) tree.hash_path_copy_to(to, *paths) end |
.hash_path_delete(hash, *paths) ⇒ Object
86 87 88 89 90 |
# File 'lib/hash_path/hash_path.rb', line 86 def self.hash_path_delete(hash, *paths) tree = hash.is_a?(TreeHash) ? hash : TreeHash.new(hash) tree.delete(*paths) hash.replace(tree.value) end |
.hash_path_key_for(hash, value) ⇒ Object
65 66 67 |
# File 'lib/hash_path/hash_path.rb', line 65 def self.hash_path_key_for(hash, value) hash.squish.find_all { |_k, v| value.is_a?(Regexp) ? v =~ value : v == value }.to_h.keys end |
.hash_path_keys(hash) ⇒ Object
61 62 63 |
# File 'lib/hash_path/hash_path.rb', line 61 def self.hash_path_keys(hash) hash.to_tree_hash.absolute_paths end |
.hash_path_move(hash, *paths) ⇒ Object
92 93 94 95 96 |
# File 'lib/hash_path/hash_path.rb', line 92 def self.hash_path_move(hash, *paths) tree = hash.is_a?(TreeHash) ? hash : TreeHash.new(hash) tree.move(*paths) hash.replace(tree.value) end |
.hash_path_move_to(from, to, *paths) ⇒ Object
98 99 100 101 102 103 104 105 |
# File 'lib/hash_path/hash_path.rb', line 98 def self.hash_path_move_to(from, to, *paths) tree = hash.is_a?(TreeHash) ? hash : TreeHash.new(hash) tree.hash_path_copy_to(to, *paths).tap do |res| from.replace(tree.value) to.replace(res.value) end to end |
.hash_path_proc(hash, *args) ⇒ Object
3 4 5 |
# File 'lib/hash_path/processors.rb', line 3 def self.hash_path_proc(hash, *args) HashPathProc.new(*args).process(hash) end |
.hash_path_set(hash, *paths) ⇒ Object
69 70 71 72 73 |
# File 'lib/hash_path/hash_path.rb', line 69 def self.hash_path_set(hash, *paths) tree = hash.is_a?(TreeHash) ? hash : TreeHash.new(hash) tree.bridge(*paths) hash.replace(tree.value) end |
.in_opal? ⇒ Boolean
2 3 4 |
# File 'lib/opal/bbopal.rb', line 2 def self.in_opal? RUBY_ENGINE == 'opal' end |
.interleave(ary_a, ary_b) ⇒ Object
5 6 7 8 9 10 11 12 |
# File 'lib/array/bbarray.rb', line 5 def self.interleave(ary_a, ary_b) ary = [] [ary_a.size, ary_b.size].max.times do |indx| ary.push(ary_a[indx]) if indx < ary_a.size ary.push(ary_b[indx]) if indx < ary_b.size end ary end |
.is_any?(obj, *klasses) ⇒ Boolean
6 7 8 |
# File 'lib/object/bbobject.rb', line 6 def self.is_any?(obj, *klasses) klasses.any? { |klass| obj.is_a?(klass) } end |
.keep_between(num, min, max) ⇒ Object
Used to keep any numeric number between a set of bounds. Passing nil as min or max represents no bounds in that direction. min and max are inclusive to the allowed bounds.
5 6 7 8 9 10 |
# File 'lib/number/bbnumber.rb', line 5 def self.keep_between(num, min, max) num = num.to_f unless num.is_a?(Numeric) num = min if min && num < min num = max if max && num > max num end |
.levenshtein_distance(a, b) ⇒ Object
A simple rendition of the levenshtein distance algorithm
8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/string/matching.rb', line 8 def self.levenshtein_distance(a, b) costs = (0..b.length).to_a (1..a.length).each do |i| costs[0] = i nw = i - 1 (1..b.length).each do |j| costs[j], nw = [costs[j] + 1, costs[j-1] + 1, a[i-1] == b[j-1] ? nw : nw + 1].min, costs[j] end end costs[b.length] end |
.levenshtein_similarity(a, b) ⇒ Object
Calculates a percentage based match using the levenshtein distance algorithm
21 22 23 24 25 |
# File 'lib/string/matching.rb', line 21 def self.levenshtein_similarity(a, b) distance = BBLib.levenshtein_distance a, b max = [a.length, b.length].max.to_f ((max - distance.to_f) / max) * 100.0 end |
.log_enabled? ⇒ Boolean
31 32 33 |
# File 'lib/logging/bblogging.rb', line 31 def self.log_enabled? @logger_on end |
.logger ⇒ Object
5 6 7 |
# File 'lib/logging/bblogging.rb', line 5 def self.logger @logger ||= default_logger end |
.logger=(logger) ⇒ Object
22 23 24 25 |
# File 'lib/logging/bblogging.rb', line 22 def self.logger=(logger) raise ArgumentError, 'Must be set to a valid logger' unless logger.is_a?(Logger) @logger = logger end |
.loop_between(num, min, max) ⇒ Object
Similar to keep between but when a number exceeds max or is less than min it is looped to the min or max value respectively.
14 15 16 17 18 19 |
# File 'lib/number/bbnumber.rb', line 14 def self.loop_between(num, min, max) num = num.to_f unless num.is_a?(Numeric) num = max if min && num < min num = min if max && num > max num end |
.method_case(str) ⇒ Object
51 52 53 |
# File 'lib/string/cases.rb', line 51 def self.method_case(str) str.gsub(/(?<=[^^])([A-Z])(?=[^A-Z\s])/, '_\1').gsub(/[\s\_]+/, '_').snake_case.downcase end |
.most_frequent(*args) ⇒ Object
Returns the element that occurs the most frequently in an array or
15 16 17 18 19 |
# File 'lib/array/bbarray.rb', line 15 def self.most_frequent(*args) totals = args.each_with_object(Hash.new(0)) { |elem, hash| hash[elem] += 1 } max = totals.values.max totals.keys.find { |key| totals[key] == max } end |
.most_frequent_str(*args, case_insensitive: false) ⇒ Object
Returns the most commonly occurring string in an arrray of params. Elements that are not strings are converted to their string representations.
25 26 27 |
# File 'lib/array/bbarray.rb', line 25 def self.most_frequent_str(*args, case_insensitive: false) most_frequent(*args.map { |arg| case_insensitive ? arg.to_s.downcase : arg.to_s }) end |
.move_articles(str, position = :front, capitalize: true) ⇒ Object
Used to move the position of the articles ‘the’, ‘a’ and ‘an’ in strings for normalization.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/string/bbstring.rb', line 35 def self.move_articles(str, position = :front, capitalize: true) return str unless [:front, :back, :none].include?(position) %w(the a an).each do |a| starts = str.downcase.start_with?(a + ' ') ends = str.downcase.end_with?(' ' + a) if starts && position != :front if position == :none str = str[(a.length + 1)..str.length] elsif position == :back str = str[(a.length + 1)..str.length] + (!ends ? ", #{capitalize ? a.capitalize : a}" : '') end end next unless ends && position != :back if position == :none str = str[0..-(a.length + 2)] elsif position == :front str = (!starts ? "#{capitalize ? a.capitalize : a} " : '') + str[0..-(a.length + 2)] end end str = str.strip.chop while str.strip.end_with?(',') str end |
.named_args(*args) ⇒ Object
35 36 37 |
# File 'lib/object/bbobject.rb', line 35 def self.named_args(*args) args.last.is_a?(Hash) && args.last.keys.all? { |k| k.is_a?(Symbol) } ? args.last : {} end |
.named_args!(*args) ⇒ Object
39 40 41 42 43 44 45 |
# File 'lib/object/bbobject.rb', line 39 def self.named_args!(*args) if args.last.is_a?(Hash) && args.last.keys.all? { |k| k.is_a?(Symbol) } args.delete_at(-1) else {} end end |
.namespace_of(klass) ⇒ Object
58 59 60 61 62 |
# File 'lib/object/bbobject.rb', line 58 def self.namespace_of(klass) split = klass.to_s.split('::') return klass if split.size == 1 Object.const_get(split[0..-2].join('::')) end |
.number_spelled_out(number, range = 0, include_and: true) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/number/bbnumber.rb', line 60 def self.number_spelled_out(number, range = 0, include_and: true) number = number.to_i negative = number.negative? number = number * -1 if negative return 'zero' if number.zero? str = [] three_digit = number > 999 ? number.to_s[-3..-1].to_i : number case three_digit when 1..19 str << NUMBER_WORDS[:special][three_digit] when 20..99 str << NUMBER_WORDS[:double_range][three_digit.to_s[-2].to_i] str << NUMBER_WORDS[:special][three_digit.to_s[-1].to_i] when 100..999 str << NUMBER_WORDS[:special][three_digit.to_s[0].to_i] str << 'hundred' str << 'and' if include_and if three_digit.to_s[-2].to_i == 1 str << NUMBER_WORDS[:special][three_digit.to_s[-2..-1].to_i] else str << NUMBER_WORDS[:double_range][three_digit.to_s[-2].to_i] str << NUMBER_WORDS[:special][three_digit.to_s[-1].to_i] end end str << NUMBER_WORDS[:ranges][range] unless str.compact.empty? (negative ? 'negative ' : '') + ((number.to_s.size > 3 ? "#{number_spelled_out(number.to_s[0..-4].to_i, range + 1)} " : '') + str.compact.join(' ')).gsub(/\s+/, ' ') end |
.numeric_similarity(a, b) ⇒ Object
Extracts all numbers from two strings and compares them and generates a percentage of match. Percentage calculations here need to be weighted better…TODO
60 61 62 63 64 65 66 67 68 69 |
# File 'lib/string/matching.rb', line 60 def self.numeric_similarity(a, b) a = a.extract_numbers b = b.extract_numbers return 100.0 if a.empty? && b.empty? || a == b matches = [] (0..[a.size, b.size].max-1).each do |i| matches << 1.0 / ([a[i].to_f, b[i].to_f].max - [a[i].to_f, b[i].to_f].min + 1.0) end (matches.inject { |sum, m| sum + m } / matches.size.to_f) * 100.0 end |
.parse_duration(str, output: :sec, min_interval: :sec) ⇒ Object
Parses known time based patterns out of a string to construct a numeric duration.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/time/bbtime.rb', line 7 def self.parse_duration(str, output: :sec, min_interval: :sec) msecs = 0.0 # Parse time expressions such as 04:05. # The argument min_interval controls what time interval the final number represents str.scan(/\d+\:[\d+\:]+\d+/).each do |e| keys = TIME_EXPS.keys position = keys.index(min_interval) e.split(':').reverse.each do |sec| key = keys[position] msecs+= sec.to_f * TIME_EXPS[key][:mult] position+=1 end end # Parse expressions such as '1m' or '1 min' TIME_EXPS.each do |_k, v| v[:exp].each do |e| numbers = str.downcase.scan(/(?=\w|\D|\A)\d*\.?\d+[[:space:]]*#{e}(?=\W|\d|\z)/i) numbers.each do |n| msecs+= n.to_f * v[:mult] end end end msecs / TIME_EXPS[output][:mult] end |
.parse_file_size(str, output: :byte) ⇒ Object
A file size parser for strings. Extracts any known patterns for file sizes.
58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/file/bbfile.rb', line 58 def self.parse_file_size(str, output: :byte) output = FILE_SIZES.keys.find { |fs| fs == output || FILE_SIZES[fs][:exp].include?(output.to_s.downcase) } || :byte bytes = 0.0 FILE_SIZES.each do |_k, v| v[:exp].each do |exp| str.scan(/(?=\w|\D|^)\d*\.?\d+\s*#{exp}s?(?=\W|\d|$)/i) .each { |num| bytes += num.to_f * v[:mult] } end end bytes / FILE_SIZES[output][:mult] end |
.path_hash(hash) ⇒ Object
8 9 10 |
# File 'lib/hash_path/path_hash.rb', line 8 def self.path_hash(hash) PathHash.new(hash) end |
.pathify(*strings) ⇒ Object
Takes one or more strings and normalizes slashes to create a consistent file path Useful when concating two strings that when you don’t know if one or both will end or begin with a slash
5 6 7 |
# File 'lib/file/bbfile.rb', line 5 def self.pathify(*strings) (strings.first.start_with?('/', '\\') ? strings.first.scan(/^[\/\\]{1,2}/).first : '') + strings.map(&:to_s).msplit('/', '\\').map(&:strip).join('/') end |
.pattern_render(text, context = {}, pattern: /\{{2}.*?\}{2}/, field_pattern: /(?<=^\{{2}).*(?=\}{2})/) ⇒ Object
Pattern render takes (by default) a mustache style template and then uses a context (either a Hash or Object) to then interpolate in placeholders. The default pattern looks for {method_name} within the string but can be customized to a different pattern by setting the pattern named argument.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/string/bbstring.rb', line 102 def self.pattern_render(text, context = {}, pattern: /\{{2}.*?\}{2}/, field_pattern: /(?<=^\{{2}).*(?=\}{2})/) raise ArgumentError, "Expected text argument to be a String, got a #{text.class}" unless text.is_a?(String) txt = text.dup txt.scan(pattern).each do |match| field = match.scan(field_pattern).first next unless field value = case context when Hash context[field.to_sym] || context[field] else context.send(field) if context.respond_to?(field) end.to_s txt.sub!(match, value) end txt end |
.phrase_similarity(a, b) ⇒ Object
Calculates a percentage based match between two strings based on the similarity of word matches.
46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/string/matching.rb', line 46 def self.phrase_similarity(a, b) temp = b.drop_symbols.split ' ' matches = 0 a.drop_symbols.split(' ').each do |w| if temp.include? w matches+=1 temp.delete_at temp.find_index w end end (matches.to_f / [a.split(' ').size, b.split(' ').size].max.to_f) * 100.0 end |
.plural_string(num, string) ⇒ Object
132 133 134 |
# File 'lib/string/pluralization.rb', line 132 def self.plural_string(num, string) "#{num} #{pluralize(string, num)}" end |
.pluralize(string, num = 2) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/string/pluralization.rb', line 91 def self.pluralize(string, num = 2) full_string = string.to_s string = string.split(/\s+/).last sym = string.to_s.downcase.to_sym if plural = SPECIAL_PLURALS[sym] result = num == 1 ? string : plural else if string.end_with?(*%w{ch z s x o}) result = num == 1 ? string : (string + 'es') elsif string =~ /[^aeiou]y$/i result = num == 1 ? string : string.sub(/y$/i, 'ies') else result = num == 1 ? string : (string + 's') end end full_string.sub(/#{Regexp.escape(string)}$/, copy_capitalization(string, result).to_s) end |
.qwerty_distance(a, b) ⇒ Object
A simple character distance calculator that uses qwerty key positions to determine how similar two strings are. May be useful for typo detection.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/string/matching.rb', line 73 def self.qwerty_distance(a, b) a = a.downcase.strip b = b.downcase.strip if a.length <= b.length t = a a = b b = t end qwerty = { 1 => %w(1 2 3 4 5 6 7 8 9 0), 2 => %w(q w e r t y u i o p), 3 => %w(a s d f g h j k l), 4 => %w(z x c v b n m) } count = 0 offset = 0 a.chars.each do |c| if b.length <= count offset+=10 else ai = qwerty.keys.find { |f| qwerty[f].include? c }.to_i bi = qwerty.keys.find { |f| qwerty[f].include? b.chars[count] }.to_i offset+= (ai - bi).abs offset+= (qwerty[ai].index(c) - qwerty[bi].index(b.chars[count])).abs end count+=1 end offset end |
.recursive_send(obj, *methods) ⇒ Object
51 52 53 54 55 56 |
# File 'lib/object/bbobject.rb', line 51 def self.recursive_send(obj, *methods) methods.each do |args| obj = obj.send(*args) end obj end |
.reload(include_args: true) ⇒ Object
EXPERIMENTAL: Reloads the original file that was called Use at your own risk, this could cause some weird issues
13 14 15 16 |
# File 'lib/system/bbsystem.rb', line 13 def self.reload(include_args: true) return false if special_program? load cmd_line(*args, include_ruby: false, include_args: include_args) end |
.restart(*args, include_args: true, stay_alive: 1) ⇒ Object
EXPERIMENTAL: Restart the ruby process that is currently running. Use at your own risk
20 21 22 23 24 25 26 27 28 |
# File 'lib/system/bbsystem.rb', line 20 def self.restart(*args, include_args: true, stay_alive: 1) exit(0) rescue SystemExit opts = BBLib::OS.windows? ? { new_pgroup: true } : { pgroup: true } pid = spawn(cmd_line(*args, include_args: include_args, prefix: (BBLib::OS.windows? ? 'start ' : nil)), **opts) Process.detach(pid) sleep(stay_alive) exit(0) if special_program? end |
.root_namespace_of(klass) ⇒ Object
64 65 66 |
# File 'lib/object/bbobject.rb', line 64 def self.root_namespace_of(klass) Object.const_get(klass.to_s.gsub(/::.*/, '')) end |
.scan_dir(path, *filters, recursive: false, files: true, dirs: true, exclude: [], &block) ⇒ Object
Scan for files and directories. Can be set to be recursive and can also have filters applied.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/file/bbfile.rb', line 17 def self.scan_dir(path, *filters, recursive: false, files: true, dirs: true, exclude: [], &block) return [] unless Dir.exist?(path) filters = filters.map { |filter| filter.is_a?(Regexp) ? filter : /^#{Regexp.quote(filter).gsub('\\*', '.*')}$/ } exclude = exclude ? [exclude].flatten.map { |exp| exp.is_a?(Regexp) ? exp : /^#{Regexp.quote(exp).gsub('\\*', '.*')}$/ } : [] Dir.foreach(path).flat_map do |item| next if item =~ /^\.{1,2}$/ || (!exclude.empty? && exclude.any? { |exp| item =~ exp }) item = "#{path}/#{item}".gsub('\\', '/') if File.file?(item) if files && (filters.empty? || filters.any? { |filter| item =~ filter }) block_given? ? yield(item) : item end elsif File.directory?(item) recur = recursive ? scan_dir(item, *filters, recursive: recursive, exclude: exclude, files: files, dirs: dirs, &block) : [] if dirs && (filters.empty? || filters.any? { |filter| item =~ filter }) (block_given? ? yield(item) : [item] + recur) elsif recursive recur end end end.compact end |
.scan_dirs(path, *filters, recursive: false, exclude: [], &block) ⇒ Object
Uses BBLib.scan_dir but returns only directories.
45 46 47 |
# File 'lib/file/bbfile.rb', line 45 def self.scan_dirs(path, *filters, recursive: false, exclude: [], &block) scan_dir(path, *filters, recursive: recursive, files: false, exclude: exclude, &block) end |
.scan_files(path, *filters, recursive: false, exclude: [], &block) ⇒ Object
Uses BBLib.scan_dir but returns only files
40 41 42 |
# File 'lib/file/bbfile.rb', line 40 def self.scan_files(path, *filters, recursive: false, exclude: [], &block) scan_dir(path, *filters, recursive: recursive, dirs: false, exclude: exclude, &block) end |
.singularize(string) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/string/pluralization.rb', line 109 def self.singularize(string) full_string = string.to_s string = string.split(/\s+/).last sym = string.to_s.downcase.to_sym sym = string.to_s.downcase.to_sym if singular = SPECIAL_PLURALS.find { |k, v| v == sym } result = singular.first elsif string.downcase.end_with?(*%w{oes ches zes ses xes}) result = string.sub(/es$/i, '') elsif string =~ /ies$/i result = string.sub(/ies$/i, 'y') elsif string =~ /s$/i && !(string =~ /s{2}$/i) result = string.sub(/s$/i, '') else result = string end full_string.sub(/#{Regexp.escape(string)}$/, copy_capitalization(string, result).to_s) end |
.snake_case(str) ⇒ Object
47 48 49 |
# File 'lib/string/cases.rb', line 47 def self.snake_case(str) BBLib.delimited_case(str, '_') end |
.special_program? ⇒ Boolean
32 33 34 |
# File 'lib/system/bbsystem.rb', line 32 def self.special_program? SPECIAL_PROGRAMS.include?($PROGRAM_NAME) end |
.spinal_case(str) ⇒ Object
59 60 61 |
# File 'lib/string/cases.rb', line 59 def self.spinal_case(str) BBLib.delimited_case str, '-' end |
.start_case(str, first_only: false) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/string/cases.rb', line 21 def self.start_case(str, first_only: false) regx = /[[:space:]]+|\-|\_|\"|\'|\(|\)|\[|\]|\{|\}|\#/ spacing = str.scan(regx).to_a words = str.split(regx).map do |word| if first_only word[0] = word[0].upcase word else word.capitalize end end words.interleave(spacing).join end |
.string_to_file(str, path, mkpath: true, mode: 'a') ⇒ Object
Shorthand method to write a string to disk. By default the path is created if it doesn’t exist. Set mode to w to truncate file or leave at a to append.
52 53 54 55 |
# File 'lib/file/bbfile.rb', line 52 def self.string_to_file(str, path, mkpath: true, mode: 'a') FileUtils.mkpath(File.dirname(path)) if mkpath && !Dir.exist?(path) File.write(path, str.to_s, mode: mode) end |
.string_to_roman(str) ⇒ Object
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/string/roman.rb', line 19 def self.string_to_roman(str) sp = str.split ' ' sp.map do |s| if s.drop_symbols.to_i.to_s == s.drop_symbols && !(s =~ /\d+\.\d+/) s.sub(s.scan(/\d+/).first.to_s, BBLib.to_roman(s.to_i)) else s end end.join(' ') end |
.title_case(str, first_only: true) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/string/cases.rb', line 2 def self.title_case(str, first_only: true) str = str.to_s unless str.is_a?(String) ignoreables = %w(a an the on upon and but or in with to) regx = /\s+|\-|\_|(?<=\W|^)\"(?=\w|$)|(?<=\W|^)\'(?=\w|$)|\(|\)|\[|\]|\{|\}|\#/ spacing = str.scan(regx).to_a words = str.split(regx).map do |word| if ignoreables.include?(word.downcase) word.downcase elsif first_only word.to_s.slice(0,1).to_s.upcase + word.to_s[1..-1].to_s else word.capitalize end end # Always cap the first word words[0] = words.first.to_s.slice(0,1).to_s.upcase + words.first.to_s[1..-1].to_s words.interleave(spacing).join end |
.to_duration(num, input: :sec, stop: :milli, style: :medium) ⇒ Object
Turns a numeric input into a time string.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/time/bbtime.rb', line 35 def self.to_duration(num, input: :sec, stop: :milli, style: :medium) return nil unless num.is_a?(Numeric) return '0' if num.zero? style = :medium unless [:long, :medium, :short].include?(style) expression = [] n = num * TIME_EXPS[input.to_sym][:mult] done = false TIME_EXPS.reverse.each do |k, v| next if done done = true if k == stop div = n / v[:mult] next unless div >= 1 val = (done ? div.round : div.floor) expression << "#{val}#{v[:styles][style]}#{val > 1 && style != :short ? 's' : nil}" n -= val.to_f * v[:mult] end expression.join(' ') end |
.to_file_size(num, input: :byte, stop: :byte, style: :short) ⇒ Object
Takes an integer or float and converts it into a string that represents
a file size (e.g. "5 MB 156 kB")
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/file/bbfile.rb', line 77 def self.to_file_size(num, input: :byte, stop: :byte, style: :short) return nil unless num.is_a?(Numeric) return '0' if num.zero? style = :short unless [:long, :short].include?(style) expression = [] n = num * FILE_SIZES[input.to_sym][:mult] done = false FILE_SIZES.reverse.each do |k, v| next if done done = true if k == stop div = n / v[:mult] next unless div >= 1 val = (done ? div.round : div.floor) expression << "#{val}#{v[:styles][style]}#{val > 1 && style != :short ? 's' : nil}" n -= val.to_f * v[:mult] end expression.join(' ') end |
.to_hash(obj) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/object/bbobject.rb', line 10 def self.to_hash(obj) return { obj => nil } if obj.instance_variables.empty? hash = {} obj.instance_variables.each do |var| value = obj.instance_variable_get(var) if value.is_a?(Array) hash[var.to_s.delete('@')] = value.map { |v| v.respond_to?(:obj_to_hash) && !v.instance_variables.empty? ? v.obj_to_hash : v } elsif value.is_a?(Hash) begin unless hash[var.to_s.delete('@')].is_a?(Hash) then hash[var.to_s.delete('@')] = {} end rescue hash[var.to_s.delete('@')] = {} end value.each do |k, v| hash[var.to_s.delete('@')][k.to_s.delete('@')] = v.respond_to?(:obj_to_hash) && !v.instance_variables.empty? ? v.obj_to_hash : v end elsif value.respond_to?(:obj_to_hash) && !value.instance_variables.empty? hash[var.to_s.delete('@')] = value.obj_to_hash else hash[var.to_s.delete('@')] = value end end hash end |
.to_nearest_duration(num, input: :sec, style: :medium) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/time/bbtime.rb', line 54 def self.to_nearest_duration(num, input: :sec, style: :medium) n = num * TIME_EXPS[input.to_sym][:mult] stop = nil TIME_EXPS.each do |k, v| stop = k if v[:mult] <= n end stop = :year unless stop to_duration(num, input: input, style: style, stop: stop) end |
.to_roman(num) ⇒ Object
Converts any integer up to 1000 to a roman numeral
7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/string/roman.rb', line 7 def self.to_roman(num) return num.to_s if num > 1000 numeral = '' ROMAN_NUMERALS.each do |n, r| while num >= n num -= n numeral += r end end numeral end |
.train_case(str) ⇒ Object
63 64 65 |
# File 'lib/string/cases.rb', line 63 def self.train_case(str) BBLib.spinal_case(BBLib.start_case(str)) end |