├── .gitignore ├── lib ├── sugar_refinery.rb └── sugar_refinery │ ├── version.rb │ ├── all.rb │ ├── same.rb │ ├── marshal_copy.rb │ ├── hash_zip.rb │ ├── chain_map.rb │ ├── array_op.rb │ ├── file_force_delete.rb │ ├── ords.rb │ ├── lchomp.rb │ ├── alias_for.rb │ ├── camel_snake.rb │ ├── regexp_union.rb │ ├── dir_utils.rb │ ├── inner_map.rb │ ├── string_op.rb │ ├── mash.rb │ ├── file_gsub.rb │ ├── hash_op.rb │ ├── constantize.rb │ ├── array_stats.rb │ └── blank.rb ├── .rspec ├── Gemfile ├── doc ├── desc │ ├── array_op.yaml │ ├── same.yaml │ ├── hash_zip.yaml │ ├── chain_map.yaml │ ├── dir_utils.yaml │ ├── lchomp.yaml │ ├── mash.yaml │ ├── ords.yml │ ├── marshal_copy.yaml │ ├── string_op.yaml │ ├── blank.yaml │ ├── file_gsub.yaml │ ├── regexp_union.yaml │ ├── inner_map.yaml │ ├── camel_snake.yaml │ ├── file_force_delete.yaml │ ├── hash_op.yaml │ ├── array_stats.yaml │ ├── alias_for.yaml │ └── constantize.yaml └── create_documentation.rb ├── .editorconfig ├── spec ├── same_spec.rb ├── hash_zip_spec.rb ├── marshal_copy_spec.rb ├── spec_helper.rb ├── mash_spec.rb ├── ords_spec.rb ├── array_op_spec.rb ├── camel_snake_spec.rb ├── chain_map_spec.rb ├── regexp_union_spec.rb ├── lchomp_spec.rb ├── blank_spec.rb ├── inner_map_spec.rb ├── hash_op_spec.rb ├── string_op_spec.rb ├── dir_utils_spec.rb ├── file_gsub_spec.rb ├── file_force_delete_spec.rb ├── constantize_spec.rb ├── alias_for_spec.rb └── array_stats_spec.rb ├── .github └── workflows │ └── test.yml ├── sugar_refinery.gemspec ├── MIT-LICENSE.txt ├── Rakefile ├── README.md ├── CODE_OF_CONDUCT.md └── CHANGELOG.md /.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | *~ 3 | *.swp 4 | *.rbc 5 | Gemfile.lock 6 | -------------------------------------------------------------------------------- /lib/sugar_refinery.rb: -------------------------------------------------------------------------------- 1 | require_relative 'sugar_refinery/version' 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | platform :rbx do 6 | gem 'rubysl-singleton' 7 | end 8 | -------------------------------------------------------------------------------- /lib/sugar_refinery/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module SugarRefinery 4 | VERSION = '1.0.1' 5 | end 6 | -------------------------------------------------------------------------------- /lib/sugar_refinery/all.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | Dir["#{File.dirname(__FILE__)}/*"].each{ |f| 4 | require_relative File.basename(f) 5 | } 6 | -------------------------------------------------------------------------------- /doc/desc/array_op.yaml: -------------------------------------------------------------------------------- 1 | array_op: 2 | summary: Operators one could miss for ⇧Array⇧ 3 | methods: 4 | Array#^: "[1,2,3,4] ^ [3,4,5,6] # => [1,2,5,6]" 5 | -------------------------------------------------------------------------------- /doc/desc/same.yaml: -------------------------------------------------------------------------------- 1 | same: 2 | summary: "Adds ⇧Float#same?⇧ for correct number comparisons." 3 | methods: 4 | Float#same?: "(0.1 + 0.2).same? 0.3 # true" 5 | -------------------------------------------------------------------------------- /doc/desc/hash_zip.yaml: -------------------------------------------------------------------------------- 1 | hash_zip: 2 | summary: "Adds a ⇧Hash.zip⇧ method, which makes sense." 3 | methods: 4 | Hash.zip: "Hash.zip [1,2,3], [4,5,6] # => {1=>4, 2=>5, 3=>6}" 5 | -------------------------------------------------------------------------------- /doc/desc/chain_map.yaml: -------------------------------------------------------------------------------- 1 | chain_map: 2 | summary: Chain multiple procs on ⇧Array⇧ elements 3 | methods: 4 | Array#chain_map: '[-3, -2, -1].chain_map(:abs, :to_s) # => ["3", "2", "1"]' 5 | -------------------------------------------------------------------------------- /doc/desc/dir_utils.yaml: -------------------------------------------------------------------------------- 1 | dir_utils: 2 | summary: Some shortcuts for working with directories 3 | methods: 4 | Dir.join: File.join 5 | Dir.split: File.split 6 | Dir.rm: FileUtils.rm_r 7 | 8 | -------------------------------------------------------------------------------- /doc/desc/lchomp.yaml: -------------------------------------------------------------------------------- 1 | lchomp: 2 | summary: "Adds ⇧String#chomp⇧ on the left side." 3 | methods: 4 | String#lchomp: "' Yes'.lchomp # => ' Yes'" 5 | String#lchomp!: "# mutable lchomp version" 6 | -------------------------------------------------------------------------------- /doc/desc/mash.yaml: -------------------------------------------------------------------------------- 1 | mash: 2 | summary: "mash: map(hash)" 3 | methods: 4 | Enumerable#mash: "[1,2,3].mash{|e| [e, e.to_s] } # => {1=>'1',2=>'2',3=>'3'}" 5 | info: 6 | - Inspired by Ruby Facets' ⇧mash⇧. 7 | 8 | -------------------------------------------------------------------------------- /doc/desc/ords.yml: -------------------------------------------------------------------------------- 1 | ords: 2 | summary: Easy way to pack and unpack your characters 3 | methods: 4 | Array#chrs: "[72, 97, 108, 108, 111].chrs # => 'Hallo'" 5 | String#ords: "'Hallo'.ords # => [72, 97, 108, 108, 111]" -------------------------------------------------------------------------------- /doc/desc/marshal_copy.yaml: -------------------------------------------------------------------------------- 1 | marshal_copy: 2 | summary: Adds ⇧Object#marshal_copy⇧ to create a deep copy using ⇧Marshal⇧. 3 | methods: 4 | Object#marshal_copy: | 5 | a = %w[hello world] 6 | b = a.marshal_copy 7 | 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.{md,rdoc,txt}] 11 | indent_size = 4 12 | 13 | -------------------------------------------------------------------------------- /doc/desc/string_op.yaml: -------------------------------------------------------------------------------- 1 | string_op: 2 | summary: "More ⇧String⇧ operators. Because Strings cannot be comfortable enough!" 3 | methods: 4 | String#-: "'1234abc5678' - 'b' - /\\d/ # => ac" 5 | String#^: "'Yes vs No'^2 # => 's vs No'" 6 | -------------------------------------------------------------------------------- /doc/desc/blank.yaml: -------------------------------------------------------------------------------- 1 | blank: 2 | summary: "Does pretty the same as in ActiveSupport: Every object can be asked if it is blank or present" 3 | methods: 4 | Object#blank?: | 5 | 'an object'.blank? # => false 6 | nil.present? # => false 7 | 8 | -------------------------------------------------------------------------------- /lib/sugar_refinery/same.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module Same 5 | refine Float do 6 | def same?(other) 7 | (self - other).abs < Float::EPSILON 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /doc/desc/file_gsub.yaml: -------------------------------------------------------------------------------- 1 | file_gsub: 2 | summary: Will read the file and substitute the hash keys with their values 3 | methods: 4 | File.gsub: | 5 | File.gsub 'some_filename', 6 | /hi/ => 'cu', 7 | /\d/ => proc{ |m| (m.to_i+1).to_s } 8 | 9 | -------------------------------------------------------------------------------- /doc/desc/regexp_union.yaml: -------------------------------------------------------------------------------- 1 | regexp_union: 2 | summary: Easy creation of a ⇧Regexp.union⇧ 3 | methods: 4 | Regexp#|, String#|: | 5 | /Ruby\d/ | /test/i | "cheat" 6 | # creates a Regexp similar to: 7 | # /(Ruby\d|[tT][eE][sS][tT]|cheat)/ 8 | 9 | -------------------------------------------------------------------------------- /lib/sugar_refinery/marshal_copy.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module MarshalCopy 5 | refine Object do 6 | def marshal_copy 7 | Marshal.load Marshal.dump self 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /doc/desc/inner_map.yaml: -------------------------------------------------------------------------------- 1 | inner_map: 2 | summary: Runs blocks on inner ⇧Array⇧ elements 3 | methods: 4 | Array#inner_map: "[[1, 2], [3, 4]].inner_map{ |i| i + 1 } # => [[2, 3], [4, 5]]" 5 | Array#inner_inject: "[[1, 2], [3, 4]].inner_inject(&:+) # => [3, 7]" 6 | -------------------------------------------------------------------------------- /doc/desc/camel_snake.yaml: -------------------------------------------------------------------------------- 1 | camel_snake: 2 | summary: Provides ⇧String#to_camel⇧ and ⇧String#to_snake⇧. 3 | methods: 4 | String#to_camel: "'was_snake_string'.to_camel # => 'WasSnakeString'" 5 | String#to_snake: "'WasCamelString'.to_snake # => 'was_camel_string'" 6 | 7 | -------------------------------------------------------------------------------- /doc/desc/file_force_delete.yaml: -------------------------------------------------------------------------------- 1 | file_force_delete: 2 | summary: ⇧File.delete!⇧ (like `rm -f`) 3 | methods: 4 | File.delete!: "File.delete! 'some_filename' # will delete the file, don't care if it exist." 5 | info: 6 | - "Idea for ⇧File.delete!⇧ from sugar-high." 7 | 8 | -------------------------------------------------------------------------------- /lib/sugar_refinery/hash_zip.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module HashZip 5 | refine Hash.singleton_class do 6 | def zip(keys, values) 7 | Hash[ *keys.zip(values).flatten ] 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/same_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/same' 2 | using SugarRefinery::Same 3 | 4 | describe Float do 5 | describe '#same?' do 6 | it 'returns true if other float represents the same number' do 7 | expect( 0.3.same?(0.1 + 0.2) ).to be true 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/sugar_refinery/chain_map.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module ChainMap 5 | refine Array do 6 | def chain_map(*args) 7 | args.inject(self) { |collection, action| collection.map(&action) } 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/sugar_refinery/array_op.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module ArrayOp 5 | refine Array do 6 | def ^(other) 7 | (self - other) + (other - self) 8 | end 9 | 10 | def **(*o, &block) 11 | product *o, &block 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/sugar_refinery/file_force_delete.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module FileForceDelete 5 | refine File.singleton_class do 6 | def delete!(filename) 7 | return nil if !File.exist?(filename) 8 | File.delete filename 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/sugar_refinery/ords.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module Ords 5 | refine Array do 6 | def chrs 7 | self.pack 'C*' 8 | end 9 | end 10 | 11 | refine String do 12 | def ords 13 | self.unpack 'C*' 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/sugar_refinery/lchomp.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module Lchomp 5 | refine String do 6 | def lchomp(arg = $/) 7 | reverse.chomp(arg).reverse 8 | end 9 | 10 | def lchomp!(arg = $/) 11 | replace reverse.chomp(arg).reverse 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/hash_zip_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/hash_zip' 2 | using SugarRefinery::HashZip 3 | 4 | 5 | describe Hash do 6 | describe '.zip' do 7 | it 'should zip together both given enumerables and take them as key=>values for a new hash' do 8 | Hash.zip( [1,2,3], [4,5,6] ).should == { 1=>4, 2=>5, 3=>6 } 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /doc/desc/hash_op.yaml: -------------------------------------------------------------------------------- 1 | hash_op: 2 | summary: Sugar for dealing with hashes 3 | methods: 4 | Hash#<<: | 5 | {1=>2} << [3, 4] # => { 1=>2, 3=>4 } 6 | {1=>2} << { 5=>6 } # => { 1=>2, 5=>6 } 7 | Hash#&: "{ 1=>4, 2=>5, 3=>6 } & { 1=>4, 2=>7 } # => { 1=>4 }" 8 | info: 9 | - Some of the operators are inspired by Ruby Facets. 10 | 11 | -------------------------------------------------------------------------------- /lib/sugar_refinery/alias_for.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module AliasFor 5 | refine Module do 6 | private 7 | 8 | def alias_for(m, *aliases) 9 | aliases.each{ |a| class_eval "alias :'#{ a }' :'#{ m }'" } 10 | end 11 | 12 | alias aliases_for alias_for 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/marshal_copy_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/marshal_copy' 2 | using SugarRefinery::MarshalCopy 3 | 4 | 5 | describe 'Object#marshal_copy' do 6 | it 'create a (deep) copy via marshalling' do 7 | a = %w[hello world] 8 | b = a.marshal_copy 9 | b.should == a 10 | 11 | b[0][1,1] = '' 12 | b.should_not == a 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /lib/sugar_refinery/camel_snake.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module CamelSnake 5 | refine String do 6 | def to_snake 7 | gsub(/(?'1',2=>'2',3=>'3',} 8 | end 9 | end 10 | 11 | 12 | describe 'Enumerator#mash' do 13 | it 'should "map" a hash' do 14 | [1,2,3].each.mash{|e| [e, e.to_s] }.should == {1=>'1',2=>'2',3=>'3',} 15 | end 16 | end 17 | 18 | -------------------------------------------------------------------------------- /spec/ords_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/ords' 2 | using SugarRefinery::Ords 3 | 4 | 5 | describe 'Array#chrs' do 6 | it 'converts the array to a string, using each element as ord value for the char' do 7 | [72, 97, 108, 108, 111].chrs.should == 'Hallo' 8 | end 9 | end 10 | 11 | describe 'String#ords' do 12 | it 'unpacks characters' do 13 | 'Hallo'.ords.should == [72, 97, 108, 108, 111] 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/array_op_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/array_op' 2 | using SugarRefinery::ArrayOp 3 | 4 | 5 | describe 'Array#^' do 6 | it 'does an exclusive or' do 7 | a = [1,2,3,4] 8 | b = [3,4,5,6] 9 | (a^b).should == [1,2,5,6] 10 | end 11 | end 12 | 13 | describe 'Array#**' do 14 | it 'returns the array product' do 15 | ([1,2] ** %w[a b]).should == [[1, "a"], [1, "b"], [2, "a"], [2, "b"]] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/sugar_refinery/dir_utils.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | require 'fileutils' 3 | 4 | module SugarRefinery 5 | module DirUtils 6 | refine Dir.singleton_class do 7 | def join(*args) 8 | File.join(*args) 9 | end 10 | 11 | def split(*args) 12 | File.split(*args) 13 | end 14 | 15 | def rm(*args) 16 | FileUtils.rm_r(*args) 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/sugar_refinery/inner_map.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module InnerMap 5 | refine Array do 6 | def inner_map(&block) 7 | map { |object| object.map(&block) } 8 | end 9 | 10 | def inner_inject(default = :not_used, &block) 11 | map { |object| default == :not_used ? object.inject(&block) : object.inject(default, &block) } 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/sugar_refinery/string_op.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module StringOp 5 | refine String do 6 | def -(rem) 7 | gsub( Regexp === rem ? rem : rem.to_s, '' ) 8 | end 9 | 10 | def ^(pos) 11 | pos = pos.to_i 12 | if pos >= 0 13 | self[pos..-1] 14 | else 15 | self[0...pos] 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /spec/camel_snake_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/camel_snake' 2 | using SugarRefinery::CamelSnake 3 | 4 | 5 | describe 'String#to_camel' do 6 | it 'should turn a snake_cased string to CamelCase' do 7 | 'was_snake_case'.to_camel.should == 'WasSnakeCase' 8 | end 9 | end 10 | 11 | describe 'String#to_snake' do 12 | it 'should turn a CamelCased string to snake_case' do 13 | 'WasCamelCase'.to_snake.should == 'was_camel_case' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/sugar_refinery/mash.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module Mash 5 | refine Enumerator do 6 | def mash 7 | ret = {} 8 | each{ |kv| ret.store( *(yield(kv)[0,2]) ) } 9 | ret 10 | end 11 | end 12 | 13 | refine Array do 14 | def mash 15 | ret = {} 16 | each{ |kv| ret.store( *(yield(kv)[0,2]) ) } 17 | ret 18 | end 19 | end 20 | end 21 | end 22 | 23 | -------------------------------------------------------------------------------- /spec/chain_map_spec.rb: -------------------------------------------------------------------------------- 1 | require "sugar_refinery/chain_map" 2 | using SugarRefinery::ChainMap 3 | 4 | describe "Array#chain_map" do 5 | it "should repeatedly chain symbols as map calls" do 6 | list = [-3, -2, -1] 7 | 8 | list.chain_map(:abs, :to_s) == %w{3 2 1} 9 | end 10 | 11 | it "should repeatedly chain blocks as map calls" do 12 | list = [-3, -2, -1] 13 | 14 | list.chain_map(->(e) { e ** 2 }, ->(e) { e * -1 }) == [-9, -4, -1] 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /doc/desc/alias_for.yaml: -------------------------------------------------------------------------------- 1 | alias_for: 2 | summary: 'A different way to create aliases: Reversed order and you can pass multiple alias names. The order feels more logical' 3 | methods: 4 | Module#alias_for, Module#aliases_for: | 5 | # creates an alias for the method :methods with the name ms 6 | class Object 7 | alias_for :methods, :ms 8 | end 9 | 10 | # creates multiple aliases 11 | module Enumerable 12 | aliases_for :zip, :with, :% 13 | end 14 | -------------------------------------------------------------------------------- /spec/regexp_union_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/regexp_union' 2 | using SugarRefinery::RegexpUnion 3 | 4 | 5 | shared_examples_for "Regexp.union operator" do 6 | it "creates a Regexp.union of both operands" do 7 | (/Ruby\d/ | /test/i | "cheat").should == 8 | Regexp.union( Regexp.union( /Ruby\d/, /test/i ), "cheat" ) 9 | end 10 | end 11 | 12 | describe 'Regexp#|' do 13 | it_should_behave_like 'Regexp.union operator' 14 | end 15 | 16 | describe 'String#|' do 17 | it_should_behave_like 'Regexp.union operator' 18 | end 19 | 20 | -------------------------------------------------------------------------------- /spec/lchomp_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/lchomp' 2 | using SugarRefinery::Lchomp 3 | 4 | describe String do 5 | describe '#lchomp' do 6 | it 'should chomp on the left side' do 7 | string = 'ameise' 8 | expect( string.lchomp('a') ).to eq 'meise' 9 | expect( string ).to eq 'ameise' 10 | end 11 | end 12 | 13 | describe '#lchomp!' do 14 | it 'should chomp on the left side (mutating)' do 15 | string = 'ameise' 16 | expect( string.lchomp!('a') ).to eq 'meise' 17 | expect( string ).to eq 'meise' 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /doc/desc/constantize.yaml: -------------------------------------------------------------------------------- 1 | constantize: 2 | summary: "Easier handling of dynamic constant names" 3 | methods: 4 | String#constantize: | 5 | 'Object'.constantize # => Object 6 | 'Spec::VERSION'.constantize # => Spec::VERSION if rspec is loaded 7 | # you can also pass a parameter or block to define what happens, when constant does not exist 8 | 'IdontExist'.constantize(Array) # => Array 9 | 'String5'.constantize do |string| 10 | string.chop.constantize 11 | end # => String 12 | info: 13 | - "An improved version of ActiveSupport's one" 14 | 15 | -------------------------------------------------------------------------------- /spec/blank_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/blank' 2 | using SugarRefinery::Blank 3 | 4 | 5 | describe 'Object#blank?' do 6 | it 'should be blank for blank values' do 7 | blank_values = [ nil, false, '', ' ', " \n\t \r ", [], {}, // ] 8 | 9 | blank_values.each{ |blank| 10 | blank.blank?.should == true 11 | } 12 | end 13 | 14 | it 'should not be blank for non blank values' do 15 | present_values = [ Object.new, true, 0, 1, 'a', [nil], { nil => nil } ] 16 | 17 | present_values.each{ |present| 18 | present.blank?.should == false 19 | } 20 | end 21 | end 22 | 23 | -------------------------------------------------------------------------------- /spec/inner_map_spec.rb: -------------------------------------------------------------------------------- 1 | require "sugar_refinery/inner_map" 2 | using SugarRefinery::InnerMap 3 | 4 | describe "Array#inner_map" do 5 | it "should delegate map to inner lists" do 6 | list = [[1, 2], [3, 4]] 7 | 8 | list.inner_map { |i| i + 1 }.should == [[2, 3], [4, 5]] 9 | end 10 | end 11 | 12 | describe "Array#inner_inject" do 13 | it "should delegate inject to inner lists" do 14 | list = [%w{a b c}, %w{d e f}] 15 | 16 | list.inner_inject(&:+).should == list.map(&:join) 17 | end 18 | 19 | it "should take default values" do 20 | list = [[3, 2, 1], [-4]] 21 | 22 | list.inner_inject(4, &:+).should == [10, 0] 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/sugar_refinery/file_gsub.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module FileGsub 5 | refine File.singleton_class do 6 | def gsub(filename, regex_hash) 7 | data = File.read filename 8 | File.open(filename,'w'){ |file| 9 | regex_hash.each{ |regex, new_string| 10 | regex = regex.to_s unless regex.is_a? Regexp 11 | 12 | if new_string.is_a? Proc 13 | data.gsub! regex, &new_string 14 | else 15 | data.gsub! regex, new_string 16 | end 17 | } 18 | file.print data 19 | } 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | name: Ruby ${{ matrix.ruby }} (${{ matrix.os }}) 8 | if: "!contains(github.event.head_commit.message, '[skip ci]')" 9 | strategy: 10 | matrix: 11 | ruby: 12 | - 3.0 13 | - 2.7 14 | - 2.6 15 | - 2.5 16 | os: 17 | - ubuntu-latest 18 | runs-on: ${{matrix.os}} 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Set up Ruby 22 | uses: ruby/setup-ruby@v1 23 | with: 24 | ruby-version: ${{matrix.ruby}} 25 | bundler-cache: true 26 | - name: Run tests 27 | run: bundle exec rake 28 | -------------------------------------------------------------------------------- /spec/hash_op_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/hash_op' 2 | using SugarRefinery::HashOp 3 | 4 | 5 | describe 'Hash#<<' do 6 | it 'appends new elements to the hash' do 7 | a = { 1=>4, 2=>5, 3=>6 } 8 | a << { 4=>7 } 9 | a << [5, 8] 10 | a.should == { 1=>4, 2=>5, 3=>6, 4=>7, 5=>8 } 11 | end 12 | end 13 | 14 | describe 'Hash#&' do 15 | it 'selects a sub hash containt only equal key-value pairs' do 16 | a = { 1=>4, 2=>5, 3=>6 } 17 | b = { 1=>4, 2=>7 } 18 | (a & b).should == { 1=>4 } 19 | end 20 | end 21 | 22 | describe 'Hash#+' do 23 | it 'merges two hashes' do 24 | a = { 1=>4, 2=>5, 3=>6 } 25 | b = { 1=>4, 2=>7, 4=>0 } 26 | (a + b).should == { 1=>4, 2=>7, 3=>6, 4=>0 } 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/sugar_refinery/hash_op.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module HashOp 5 | refine Hash do 6 | def <<(other) 7 | case 8 | when other.is_a?(Hash) 9 | merge! other 10 | when other.is_a?(Enumerable) || other.respond_to?(:to_splat) 11 | merge! Hash[*other] 12 | else 13 | raise TypeError, 'can only append other Hashs and Enumerables (or Classes that implement to_splat)' 14 | end 15 | end 16 | 17 | def &(other) 18 | Hash[ *select{ |k,v| 19 | other[k] == v 20 | }.flatten ] 21 | end 22 | 23 | def +(*o, &block) 24 | merge *o, &block 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/string_op_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/string_op' 2 | using SugarRefinery::StringOp 3 | 4 | 5 | describe 'String#-' do 6 | it 'should remove the applied Regexp or String from self via gsub' do 7 | ('1234abc5678' - 'b' - /\d/).should == 'ac' 8 | end 9 | end 10 | 11 | describe 'String#^' do 12 | it 'should give C-like substring access to strings' do 13 | string = 'Theoretische Informatik ist voll geil!' 14 | 15 | (string^0).should == 'Theoretische Informatik ist voll geil!' 16 | (string^1).should == 'heoretische Informatik ist voll geil!' 17 | (string^13).should == 'Informatik ist voll geil!' 18 | (string^-1).should == 'Theoretische Informatik ist voll geil' 19 | (string^38).should == '' 20 | (string^99).should == nil 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/sugar_refinery/constantize.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module Constantize 5 | refine String do 6 | def constantize(default_value = nil) # always uses global scope as in AS... is this good? 7 | get_constant = lambda{ 8 | self.split(/::/).inject( Object ){ |base_constant, current_constant| 9 | base_constant.const_get current_constant 10 | } 11 | } 12 | 13 | if !default_value && !block_given? 14 | get_constant.call 15 | else 16 | begin 17 | get_constant.call 18 | rescue NameError 19 | if block_given? 20 | yield self 21 | else 22 | default_value 23 | end 24 | end 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/dir_utils_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/dir_utils' 2 | require 'securerandom' 3 | using SugarRefinery::DirUtils 4 | 5 | 6 | describe Dir do 7 | describe '.join' do 8 | it 'delegates to File.join' do 9 | a = %w[some file path] 10 | expect( Dir.join(a) ).to be == File.join(a) 11 | end 12 | end 13 | 14 | describe '.split' do 15 | it 'delegates to File.split' do 16 | a = 'some/file/path' 17 | expect( Dir.split(a) ).to be == File.split(a) 18 | end 19 | end 20 | 21 | describe '.rm' do 22 | it 'removes directories with content' do 23 | path = "tmp_#{SecureRandom.uuid}" 24 | FileUtils.mkdir path 25 | FileUtils.touch "#{path}/123" 26 | expect{ 27 | Dir.rm path 28 | }.not_to raise_error 29 | expect( Dir['*'] ).to_not include(path) 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/sugar_refinery/array_stats.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module ArrayStats 5 | refine Array do 6 | def mean 7 | inject(&:+) / length.to_f 8 | end 9 | 10 | def stdev(type = :population) 11 | case type 12 | when :population then stdev_population 13 | when :sample then stdev_sample 14 | else raise ArgumentError.new("%s is not a valid argument" % type) 15 | end 16 | end 17 | 18 | def stdev_sample 19 | Math.sqrt(inject(0.0) { |sum, x| sum + (mean - x) ** 2 } / (length - 1)) 20 | end 21 | 22 | def stdev_population 23 | Math.sqrt(inject(0.0) { |sum, x| sum + (mean - x) ** 2 } / length) 24 | end 25 | 26 | def z_score(type = :population) 27 | map { |x| (x - mean) / stdev(type) } 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/file_gsub_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/file_gsub' 2 | require 'fileutils' 3 | using SugarRefinery::FileGsub 4 | 5 | 6 | describe File do 7 | describe '.gsub' do 8 | let :random_filename do 9 | 'test_' + (0..20).map{|e| [*'a'..'z'].sample }*'' 10 | end 11 | 12 | it 'should read filename in arg1, substitute every key in the arg2 with its value and save the file' do 13 | File.open(random_filename,'w'){ |file| 14 | file.print 'should read filename in arg1, substitute every key in the arg2 with its value and save the file' 15 | } 16 | File.gsub random_filename, 17 | /read/ => 'write', 18 | /\d+/ => proc{|m| (m.to_i+1).to_s } 19 | 20 | File.read(random_filename).should == 21 | 'should write filename in arg2, substitute every key in the arg3 with its value and save the file' 22 | 23 | FileUtils.rm random_filename 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/sugar_refinery/blank.rb: -------------------------------------------------------------------------------- 1 | require_relative 'version' 2 | 3 | module SugarRefinery 4 | module Blank 5 | refine Object do 6 | def blank? 7 | if respond_to? :empty? then empty? else !self end 8 | end 9 | 10 | def present? 11 | !blank? 12 | end 13 | end 14 | 15 | refine NilClass do 16 | def blank?() true end 17 | end 18 | 19 | refine FalseClass do 20 | def blank?() true end 21 | end 22 | 23 | refine TrueClass do 24 | def blank?() false end 25 | end 26 | 27 | refine Numeric do 28 | def blank?() false end 29 | end 30 | 31 | refine Array do 32 | def blank?() empty? end 33 | end 34 | 35 | refine Hash do 36 | def blank?() empty? end 37 | end 38 | 39 | refine String do 40 | def blank?() self !~ /\S/ end 41 | end 42 | 43 | refine Regexp do 44 | def blank?() self == // end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/file_force_delete_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/file_force_delete' 2 | require 'fileutils' 3 | using SugarRefinery::FileForceDelete 4 | 5 | 6 | describe File do 7 | describe '.delete!' do 8 | after{ File.delete! 'random_filename' } 9 | let :random_filename do 10 | 'test_' + (0..20).map{|e| [*'a'..'z'].sample }*'' 11 | end 12 | 13 | it 'should delete the filename given as argument if it exists + return non-nil' do 14 | FileUtils.touch random_filename 15 | res = false 16 | proc do 17 | res = File.delete! random_filename 18 | end.should_not raise_exception 19 | res.should be_truthy 20 | end 21 | 22 | it 'should do nothing if the filename given as argument does not exist + return nil' do 23 | res = false 24 | proc do 25 | res = File.delete! random_filename 26 | end.should_not raise_exception 27 | res.should be_falsey 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /sugar_refinery.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require File.dirname(__FILE__) + '/lib/sugar_refinery/version' 3 | 4 | Gem::Specification.new do |s| 5 | s.name = "sugar_refinery" 6 | s.version = SugarRefinery::VERSION 7 | s.authors = ['Jan Lelis'] 8 | s.email = ['hi@ruby.consulting'] 9 | s.summary = "The Ruby Sugar Refinery is a collection of tiny refinements." 10 | s.description = "The Ruby Sugar Refinery is a collection of tiny refinements (declarative local core extensions)." 11 | s.homepage = "https://janlelis.github.io/sugar_refinery" 12 | s.files = Dir.glob( %w[{lib,spec}/**/*.rb desc/**/*.yaml] ) + %w{Rakefile sugar_refinery.gemspec MIT-LICENSE.txt README.md CHANGELOG.md doc/create_documentation.rb doc/index.html} 13 | s.require_paths = ["lib"] 14 | s.license = 'MIT' 15 | 16 | s.required_ruby_version = '>= 2.0' 17 | s.add_development_dependency 'rake', '~> 13.0' 18 | s.add_development_dependency 'rspec', '~> 2.99' 19 | s.add_development_dependency 'coderay', '~> 1.1' 20 | end 21 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2016 Jan Lelis 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # # # 2 | # Get gemspec info 3 | 4 | gemspec_file = Dir['*.gemspec'].first 5 | gemspec = eval File.read(gemspec_file), binding, gemspec_file 6 | info = "#{gemspec.name} | #{gemspec.version} | " \ 7 | "#{gemspec.runtime_dependencies.size} dependencies | " \ 8 | "#{gemspec.files.size} files" 9 | 10 | 11 | # # # 12 | # Gem build and install task 13 | 14 | desc info 15 | task :gem do 16 | puts info + "\n\n" 17 | print " "; sh "gem build #{gemspec_file}" 18 | FileUtils.mkdir_p 'pkg' 19 | FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg' 20 | puts; sh %{gem install --no-document pkg/#{gemspec.name}-#{gemspec.version}.gem} 21 | end 22 | 23 | 24 | # # # 25 | # Start an IRB session with the gem loaded 26 | 27 | desc "#{gemspec.name} | IRB" 28 | task :irb do 29 | sh "irb -I ./lib -r #{gemspec.name.gsub '-','/'}" 30 | end 31 | 32 | 33 | # # # 34 | # Run Specs 35 | 36 | desc "#{gemspec.name} | Spec" 37 | task 'spec' do 38 | sh %[rspec spec] 39 | end 40 | task default: :spec 41 | 42 | 43 | # # # 44 | # Documentation 45 | 46 | desc "#{gemspec.name} | Documentation" 47 | task 'doc' do 48 | ruby 'doc/create_documentation.rb' 49 | end 50 | -------------------------------------------------------------------------------- /spec/constantize_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/constantize' 2 | using SugarRefinery::Constantize 3 | 4 | 5 | describe 'String#constantize' do 6 | it 'should return the constant with that name' do 7 | 'Object'.constantize.should == Object 8 | end 9 | 10 | it 'should also work for nested constants' do 11 | 'SugarRefinery::VERSION'.constantize.should == SugarRefinery::VERSION 12 | end 13 | 14 | it 'should throw name error if constant does not exist (and no parameter is given)' do 15 | proc do 16 | 'ObfsefsefsefafesafaefRubySugarRefineryafdfselijfesject'.constantize 17 | end.should raise_exception NameError 18 | end 19 | 20 | it 'should call the block (and not raise an error) if constant does not exist and block given' do 21 | proc do 22 | 'ObfsefsefsefafesafaefRubySugarRefineryafdfselijfesject'.constantize do |string| 23 | Default = [1,2,3] 24 | end.should == [1,2,3] 25 | end.should_not raise_exception 26 | end 27 | 28 | it 'should return the second parameter (and not raise an error) if constant does not exist and parameter given' do 29 | proc do 30 | 'ObfsefsefsefafesafaefRubySugarRefineryafdfselijfesject'.constantize(Array).should == Array 31 | end.should_not raise_exception 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /spec/alias_for_spec.rb: -------------------------------------------------------------------------------- 1 | require 'sugar_refinery/alias_for' 2 | using SugarRefinery::AliasFor 3 | 4 | 5 | describe 'alias_for' do 6 | it 'should create an alias for instance methods' do 7 | class Array 8 | def m2 9 | 2 10 | end 11 | aliases_for :m2, :a2, :'a-2' 12 | end 13 | proc do 14 | [1,2,3].a2.should == 2 15 | [1,2,3].send('a-2').should == 2 16 | end.should_not raise_exception 17 | end 18 | 19 | it 'should create an alias for class (singleton) methods' do 20 | class Array 21 | class << Array 22 | def m3 23 | 3 24 | end 25 | alias_for :m3, :a3 26 | end 27 | end 28 | 29 | proc{ 30 | Array.a3.should == 3 31 | }.should_not raise_exception 32 | end 33 | 34 | 35 | it 'should create aliases for the first argument with all other arguments' do 36 | class Object 37 | def m4 38 | 4 39 | end 40 | alias_for :m4, :ma, :mb, :mc 41 | end 42 | 43 | proc{ 44 | 1.ma.should == 4 45 | "1".mb.should == 4 46 | [1].mc.should == 4 47 | }.should_not raise_exception 48 | end 49 | 50 | it 'works with uncommon chars' do 51 | class Object 52 | alias_for :tainted?, :"tain-ted?" 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ruby Sugar Refinery [![version](https://badge.fury.io/rb/sugar_refinery.svg)](https://badge.fury.io/rb/sugar_refinery) [![[ci]](https://github.com/janlelis/sugar_refinery/workflows/Test/badge.svg)](https://github.com/janlelis/sugar_refinery/actions?query=workflow%3ATest) 2 | 3 | The Ruby Sugar Refinery is a collection of tiny [refinements](https://ruby-doc.org/core/doc/syntax/refinements_rdoc.html) (declarative local core extensions) for Ruby. 4 | 5 | ## Setup & usage 6 | 7 | Add to Gemfile: 8 | 9 | ```ruby 10 | gem 'sugar_refinery', require: 'sugar_refinery/all' 11 | ``` 12 | 13 | Then add refinements to the current Ruby file or module: 14 | 15 | ```ruby 16 | using SugarRefinery::CamelSnake 17 | using SugarRefinery::HashZip 18 | 19 | "ClassName".to_snake # => "class_name" 20 | Hash.zip [1,2,3], [4,5,6] # => {1=>4, 2=>5, 3=>6} 21 | ``` 22 | 23 | ## List of included refinements 24 | 25 | Please see [the documentation](http://janlelis.github.io/sugar_refinery), [the code](https://github.com/janlelis/sugar_refinery/tree/master/lib/sugar_refinery) or [the specs](https://github.com/janlelis/sugar_refinery/tree/master/spec)! 26 | 27 | ## The Sugar Refinery was Zucker before 28 | 29 | This collection of core extensions used to be called **zucker**. 30 | 31 | Missing former functionality? It might have been extracted into a separate micro gem: 32 | 33 | * [iterate](https://github.com/janlelis/iterate) | Control structure-like iteration 34 | * [instance_variables_from](https://github.com/janlelis/instance_variables_from) | Auto-assign instance variables 35 | * [egonil](https://github.com/janlelis/egonil) | Egocentric nil 36 | * [debugging](https://github.com/janlelis/debugging) | Print debugging helpers 37 | * [procstar](https://github.com/janlelis/procstar) | Beyond symbol2proc 38 | * [ruby_info](https://github.com/janlelis/ruby_info) | Misc information about the Ruby environment 39 | * [ruby_version](https://github.com/janlelis/ruby_version) | Smart Ruby version accessor 40 | * [ruby_engine](https://github.com/janlelis/ruby_engine) | Smar Ruby engine accessor 41 | 42 | ## J-_-L 43 | 44 | Copyright (c) 2010-2016 [Jan Lelis](https://janlelis.com), released under the MIT license 45 | -------------------------------------------------------------------------------- /spec/array_stats_spec.rb: -------------------------------------------------------------------------------- 1 | require "sugar_refinery/array_stats" 2 | using SugarRefinery::ArrayStats 3 | 4 | describe "doing statistics on arrays" do 5 | let(:list) { (2..5).to_a } 6 | 7 | describe "Array#mean" do 8 | it "should return the average" do 9 | list.mean.should == 3.5 10 | end 11 | end 12 | 13 | describe "Array#stdev_sample" do 14 | it "should return the standard deviation of the sample" do 15 | list.stdev_sample.should be_within(1e-8).of(1.2909944487358056) 16 | end 17 | end 18 | 19 | describe "Array#stdev_population" do 20 | it "should return the standard deviation of the population" do 21 | list.stdev_population.should be_within(1e-8).of(1.118033988749895) 22 | end 23 | end 24 | 25 | describe "Array#stdev" do 26 | it "should default to population" do 27 | list.stdev.should be_within(1e-8).of(list.stdev_population) 28 | end 29 | 30 | it "should delegate sample correctly" do 31 | list.stdev(:sample).should be_within(1e-8).of(list.stdev_sample) 32 | end 33 | 34 | it "should delegate population correctly" do 35 | list.stdev(:population).should be_within(1e-8).of(list.stdev_population) 36 | end 37 | 38 | it "should raise an error with any other key" do 39 | expect { list.stdev(:pony) }.to raise_error(ArgumentError) 40 | end 41 | end 42 | 43 | describe "Array#z_score" do 44 | it "should default to population" do 45 | list.z_score.zip(list.z_score(:population)).each do |value, actual| 46 | value.should be_within(1e-8).of(actual) 47 | end 48 | end 49 | 50 | it "should delegate sample correctly" do 51 | sample_z_score = [ 52 | -1.161895003862225, 53 | -0.3872983346207417, 54 | 0.3872983346207417, 55 | 1.161895003862225 56 | ] 57 | 58 | p list 59 | 60 | list.z_score(:sample).zip(sample_z_score).each do |value, actual| 61 | value.should be_within(1e-8).of(actual) 62 | end 63 | end 64 | 65 | it "should delegate population correctly" do 66 | population_z_score = [ 67 | -1.3416407864998738, 68 | -0.4472135954999579, 69 | 0.4472135954999579, 70 | 1.3416407864998738 71 | ] 72 | 73 | list.z_score(:population).zip(population_z_score).each do |value, actual| 74 | value.should be_within(1e-8).of(actual) 75 | end 76 | end 77 | 78 | it "should raise an error with any other key" do 79 | expect { list.z_score(:pony) }.to raise_error(ArgumentError) 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at conduct@janlelis.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # SUGAR REFINERY CHANGELOG 2 | 3 | ## 2021-01-07 | Sugar Refinery 1.0.1 4 | 5 | * Relax Ruby version requirement to allow Ruby 3.0 6 | 7 | 8 | ## 2016-01-03 | Sugar Refinery 1.0.0 9 | 10 | * turn zucker gem into sugar_refinery 11 | * move iterate into its own gem 12 | * move instance_variable_from into its own gem 13 | * move egonil into its own gem 14 | * remove 'Zucker#require' and 'Zucker#require_all' 15 | * remove 'refine' gem dependency 16 | * remove unary_conversion in favor of https://bugs.ruby-lang.org/issues/11782 17 | * remove square_brackets_for 18 | * remove tap 19 | * rename string_extras to lchomp 20 | * rename hash_extras to hash_zip 21 | * rename float_extras to same 22 | * rename dir_extras to dir_utils 23 | * split file_extras into file_force_delete and file_gsub (also remove File.filename) 24 | 25 | 26 | ## OLD ZUCKER CHANGELOG 27 | 28 | 2015-04-01 | Zucker 100.1.0 29 | * drop Ruby 1.9 support 30 | * add float_extras for Float#same? 31 | * add chain_map 32 | * add inner_map 33 | * add array_stats 34 | 35 | 36 | 2014-04-01 | Zucker 100.0.0 37 | * drop Ruby 1.8 support 38 | * rewrite zucker to use refinements! 39 | * use usual semantic versioning 40 | * remove all "debug" cubes, use the "debugging" gem instead! 41 | * remove "ruby_version" cube, use the "ruby_version" gem instead! 42 | * remove "engine" cube, use the "ruby_engine" gem instead! 43 | * remove "info" cube, use the "ruby_info" gem instead! 44 | * remove "os" cube, use rdp's "os" gem instead! 45 | * remove "*_to_proc" cubes, use the "procstar" gem instead! 46 | * remove "sandbox" cube, since sandboxing is not recommended and removed from Ruby 2.1 47 | * remove "kernel" and "not" cube completely 48 | * tweaks to most other cubes 49 | 50 | 51 | 2013-04-30 | Zucker 13 52 | * fix alias_for bug 53 | * let RubyVersion#inspect and RubyEngine#inspect map to #to_s 54 | * remove Array#sum 55 | * repackage (gh#4) 56 | 57 | 58 | 2012-01-16 | Zucker 12 59 | * fix a requiring bug 60 | * rename zucker/version cube to zucker/ruby_version and Zucker::PACKAGES to Zucker::PACKS 61 | * remove more_aliases! (keep it simple...) 62 | * add case cube: String#to_camel and String#to_snake 63 | 64 | 65 | 2011-05-25 | Zucker 11 66 | * add Zucker::constants to check if cube has been required (e.g. Zucker::AliasFor if 'zucker/alias_for' is loaded) 67 | * rbx tweaks 68 | * don't define Binding#vars on rbx (prevent endless recursion) 69 | * sandbox-not-working warning 70 | * add Kernel#ignore_sigquit! 71 | * fix warnings 72 | * doc tweaks 73 | 74 | 75 | 2011-04-29 | Zucker 10 76 | * doc/spec tweaks 77 | * make test.rubygems.org-testable 78 | * fix zucker 9 permission issue 79 | 80 | 81 | 2011-01-22 | Zucker 9 82 | * remove history versions (sorry, it caused too much gem/rdoc troubles) 83 | * add file cube: File.delete! and File.gsub 84 | * debug pack improvements 85 | * binding: typos + return nil 86 | * cc: support for ripl + return nil 87 | * mm: also show eigenclass for modules + nicer displaying + return nil 88 | * added Regexp#visualize 89 | * remove optional sandbox param 90 | * rename xxx2proc to xxx_to_proc 91 | * change rakefile/rspec/gemspec structure 92 | * more minor fixes and improvements 93 | 94 | 95 | 2010-10-06 | Zucker 8 96 | * fix a little alias_for bug 97 | * disable rdoc creation when installing (in favour of the custom docs) 98 | * change Binding#inspect to Binding.variables (was too verbose and dangerous) 99 | 100 | 101 | 2010-10-03 | Zucker 7 102 | * fix critical OS.windows? bug 103 | 104 | 105 | 2010-10-03 | Zucker 6 106 | * no new cubes 107 | * bugfix for OS.posix? 108 | * small changes + bugfixes + doc improvements 109 | * add two user methods to Info 110 | * change egonil semantics ( using method_missing, see http://ruby.janlelis.de/26/catch_nil.rb ) 111 | * bugfix for vv 112 | 113 | 114 | 2010-09-04 | Zucker 5 115 | * debug edition - add two debug helpers: oo (output line, method, file) and cc (output method callstack) 116 | * rename cube D to dd add add more debug aliases (for mm and binding) 117 | * fix __SPECIAL_VARS__ in info and kernel cube and some minor bugfixes 118 | * Zucker.activate_more_aliases! option 119 | * add Hash#& 120 | * add aliases: File.filename (for basename), Dir.join and Dir.split (for File.join, split) 121 | * add a flexible requiring mechansim in zucker.rb (no api changes) 122 | * restructure packages 123 | * add rake tasks for releasing 124 | * improve RubyVersion constant (cleaner and more flexible) 125 | 126 | 127 | 2010-09-01 | Zucker 4 128 | * fix Binding#inspect 129 | * add RubyEngine constant 130 | * add RubyVersion constant 131 | * add OS constant 132 | * add q debug method (like p but on one line) 133 | * add String#- 134 | 135 | 136 | 2010-08-14 | Zucker 3 137 | * add tap cube 138 | * add Object#not 139 | * add alias_for for an alternative alias syntax 140 | * add String#constantize (improved AS version) 141 | * improve Info module 142 | * make Array#sum Rails compatibile 143 | * improve docs 144 | * change directory layout (no changes for requiring) 145 | * more small changes 146 | 147 | 148 | 2010-08-08 | Zucker 2 149 | * add info cube 150 | * add chaining for array2proc 151 | * fix Hash.zip 152 | * fix instance_variables_from binding for 1.9 153 | * more specs 154 | 155 | 156 | 2010-08-06 | Zucker 1 157 | * initial release 158 | 159 | 160 | 2010-08-05 | Zucker 0 161 | * pre-release for rug-b talk 162 | 163 | -------------------------------------------------------------------------------- /doc/create_documentation.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # creates the documentation for SugarRefinery 3 | 4 | require 'date' 5 | require 'yaml' 6 | require 'coderay' 7 | 8 | require_relative '../lib/sugar_refinery/camel_snake' 9 | using SugarRefinery::CamelSnake 10 | 11 | 12 | class SugarRefineryDoc 13 | ORDER = %w|summary use methods info spec source| 14 | DESCRIPTIONS = { 15 | 'summary' => 'Summary', 16 | 'use' => 'Activate', 17 | 'methods' => 'Usage', 18 | 'info' => 'Information', 19 | 'spec' => 'Specification', 20 | 'source' => 'Source', 21 | } 22 | 23 | 24 | class << self 25 | def generate(path = File.dirname(__FILE__) + '/../') 26 | @path = path 27 | 28 | # get version / date 29 | @version = SugarRefinery::VERSION 30 | @date = Date.today.to_s 31 | 32 | # include + format changelog 33 | @changelog = replace_html_special_chars File.read File.join( @path, 'CHANGELOG.md' ) 34 | 35 | # collect description files and turn them into html 36 | @cubes = Dir[ File.join(path, 'doc', 'desc', '*.yaml') ].inject({}) do |res, cube_file; a| 37 | begin 38 | a = YAML.load_file cube_file 39 | rescue 40 | warn "Could not load the yaml file for #{ cube_file }" 41 | end 42 | if a.instance_of? Hash 43 | res.merge a 44 | else 45 | res 46 | end 47 | end.sort.map{ |name, hash| cube name, hash }.join 48 | 49 | output_path = File.join(path, 'doc', 'index.html') 50 | template = DATA.read 51 | template.gsub! /\.\.([a-z]+)\.\./i do eval "@#$1" end # substitute vars 52 | template.gsub! /⇧(.+?)⇧/, '\1' 53 | template.gsub! /●(.+?)●/, '\1' 54 | template.gsub! /→(.+?)→(.+?)→/, '\1' 55 | File.open(output_path, 'w'){ |file| file.puts(template) } 56 | 57 | puts "Created SugarRefinery documentation at #{File.expand_path(output_path)}" 58 | end 59 | 60 | private 61 | 62 | def cube(name, hash) 63 | @cube_name = name 64 | %{

