bblib 0.3.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|