bblib 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +11 -10
- data/.rspec +2 -2
- data/.travis.yml +4 -4
- data/CODE_OF_CONDUCT.md +13 -13
- data/Gemfile +4 -4
- data/LICENSE.txt +21 -21
- data/README.md +247 -757
- data/Rakefile +6 -6
- data/bblib.gemspec +34 -34
- data/bin/console +14 -14
- data/bin/setup +7 -7
- data/lib/array/bbarray.rb +71 -29
- data/lib/bblib.rb +12 -12
- data/lib/bblib/version.rb +3 -3
- data/lib/class/effortless.rb +23 -0
- data/lib/error/abstract.rb +3 -0
- data/lib/file/bbfile.rb +93 -52
- data/lib/hash/bbhash.rb +130 -46
- data/lib/hash/hash_struct.rb +24 -0
- data/lib/hash/tree_hash.rb +364 -0
- data/lib/hash_path/hash_path.rb +210 -0
- data/lib/hash_path/part.rb +83 -0
- data/lib/hash_path/path_hash.rb +84 -0
- data/lib/hash_path/proc.rb +93 -0
- data/lib/hash_path/processors.rb +239 -0
- data/lib/html/bbhtml.rb +2 -0
- data/lib/html/builder.rb +34 -0
- data/lib/html/tag.rb +49 -0
- data/lib/logging/bblogging.rb +42 -0
- data/lib/mixins/attrs.rb +422 -0
- data/lib/mixins/bbmixins.rb +7 -0
- data/lib/mixins/bridge.rb +17 -0
- data/lib/mixins/family_tree.rb +41 -0
- data/lib/mixins/hooks.rb +139 -0
- data/lib/mixins/logger.rb +31 -0
- data/lib/mixins/serializer.rb +71 -0
- data/lib/mixins/simple_init.rb +160 -0
- data/lib/number/bbnumber.rb +15 -7
- data/lib/object/bbobject.rb +46 -19
- data/lib/opal/bbopal.rb +0 -4
- data/lib/os/bbos.rb +24 -16
- data/lib/os/bbsys.rb +60 -43
- data/lib/string/bbstring.rb +165 -66
- data/lib/string/cases.rb +37 -29
- data/lib/string/fuzzy_matcher.rb +48 -50
- data/lib/string/matching.rb +43 -30
- data/lib/string/pluralization.rb +156 -0
- data/lib/string/regexp.rb +45 -0
- data/lib/string/roman.rb +17 -30
- data/lib/system/bbsystem.rb +42 -0
- data/lib/time/bbtime.rb +79 -58
- data/lib/time/cron.rb +174 -132
- data/lib/time/task_timer.rb +86 -70
- metadata +27 -10
- data/lib/gem/bbgem.rb +0 -28
- data/lib/hash/hash_path.rb +0 -344
- data/lib/hash/hash_path_proc.rb +0 -256
- data/lib/hash/path_hash.rb +0 -81
- data/lib/object/attr.rb +0 -182
- data/lib/object/hooks.rb +0 -69
- data/lib/object/lazy_class.rb +0 -73
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require "rspec/core/rake_task"
|
3
|
-
|
4
|
-
RSpec::Core::RakeTask.new(:spec)
|
5
|
-
|
6
|
-
task :default => :spec
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
task :default => :spec
|
data/bblib.gemspec
CHANGED
@@ -1,34 +1,34 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'bblib/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "bblib"
|
8
|
-
spec.version = BBLib::VERSION
|
9
|
-
spec.authors = ["Brandon Black"]
|
10
|
-
spec.email = ["d2sm10@hotmail.com"]
|
11
|
-
|
12
|
-
spec.summary = %q{A library containing many reusable, basic functions.}
|
13
|
-
spec.description = %q{A library containing many reusable, basic functions.}
|
14
|
-
spec.homepage = "https://github.com/bblack16/bblib-ruby"
|
15
|
-
spec.license = "MIT"
|
16
|
-
|
17
|
-
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
-
# delete this section to allow pushing this gem to any host.
|
19
|
-
# if spec.respond_to?(:metadata)
|
20
|
-
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
-
# else
|
22
|
-
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
-
# end
|
24
|
-
|
25
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) || f.end_with?('.gem') }
|
26
|
-
spec.bindir = "exe"
|
27
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
-
spec.require_paths = ["lib"]
|
29
|
-
|
30
|
-
spec.add_development_dependency "bundler", "~> 1.10"
|
31
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
-
spec.add_development_dependency "rspec"
|
33
|
-
spec.add_development_dependency "simplecov"
|
34
|
-
end
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bblib/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bblib"
|
8
|
+
spec.version = BBLib::VERSION
|
9
|
+
spec.authors = ["Brandon Black"]
|
10
|
+
spec.email = ["d2sm10@hotmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A library containing many reusable, basic functions.}
|
13
|
+
spec.description = %q{A library containing many reusable, basic functions.}
|
14
|
+
spec.homepage = "https://github.com/bblack16/bblib-ruby"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
# if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
# else
|
22
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
# end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) || f.end_with?('.gem') }
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
31
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
+
spec.add_development_dependency "rspec"
|
33
|
+
spec.add_development_dependency "simplecov"
|
34
|
+
end
|
data/bin/console
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "bblib"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "bblib"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
#!/bin/bash
|
2
|
-
set -euo pipefail
|
3
|
-
IFS=$'\n\t'
|
4
|
-
|
5
|
-
bundle install
|
6
|
-
|
7
|
-
# Do any other automated setup that you need to do here
|
1
|
+
#!/bin/bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
|
5
|
+
bundle install
|
6
|
+
|
7
|
+
# Do any other automated setup that you need to do here
|
data/lib/array/bbarray.rb
CHANGED
@@ -1,50 +1,92 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
module BBLib
|
3
|
-
|
4
|
-
#
|
5
|
-
def self.interleave
|
6
|
-
ary =
|
7
|
-
[
|
8
|
-
ary.push(
|
9
|
-
ary.push(
|
3
|
+
# Takes two arrays (can be of different length) and interleaves
|
4
|
+
# them like [a[0], b[0], a[1], b[1]...]
|
5
|
+
def self.interleave(ary_a, ary_b)
|
6
|
+
ary = []
|
7
|
+
[ary_a.size, ary_b.size].max.times do |indx|
|
8
|
+
ary.push(ary_a[indx]) if indx < ary_a.size
|
9
|
+
ary.push(ary_b[indx]) if indx < ary_b.size
|
10
10
|
end
|
11
11
|
ary
|
12
12
|
end
|
13
13
|
|
14
|
+
# Returns the element that occurs the most frequently in an array or
|
15
|
+
def self.most_frequent(*args)
|
16
|
+
totals = args.each_with_object(Hash.new(0)) { |elem, hash| hash[elem] += 1 }
|
17
|
+
max = totals.values.max
|
18
|
+
totals.keys.find { |key| totals[key] == max }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the most commonly occurring string in an arrray of params.
|
22
|
+
# Elements that are not strings are converted to their string representations.
|
23
|
+
#
|
24
|
+
# @param [TrueClass, FalseClass] case_insensitive Compare strings case isensitively.
|
25
|
+
def self.most_frequent_str(*args, case_insensitive: false)
|
26
|
+
most_frequent(*args.map { |arg| case_insensitive ? arg.to_s.downcase : arg.to_s })
|
27
|
+
end
|
28
|
+
|
29
|
+
# Takes an array and averages all of the floats and integers within it.
|
30
|
+
# Non numeric values are ignored.
|
31
|
+
def self.average(ary)
|
32
|
+
numbers = ary.select { |v| BBLib.is_a?(v, Integer, Float) }
|
33
|
+
numbers.inject(0) do |sum, x|
|
34
|
+
sum += x
|
35
|
+
end / numbers.size.to_f
|
36
|
+
end
|
14
37
|
end
|
15
38
|
|
39
|
+
# Monkey Patches for the Array class
|
16
40
|
class Array
|
41
|
+
# Splits all elements in an array using a list of delimiters.
|
42
|
+
def msplit(*delims)
|
43
|
+
map { |elem| elem.msplit(*delims) if elem.respond_to?(:msplit) }.flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
alias multi_split msplit
|
47
|
+
|
48
|
+
# Converts all keys in nested hashes to symbols.
|
49
|
+
def keys_to_sym(clean: false)
|
50
|
+
map { |elem| elem.respond_to?(:keys_to_sym) ? elem.keys_to_sym(clean: clean) : elem }
|
51
|
+
end
|
17
52
|
|
18
|
-
|
19
|
-
|
53
|
+
# Converts all keys in nested hashes to strings.
|
54
|
+
def keys_to_s
|
55
|
+
map { |v| v.respond_to?(:keys_to_s) ? v.keys_to_s : v }
|
20
56
|
end
|
21
|
-
alias_method :multi_split, :msplit
|
22
57
|
|
23
|
-
|
24
|
-
|
58
|
+
# Takes two arrays (can be of different length) and interleaves
|
59
|
+
# them like [a[0], b[0], a[1], b[1]...]
|
60
|
+
def interleave(ary)
|
61
|
+
BBLib.interleave(self, ary)
|
25
62
|
end
|
26
63
|
|
27
|
-
|
28
|
-
|
64
|
+
# Displays all elements between this hash and another hash that are different.
|
65
|
+
# @param [Array] ary The ary to compare elements to.
|
66
|
+
def diff(ary)
|
67
|
+
(self - ary) + (ary - self)
|
29
68
|
end
|
30
69
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
value = nested ? v.to_xml(level:level + 1, key:key) : v
|
35
|
-
"\t" * level + "<#{key}>\n" +
|
36
|
-
(nested ? '' : "\t"*(level+1)) +
|
37
|
-
"#{value}\n" +
|
38
|
-
"\t"*level + "</#{key}>\n"
|
39
|
-
end.join
|
70
|
+
# Creates a tree hash wrapper for this array.
|
71
|
+
def to_tree_hash
|
72
|
+
TreeHash.new(self)
|
40
73
|
end
|
41
74
|
|
42
|
-
|
43
|
-
|
75
|
+
# Conventient way to join an array into a comma seperated list with the last two elements
|
76
|
+
# seperated by a word like 'and' or 'or'.
|
77
|
+
# @param seperator [String] The term or phrase to seperate the last two elements by
|
78
|
+
# @param delimiter [String] The delimiter used in the join. This allows something other than ', ' to be used
|
79
|
+
# @param encapsulate [String] This will optionally encapsulate each element with a character or string. Useful to wrap all elements in quotes.
|
80
|
+
# @returns [String] By default returns a comma seperated list with the final elements seperated by an 'and'. Behavior can be overriden using the params.
|
81
|
+
def join_terms(seperator = :and, delimiter: ', ', encapsulate: nil)
|
82
|
+
elements = (encapsulate ? map { |element| element.to_s.encapsulate(encapsulate) } : self)
|
83
|
+
return elements.join(delimiter) if size <= 1
|
84
|
+
return elements.join(" #{seperator} ") if size == 2
|
85
|
+
[elements[0..-2].join(delimiter), elements.last].join(" #{seperator} ")
|
44
86
|
end
|
45
87
|
|
46
|
-
def
|
47
|
-
|
88
|
+
def hmap
|
89
|
+
return map unless block_given?
|
90
|
+
map { |v| yield(v) }.to_h
|
48
91
|
end
|
49
|
-
|
50
92
|
end
|
data/lib/bblib.rb
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
require_relative 'bblib/version'
|
2
2
|
require_relative 'opal/bbopal'
|
3
3
|
require_relative 'object/bbobject'
|
4
|
-
require_relative '
|
4
|
+
require_relative 'hash/bbhash'
|
5
|
+
require_relative 'mixins/bbmixins'
|
6
|
+
require_relative 'class/effortless'
|
7
|
+
require_relative 'hash_path/hash_path'
|
5
8
|
require_relative 'string/bbstring'
|
6
9
|
require_relative 'file/bbfile'
|
7
10
|
require_relative 'time/bbtime'
|
8
|
-
require_relative 'hash/bbhash'
|
9
|
-
require_relative 'gem/bbgem'
|
10
11
|
require_relative 'number/bbnumber'
|
11
12
|
require_relative 'array/bbarray'
|
13
|
+
require_relative 'system/bbsystem'
|
14
|
+
require_relative 'logging/bblogging'
|
15
|
+
require_relative 'error/abstract'
|
16
|
+
require_relative 'html/bbhtml'
|
12
17
|
|
13
|
-
non_opal = ['os/bbos'
|
14
|
-
|
15
|
-
unless BBLib::in_opal?
|
16
|
-
non_opal.each{ |i| require_relative i }
|
17
|
-
end
|
18
|
+
non_opal = ['os/bbos']
|
18
19
|
|
20
|
+
non_opal.each { |i| require_relative i } unless BBLib.in_opal?
|
19
21
|
|
20
22
|
require 'fileutils'
|
21
|
-
|
23
|
+
require 'time'
|
22
24
|
|
23
25
|
module BBLib
|
24
|
-
|
25
|
-
CONFIGS_PATH = 'config/'
|
26
|
-
|
26
|
+
CONFIGS_PATH = 'config/'.freeze
|
27
27
|
end
|
data/lib/bblib/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module BBLib
|
2
|
-
VERSION =
|
3
|
-
end
|
1
|
+
module BBLib
|
2
|
+
VERSION = '0.4.1'.freeze
|
3
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module BBLib
|
3
|
+
module Effortless
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(BBLib::Attrs)
|
6
|
+
base.extend(BBLib::Hooks)
|
7
|
+
base.singleton_class.extend(BBLib::Hooks)
|
8
|
+
base.extend(BBLib::FamilyTree) unless BBLib.in_opal?
|
9
|
+
base.extend(BBLib::Bridge)
|
10
|
+
base.send(:include, BBLib::Serializer)
|
11
|
+
base.send(:include, BBLib::SimpleInit)
|
12
|
+
base.send(:include, BBLib::Logger)
|
13
|
+
end
|
14
|
+
|
15
|
+
def _attrs
|
16
|
+
self.class._attrs
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class EffortlessClass
|
21
|
+
include Effortless
|
22
|
+
end
|
23
|
+
end
|
data/lib/file/bbfile.rb
CHANGED
@@ -1,91 +1,132 @@
|
|
1
1
|
|
2
|
-
|
3
2
|
module BBLib
|
4
|
-
|
5
3
|
# Takes one or more strings and normalizes slashes to create a consistent file path
|
6
4
|
# Useful when concating two strings that when you don't know if one or both will end or begin with a slash
|
7
|
-
def self.pathify
|
8
|
-
|
9
|
-
(start ? '/' : '' ) + strings.map(&:to_s).msplit('/', '\\').map(&:strip).join('/')
|
5
|
+
def self.pathify(*strings)
|
6
|
+
(strings.first.start_with?('/', '\\') ? '/' : '') + strings.map(&:to_s).msplit('/', '\\').map(&:strip).join('/')
|
10
7
|
end
|
11
8
|
|
12
9
|
# Scan for files and directories. Can be set to be recursive and can also have filters applied.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
# @param [String] path The directory to scan files from.
|
11
|
+
# @param [String..., Regexp...] filters A list of filters to apply. Can be regular expressions or strings.
|
12
|
+
# Strings with a * are treated as regular expressions with a .*. If no filters are passed, all files/dirs are returned.
|
13
|
+
# @param [Boolean] recursive When true scan will recursively search directories
|
14
|
+
# @param [Boolean] files If true, paths to files matching the filter will be returned.
|
15
|
+
# @param [Boolean] dirs If true, paths to dirs matching the filter will be returned.
|
16
|
+
def self.scan_dir(path, *filters, recursive: false, files: true, dirs: true, &block)
|
17
|
+
return [] unless Dir.exist?(path)
|
18
|
+
filters = filters.map { |filter| filter.is_a?(Regexp) ? filter : /^#{Regexp.quote(filter).gsub('\\*', '.*')}$/ }
|
19
|
+
Dir.foreach(path).flat_map do |item|
|
20
|
+
next if item =~ /^\.{1,2}$/
|
21
|
+
item = "#{path}/#{item}".gsub('\\', '/')
|
22
|
+
if File.file?(item)
|
23
|
+
if files && (filters.empty? || filters.any? { |filter| item =~ filter })
|
24
|
+
block_given? ? yield(item) : item
|
25
|
+
end
|
26
|
+
elsif File.directory?(item)
|
27
|
+
recur = recursive ? scan_dir(item, *filters, recursive: recursive, files: files, dirs: dirs, &block) : []
|
28
|
+
if dirs && (filters.empty? || filters.any? { |filter| item =~ filter })
|
29
|
+
(block_given? ? yield(item) : [item] + recur)
|
30
|
+
elsif recursive
|
31
|
+
recur
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end.compact
|
20
35
|
end
|
21
36
|
|
22
|
-
# Uses BBLib.scan_dir but returns only files
|
23
|
-
def self.scan_files
|
24
|
-
|
37
|
+
# Uses BBLib.scan_dir but returns only files
|
38
|
+
def self.scan_files(path, *filters, recursive: false, &block)
|
39
|
+
scan_dir(path, *filters, recursive: recursive, dirs: false, &block)
|
25
40
|
end
|
26
41
|
|
27
|
-
# Uses BBLib.scan_dir but returns only directories.
|
28
|
-
def self.scan_dirs
|
29
|
-
|
42
|
+
# Uses BBLib.scan_dir but returns only directories.
|
43
|
+
def self.scan_dirs(path, *filters, recursive: false, &block)
|
44
|
+
scan_dir(path, *filters, recursive: recursive, files: false, &block)
|
30
45
|
end
|
31
46
|
|
32
|
-
# Shorthand method to write a string to disk. By default the
|
47
|
+
# Shorthand method to write a string to disk. By default the
|
48
|
+
# path is created if it doesn't exist.
|
33
49
|
# Set mode to w to truncate file or leave at a to append.
|
34
|
-
def self.string_to_file path,
|
35
|
-
if !Dir.
|
36
|
-
|
37
|
-
end
|
38
|
-
File.write(path, str.to_s, mode:mode)
|
50
|
+
def self.string_to_file(str, path, mkpath: true, mode: 'a')
|
51
|
+
FileUtils.mkpath(File.dirname(path)) if mkpath && !Dir.exist?(path)
|
52
|
+
File.write(path, str.to_s, mode: mode)
|
39
53
|
end
|
40
54
|
|
41
55
|
# A file size parser for strings. Extracts any known patterns for file sizes.
|
42
|
-
def self.parse_file_size
|
43
|
-
output = FILE_SIZES.keys.find{ |
|
56
|
+
def self.parse_file_size(str, output: :byte)
|
57
|
+
output = FILE_SIZES.keys.find { |fs| fs == output || FILE_SIZES[fs][:exp].include?(output.to_s.downcase) } || :byte
|
44
58
|
bytes = 0.0
|
45
|
-
FILE_SIZES.each do |
|
46
|
-
v[:exp].each do |
|
47
|
-
|
48
|
-
|
59
|
+
FILE_SIZES.each do |_k, v|
|
60
|
+
v[:exp].each do |exp|
|
61
|
+
str.scan(/(?=\w|\D|^)\d*\.?\d+\s*#{exp}s?(?=\W|\d|$)/i)
|
62
|
+
.each { |num| bytes += num.to_f * v[:mult] }
|
49
63
|
end
|
50
64
|
end
|
51
|
-
|
65
|
+
bytes / FILE_SIZES[output][:mult]
|
52
66
|
end
|
53
67
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
68
|
+
# Takes an integer or float and converts it into a string that represents
|
69
|
+
# a file size (e.g. "5 MB 156 kB")
|
70
|
+
# @param [Integer, Float] num The number of bytes to convert to a file size string.
|
71
|
+
# @param [Symbol] input Sets the value of the input. Default is byte.
|
72
|
+
# @param [Symbol] stop Sets a minimum file size to display.
|
73
|
+
# e.g. If stop is set to :megabyte, :kilobyte and below will be truncated.
|
74
|
+
# @param [Symbol] style The out style, Current options are :short and :long
|
75
|
+
def self.to_file_size(num, input: :byte, stop: :byte, style: :short)
|
76
|
+
return nil unless num.is_a?(Numeric)
|
77
|
+
return '0' if num.zero?
|
78
|
+
style = :short unless [:long, :short].include?(style)
|
79
|
+
expression = []
|
80
|
+
n = num * FILE_SIZES[input.to_sym][:mult]
|
81
|
+
done = false
|
82
|
+
FILE_SIZES.reverse.each do |k, v|
|
83
|
+
next if done
|
84
|
+
done = true if k == stop
|
85
|
+
div = n / v[:mult]
|
86
|
+
next unless div >= 1
|
87
|
+
val = (done ? div.round : div.floor)
|
88
|
+
expression << "#{val}#{v[:styles][style]}#{val > 1 && style != :short ? 's' : nil}"
|
89
|
+
n -= val.to_f * v[:mult]
|
90
|
+
end
|
91
|
+
expression.join(' ')
|
92
|
+
end
|
65
93
|
|
94
|
+
FILE_SIZES = {
|
95
|
+
byte: { mult: 1, exp: %w(b byt byte), styles: { short: 'B', long: ' byte' } },
|
96
|
+
kilobyte: { mult: 1024, exp: %w(kb kilo k kbyte kilobyte), styles: { short: 'kB', long: ' kilobyte' } },
|
97
|
+
megabyte: { mult: 1024**2, exp: %w(mb mega m mib mbyte megabyte), styles: { short: 'MB', long: ' megabyte' } },
|
98
|
+
gigabyte: { mult: 1024**3, exp: %w(gb giga g gbyte gigabyte), styles: { short: 'GB', long: ' gigabyte' } },
|
99
|
+
terabyte: { mult: 1024**4, exp: %w(tb tera t tbyte terabyte), styles: { short: 'TB', long: ' terabyte' } },
|
100
|
+
petabyte: { mult: 1024**5, exp: %w(pb peta p pbyte petabyte), styles: { short: 'PB', long: ' petabyte' } },
|
101
|
+
exabyte: { mult: 1024**6, exp: %w(eb exa e ebyte exabyte), styles: { short: 'EB', long: ' exabyte' } },
|
102
|
+
zettabyte: { mult: 1024**7, exp: %w(zb zetta z zbyte zettabyte), styles: { short: 'ZB', long: ' zettabyte' } },
|
103
|
+
yottabyte: { mult: 1024**8, exp: %w(yb yotta y ybyte yottabyte), styles: { short: 'YB', long: ' yottabyte' } }
|
104
|
+
}.freeze
|
66
105
|
end
|
67
106
|
|
68
|
-
class
|
69
|
-
|
70
|
-
|
107
|
+
# Monkey patches for the Numeric class
|
108
|
+
class Numeric
|
109
|
+
def to_file_size(*args)
|
110
|
+
BBLib.to_file_size(self, *args)
|
71
111
|
end
|
72
112
|
end
|
73
113
|
|
114
|
+
# Monkey patches for the String class
|
74
115
|
class String
|
75
|
-
def to_file
|
76
|
-
BBLib.string_to_file
|
116
|
+
def to_file(*args)
|
117
|
+
BBLib.string_to_file(self, *args)
|
77
118
|
end
|
78
119
|
|
79
|
-
def file_name
|
80
|
-
|
120
|
+
def file_name(with_extension = true)
|
121
|
+
with_extension ? File.basename(self) : File.basename(self, File.extname(self))
|
81
122
|
end
|
82
123
|
|
83
124
|
def dirname
|
84
|
-
|
125
|
+
File.dirname(self)
|
85
126
|
end
|
86
127
|
|
87
|
-
def parse_file_size
|
88
|
-
BBLib.parse_file_size(self,
|
128
|
+
def parse_file_size(*args)
|
129
|
+
BBLib.parse_file_size(self, *args)
|
89
130
|
end
|
90
131
|
|
91
132
|
def pathify
|