#{name}

65 | } + 68 | 69 | ORDER.map{ |th| 70 | if %w|spec use source|.include?(th) || td = hash[th] 71 | "" + 72 | " " 73 | end 74 | }.join + '
#{ DESCRIPTIONS[th] }#{ send th, td || name }
' 75 | end 76 | 77 | def use(n) 78 | "
#{ syntax_highlight "using SugarRefinery::#{n.to_camel}" }
" 79 | end 80 | 81 | def methods(m) 82 | m.map{ |name, usage| 83 | "
#{replace_html_special_chars name}
" + 84 | "
#{ syntax_highlight usage }
" 85 | }.join 86 | end 87 | 88 | def info(i) 89 | i.map{|e|convert_html_chars e}.join '
' 90 | end 91 | 92 | def summary(s) 93 | convert_html_chars s 94 | end 95 | 96 | def spec(_) 97 | source_helper(:spec, File.join( @path, 'spec/' ), '_spec') 98 | end 99 | 100 | def source(_) 101 | source_helper(:source, File.join( @path, 'lib/sugar_refinery') ) 102 | end 103 | 104 | def source_helper(kind, file_prefix, suffix='') 105 | %{ (show) 106 |
#{ 107 | get_source_file( File.join file_prefix, ( @cube_name + suffix + '.rb' ) ) 108 | }
} 109 | end 110 | 111 | def get_source_file(filename) 112 | if File.file? filename 113 | syntax_highlight( File.read(filename).strip ) 114 | else 115 | 'FIXME: missing (please create a github issue)' 116 | end 117 | end 118 | 119 | def syntax_highlight(string) 120 | CodeRay.scan(string, :ruby).div 121 | end 122 | 123 | def replace_html_special_chars(string) 124 | string.gsub( /&/, '&' ). 125 | gsub( //, '>' ) 127 | end 128 | 129 | def convert_html_chars(string, protect_spaces = false) 130 | string = replace_html_special_chars( string ) 131 | string = string.to_s.gsub( "\n", '
' ) 132 | 133 | if protect_spaces 134 | string.gsub(' ',' ') 135 | else 136 | string 137 | end 138 | end 139 | end 140 | end 141 | 142 | SugarRefineryDoc.generate *ARGV 143 | 144 | __END__ 145 | 147 | 148 | 149 | 150 | 151 | 152 | Ruby Sugar Refinery 153 | 161 | 422 | 423 | 424 |
425 | 426 |

Ruby Sugar Refinery

427 |
428 |

The Ruby Sugar Refinery is a collection of tiny refinements (declarative local core extensions) for Ruby.

429 | 430 |

Setup & Usage

431 |

432 | Add to Gemfile: 433 |

434 | 435 |
436 | gem 'sugar_refinery', require: 'sugar_refinery/all' 437 |
438 | 439 |

440 | Then add refinements to the current Ruby file or module: 441 |

442 |
using SugarRefinery::CamelSnake
443 | using SugarRefinery::HashZip
444 | 
445 | "ClassName".to_snake # => "class_name"
446 | Hash.zip [1,2,3], [4,5,6] # => {1=>4, 2=>5, 3=>6}
447 |
448 |

449 | 450 |

List of Refinements

451 | 452 | ..cubes.. 453 | 454 |

Changelog

455 |
456 |
..changelog..
457 |
458 |
459 |
460 | 461 | 467 | 468 | Fork me on GitHub 469 | 470 | 471 | 472 | --------------------------------------------------------------------------------