Code Monkey home page Code Monkey logo

crutches's People

Contributors

adzz avatar austinschwartz avatar axxiss avatar carlism avatar cyrusofeden avatar doomspork avatar druzn3k avatar duijf avatar eksperimental avatar erol avatar garman avatar janxious avatar jdl avatar jesuspc avatar joeyates avatar lpil avatar lubien avatar mayppong avatar mgwidmann avatar mykewould avatar paolodm avatar scrogson avatar stevensona avatar udfalkso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

crutches's Issues

Crutches.Format.Number.as_human_size

@doc ~S"""
Formats the bytes in `number` into a more understandable representation (e.g., 
giving it 1500 yields 1.5 KB). This method is useful for reporting file sizes to
users. You can customize the format in the `options` Dict.

See `as_human` if you want to pretty-print a generic number.

# Options

 * `:locale` - Sets the locale to be used for formatting (defaults to current locale).
 * `:precision` - Sets the precision of the number (defaults to 3).
 * `:significant` - If true, precision will be the # of significant_digits. If false, the # of fractional digits (defaults to true)
 * `:separator` - Sets the separator between the fractional and integer digits (defaults to “.”).
 * `:delimiter` - Sets the thousands delimiter (defaults to “”).
 * `:strip_insignificant_zeros` - If true removes insignificant zeros after the decimal separator (defaults to true)
 * `:prefix` - If :si formats the number using the SI prefix (defaults to :binary)

# Examples

    iex> Number.as_human_size(123)                                          
    "123 Bytes"

    iex> Number.as_human_size(1234)                                         
    "1.21 KB"

    iex> Number.as_human_size(12345)                                        
    "12.1 KB"

    iex> Number.as_human_size(1234567)                                      
    "1.18 MB"

    iex> Number.as_human_size(1234567890)                                   
    "1.15 GB"

    iex> Number.as_human_size(1234567890123)                                
    "1.12 TB"

    iex> Number.as_human_size(1234567, precision: 2)                        
    "1.2 MB"

    iex> Number.as_human_size(483989, precision: 2)                         
    "470 KB"

    iex> Number.as_human_size(1234567, precision: 2, separator: ',')        
    "1,2 MB"

    iex> Number.as_human_size(1234567890123, precision: 5)                  
    "1.1228 TB"

    iex> Number.as_human_size(524288000, precision: 5)                      
    "500 MB"

    iex> Number.as_human_size!("abc")
    ** (ArithmeticError) bad input number

"""

RFC: UnionRange / ComplexRange

Should we build a data structure based on Range that consist in the uninion of n Ranges or is out of scope? Should this live in a different project? Could be another library for kickstarting people in the world of Elixir!

Internationalization support

I think we should start thinking about internationalization. The porting of the NumberHelpers module has given this issue a boost on priority. Otherwise, the number helpers are mostly useless outside of USA. I think that linguist could be really easy to integrate. But, on the other hand, I think that the less dependencies we have, the better. Thoughts?

Investigate including a module extension mechanism

I found this gist that implements Elixir module inheritance/extension. Maybe this good functionality to provide (also seems to provide a way to alias modules like Crutches.List to List without shadowing the standard library).

The gist has one issue (it is marked as a todo): it doesn't provide something to override functions without changing all of those that call the overridden function. I don't know if this can be fixed without modifications to Elixir itself, but a lot of Elixir is defined in Elixir macros, so it might be doable.

Thoughts?

Array#to_formatted_s => List.to_formatted_s

Convert ActiveSupport Array#to_formatted_s to Crutches List.to_formatted_s

  # Extends <tt>Array#to_s</tt> to convert a collection of elements into a
  # comma separated id list if <tt>:db</tt> argument is given as the format.
  #
  #   Blog.all.to_formatted_s(:db) # => "1,2,3"

Hints to get started:

Additional resources:
List intro
List documentation

Add description to README and Crutches module

Right now I am unable to know what the aim of the project is unless I know about what ActiveSupport is.
Also, a description in the module doc should be added so it will appear in the docs

Array#in_groups => List.in_groups

  # Splits or iterates over the array in +number+ of groups, padding any
  # remaining slots with +fill_with+ unless it is +false+.
  #
  #   %w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
  #   ["1", "2", "3", "4"]
  #   ["5", "6", "7", nil]
  #   ["8", "9", "10", nil]
  #
  #   %w(1 2 3 4 5 6 7 8 9 10).in_groups(3, '&nbsp;') {|group| p group}
  #   ["1", "2", "3", "4"]
  #   ["5", "6", "7", "&nbsp;"]
  #   ["8", "9", "10", "&nbsp;"]
  #
  #   %w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
  #   ["1", "2", "3"]
  #   ["4", "5"]
  #   ["6", "7"]

Convert Array#in_groups => List.in_groups

Hints to get started:

  • in_groups should take 3 parameters, the last parameter is a function
  • Convert Ruby comments into Elixir doctests
  • TDD to solve

Additional resources:
List intro
List documentation

Add Integer.undigits/1

since we have Integer.digits/1, I think we should have Integer.undigits/1

the @doc for Integer.digits/1 is missing and it could be copied from Elixir codebase

Array#split => List.split

  # Divides the array into one or more subarrays based on a delimiting +value+
  # or the result of an optional block.
  #
  #   [1, 2, 3, 4, 5].split(3)              # => [[1, 2], [4, 5]]
  #   (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]

Convert Array#split => List.split

Hints to get started:

  • Split should be able to accept an integer or a function.
  • Convert Ruby comments into Elixir doctests
  • TDD to solve

Additional resources:
List intro
List documentation

Array#to_sentence => List.to_sentence

Convert ActiveSupport Array#to_sentence to Crutches List.to_sentence

  # Converts the array to a comma-separated sentence where the last element is
  # joined by the connector word.
  #
  # You can pass the following options to change the default behavior. If you
  # pass an option key that doesn't exist in the list below, it will raise an
  # <tt>ArgumentError</tt>.
  #
  # ==== Options
  #
  # * <tt>:words_connector</tt> - The sign or word used to join the elements
  #   in arrays with two or more elements (default: ", ").
  # * <tt>:two_words_connector</tt> - The sign or word used to join the elements
  #   in arrays with two elements (default: " and ").
  # * <tt>:last_word_connector</tt> - The sign or word used to join the last element
  #   in arrays with three or more elements (default: ", and ").
  # * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
  #   the connector options defined on the 'support.array' namespace in the
  #   corresponding dictionary file.
  #
  # ==== Examples
  #
  #   [].to_sentence                      # => ""
  #   ['one'].to_sentence                 # => "one"
  #   ['one', 'two'].to_sentence          # => "one and two"
  #   ['one', 'two', 'three'].to_sentence # => "one, two, and three"
  #
  #   ['one', 'two'].to_sentence(passing: 'invalid option')
  #   # => ArgumentError: Unknown key :passing
  #
  #   ['one', 'two'].to_sentence(two_words_connector: '-')
  #   # => "one-two"
  #
  #   ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
  #   # => "one or two or at least three"
  #
  # Using <tt>:locale</tt> option:
  #
  #   # Given this locale dictionary:
  #   #
  #   #   es:
  #   #     support:
  #   #       array:
  #   #         words_connector: " o "
  #   #         two_words_connector: " y "
  #   #         last_word_connector: " o al menos "
  #
  #   ['uno', 'dos'].to_sentence(locale: :es)
  #   # => "uno y dos"
  #
  #   ['uno', 'dos', 'tres'].to_sentence(locale: :es)
  #   # => "uno o dos o al menos tres"

Hints to get started:

  • Create a Crutches.List module (if it does not exist)
  • Convert Ruby comments into Elixir doctests
  • TDD to solve

Additional resources:
List intro
List documentation

Crutches.Format.Number.as_currency

@doc ~S"""
Formats a `number` into a currency string (e.g., $13.65). You can customize the format in 
the `options` hash. The `as_currency!` method raises an exception if the input is 
not numeric

# Options

 * `:locale` - Sets the locale to be used for formatting (defaults to current locale).
 * `:precision` - Sets the level of precision (defaults to 2).
 * `:unit` - Sets the denomination of the currency (defaults to “$”).
 * `:separator` - Sets the separator between the units (defaults to “.”).
 * `:delimiter` - Sets the thousands delimiter (defaults to “,”).
 * `:format` - Sets the format for non-negative numbers (defaults to “%u%n”). Fields are %u for the currency, and %n for the number.
 * `:negative_format` - Sets the format for negative numbers (defaults to prepending an hyphen to the formatted number given by :format). Accepts the same fields than :format, except %n is here the absolute value of the number.

# Examples


    iex> Number.as_currency(1234567890.50)                    
    "$1,234,567,890.50"

    iex> Number.as_currency(1234567890.506)                   
    "$1,234,567,890.51"

    iex> Number.as_currency(1234567890.506, precision: 3)     
    "$1,234,567,890.506"

    iex> Number.as_currency(1234567890.506, locale: :fr)      
    "1 234 567 890,51 €"

    iex> Number.as_currency("123a456")                        
    "$123a456"

    iex> Number.as_currency!("123a456")
    ** (ArithmeticError) invalid number

    iex> Number.as_currency(-1234567890.50, negative_format: "(%u%n)")
    "($1,234,567,890.50)"

    iex> Number.as_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "")
    "R$1234567890,50"

    iex> Number.as_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "", format: "%n %u")
    "1234567890,50 R$"

"""

Crutches.String.truncate

Truncates a given `text` after a given `length` if `text` is longer than `length`:

## Examples

    iex> String.truncate("Once upon a time in a world far far away", 27)
    "Once upon a time in a wo..."

    iex> String.truncate("Once upon a time in a world far far away", 27, separator: " ")
    "Once upon a time in a..."

    iex> String.truncate("Once upon a time in a world far far away", 27, separator: ~r/\s/)
    "Once upon a time in a..."

    iex> String.truncate("And they found that many people were sleeping better.", 25, omission: "... (continued)")
    "And they f... (continued)"

Crutches.Format.to_xml

More information to come. Generated from #7.

  • Copy/paste the provided ElixirDoc/DocTest
  • Add xml_builder as a dependency (look into how to do that)
  • Write the appropriate code to call the appropriate xml_builder functions.

Array#from => List.from

Convert ActiveSupport Array#from to Crutches List.from

  # Returns the tail of the array from +position+.
  #
  #   %w( a b c d ).from(0)  # => ["a", "b", "c", "d"]
  #   %w( a b c d ).from(2)  # => ["c", "d"]
  #   %w( a b c d ).from(10) # => []
  #   %w().from(0)           # => []
  #   %w( a b c d ).from(-2) # => ["c", "d"]
  #   %w( a b c ).from(-10)  # => []

Hints to get started:

  • Create a Crutches.List module
  • Convert Ruby comments into Elixir doctests
  • TDD to solve

Additional resources:
List intro
List documentation

Array#to => List.to

Convert ActiveSupport Array#to to Crutches List.to

  # Returns the beginning of the array up to +position+.
  #
  #   %w( a b c d ).to(0)  # => ["a"]
  #   %w( a b c d ).to(2)  # => ["a", "b", "c"]
  #   %w( a b c d ).to(10) # => ["a", "b", "c", "d"]
  #   %w().to(0)           # => []
  #   %w( a b c d ).to(-2) # => ["a", "b", "c"]
  #   %w( a b c ).to(-10)  # => []

Hints to get started:

  • Create a Crutches.List module
  • Convert Ruby comments into Elixir doctests
  • TDD to solve

Additional resources:
List intro
List documentation

CLA is not signed by all contributors

The CLA at https://github.com/FLIF-hub/FLIF-CLAs has been signed by 3 people so far (as of 20151119).
There are 17 contributors so far (as of 20151119) to https://github.com/FLIF-hub/FLIF
One of the contributors is jonsneyers, so that means there are 13 other contributors who have contributed code to FLIF, yet have not signed the CLA.
This needs to be rectified as soon as possible, otherwise later re-licensing of the code from GPLv3 to any other license becomes extremely difficult or impossible.

Crutches.Format.Number.as_percentage

@doc ~S"""
Formats a `number` as a percentage string (e.g., 65%). You can customize the 
format in the `options` Dict

The `as_percentage!` method raises an error if the input is not numeric.

# Options

 * `:locale` - Sets the locale to be used for formatting (defaults to current locale).
 * `:precision` - Sets the precision of the number (defaults to 3).
 * `:significant` - If true, precision will be the # of significant_digits. If false, the # of fractional digits (defaults to false).
 * `:separator` - Sets the separator between the fractional and integer digits (defaults to “.”).
 * `:delimiter` - Sets the thousands delimiter (defaults to “”).
 * `:strip_insignificant_zeros` - If true removes insignificant zeros after the decimal separator (defaults to false).
 * `:format` - Specifies the format of the percentage string The number field is %n (defaults to “%n%”).

# Examples

    iex> Number.as_percentage(100)                                        
    "100.000%"

    iex> Number.as_percentage("98")                                       
    "98.000%"

    iex> Number.as_percentage(100, precision: 0)                          
    "100%"

    iex> Number.as_percentage(1000, delimiter: '.', separator: ',')       
    "1.000,000%"

    iex> Number.as_percentage(302.24398923423, precision: 5)              
    "302.24399%"

    iex> Number.as_percentage(1000, locale: :fr)                          
    "1 000,000%"

    iex> Number.as_percentage("98a")                                      
    "98a%"

    iex> Number.as_percentage(100, format: "%n  %")                       
    "100  %"

    iex> Number.as_percentage!("98a", raise: true)                        
    ** (ArithmeticError) bad input number

"""

Continuous integration

It could be worthwhile to adopt CI to get some feedback on tests in PRs. In addition, we get some awesome badges :)

There are a couple of services that I like and work with Elixir projects:

  • Travis CI continuous integration that checks the correctness of the code.
  • Inch CI feedback on documentation quality.

Curious to hear thoughts and opinions. If any help is needed to set it all up, I'll gladly help.

Array#to_xml => List.to_xml

  # Returns a string that represents the array in XML by invoking +to_xml+
  # on each element. Active Record collections delegate their representation
  # in XML to this method.
  #
  # All elements are expected to respond to +to_xml+, if any of them does
  # not then an exception is raised.
  #
  # The root node reflects the class name of the first element in plural
  # if all elements belong to the same type and that's not Hash:
  #
  #   customer.projects.to_xml
  #
  #   <?xml version="1.0" encoding="UTF-8"?>
  #   <projects type="array">
  #     <project>
  #       <amount type="decimal">20000.0</amount>
  #       <customer-id type="integer">1567</customer-id>
  #       <deal-date type="date">2008-04-09</deal-date>
  #       ...
  #     </project>
  #     <project>
  #       <amount type="decimal">57230.0</amount>
  #       <customer-id type="integer">1567</customer-id>
  #       <deal-date type="date">2008-04-15</deal-date>
  #       ...
  #     </project>
  #   </projects>
  #
  # Otherwise the root element is "objects":
  #
  #   [{ foo: 1, bar: 2}, { baz: 3}].to_xml
  #
  #   <?xml version="1.0" encoding="UTF-8"?>
  #   <objects type="array">
  #     <object>
  #       <bar type="integer">2</bar>
  #       <foo type="integer">1</foo>
  #     </object>
  #     <object>
  #       <baz type="integer">3</baz>
  #     </object>
  #   </objects>
  #
  # If the collection is empty the root element is "nil-classes" by default:
  #
  #   [].to_xml
  #
  #   <?xml version="1.0" encoding="UTF-8"?>
  #   <nil-classes type="array"/>
  #
  # To ensure a meaningful root element use the <tt>:root</tt> option:
  #
  #   customer_with_no_projects.projects.to_xml(root: 'projects')
  #
  #   <?xml version="1.0" encoding="UTF-8"?>
  #   <projects type="array"/>
  #
  # By default name of the node for the children of root is <tt>root.singularize</tt>.
  # You can change it with the <tt>:children</tt> option.
  #
  # The +options+ hash is passed downwards:
  #
  #   Message.all.to_xml(skip_types: true)
  #
  #   <?xml version="1.0" encoding="UTF-8"?>
  #   <messages>
  #     <message>
  #       <created-at>2008-03-07T09:58:18+01:00</created-at>
  #       <id>1</id>
  #       <name>1</name>
  #       <updated-at>2008-03-07T09:58:18+01:00</updated-at>
  #       <user-id>1</user-id>
  #     </message>
  #   </messages>
  #

Convert ActiveSupport Array#to_xml to Crutches List.to_xml

Hints to get started:

Additional resources:
List intro
List documentation
XML resources for Elixir
Parsing Elixir

"to" function name is misleading

I was skimming through the docs, this one certainly called my attention.

to is generally used to convert data type from one type to another, such as in Enum.to_list/1, Float.to_string/1

I think Crutches.List.to/2 will make more sense to rename it Crutches.List.up_to/2
the thing is what are you gonna name "from".

personally I think having Enum.slice/3 there is not need to have such functions (and Enum will work with any enumerable, not just lists).

in a case you want to keep it , maybe Enum.slice_to Enum.slice_from would be more clear (but redundant IMO)

Crutches.Format.Number.as_rounded

@doc ~S"""
Formats a `number` with the specified level of :precision (e.g., 112.32 has a 
precision of 2 if `:significant` is false, and 5 if `:significant` is true). You
can customize the format in the `options` Dict.

# Options

  * `:locale` - Sets the locale to be used for formatting (defaults to current locale).
  * `:precision` - Sets the precision of the number (defaults to 3).
  * `:significant` - If true, precision will be the # of significant_digits. If false, the # of fractional digits (defaults to false).
  * `:separator` - Sets the separator between the fractional and integer digits (defaults to “.”).
  * `:delimiter` - Sets the thousands delimiter (defaults to “”).
  * `:strip_insignificant_zeros` - If true removes insignificant zeros after the decimal separator (defaults to false).

# Examples

    iex> Number.as_rounded(111.2345)                                  
    "111.235"

    iex> Number.as_rounded(111.2345, precision: 2)                    
    "111.23"

    iex> Number.as_rounded(13, precision: 5)                          
    "13.00000"

    iex> Number.as_rounded(389.32314, precision: 0)                   
    "389"

    iex> Number.as_rounded(111.2345, significant: true)               
    "111"

    iex> Number.as_rounded(111.2345, precision: 1, significant: true) 
    "100"

    iex> Number.as_rounded(13, precision: 5, significant: true)       
    "13.000"

    iex> Number.as_rounded(111.234, locale: :fr)                      
    "111,234"

    iex> Number.as_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
    "13"

    iex> Number.as_rounded(389.32314, precision: 4, significant: true) 
    "389.3"

    iex> Number.as_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.') 
    "1.111,23"

"""

Array#without => List.without

Convert ActiveSupport Array#without to Crutches List.without

  # Returns a copy of the Array without the specified elements.
  #
  #   people = ["David", "Rafael", "Aaron", "Todd"]
  #   people.without "Aaron", "Todd"
  #     => ["David", "Rafael"]
  #
  # Note: This is an optimization of `Enumerable#without` that uses `Array#-`
  # instead of `Array#reject` for performance reasons.

Hints to get started:

  • Create a Crutches.List module (if it does not exist)
  • Convert Ruby comments into Elixir doctests
  • TDD to solve

Additional resources:
List intro
List documentation

Crutches.Range.overlaps?

Compare two ranges and see if they overlap each other

## Examples

  iex> Range.overlaps?(1..5, 4..6)
  true 

  iex> Range.overlaps?(1..5, 7..9)
  false

Make use of Option.combine instead of Option.validate!

PR #43 is now merged, which gives us some nicer functions to handle keyword options to functions, but we aren't out of the woods yet. There are a couple of locations in the library that aren't making use of the new functions in the Crutches.Option module yet.

Here is a list:

  • Crutches.Format.Number.as_delimited/2, see #57.
  • Crutches.Format.Number.as_phone/2
  • Crutches.Format.Number.as_currency/2
  • Crutches.List.as_sentence/2

These need to be refactored to make use of the following convention (if possible):

@function_name [
  valid: [:some, :option],
  defaults: [
    some: "foo",
    option: "bar"
  ]
]
def function_name(args, opts \\ @function_name[:defaults])
def function_name(args, opts) do
  # This validates and merges the options, throwing on error.
  opts = Crutches.Option.combine!(opts, @function_name) # Or use Option.combine[!]/3

  ...
end

Tests (in general) shouldn't require modifications. Everyone is free to work on this, but I'm going to tackle the first one to provide an example.

In the meantime, if you find that a function cannot be changed to make use of this convention, please do post why. Might be because we are missing a use case in the Option module and I'd like to know!

number_to_human issue when rounding up to next unit

iex(1)> Crutches.Format.Number.as_human 999_499
"999 Thousand"
iex(2)> Crutches.Format.Number.as_human 999_500
"1000 Thousand"
iex(3)> Crutches.Format.Number.as_human 999_999
"1000 Thousand"
iex(4)> Crutches.Format.Number.as_human 1_000_000
"1 Million"
iex(5)> Crutches.Format.Number.as_human 999_999_999
"1000 Million"

"1000 thousand" should probably be "1 million". Same with "1000 Million", "1000 Billion", etc.

FWIW, Rails/ActiveSupport had this same issue up until 2 months ago

Crutches.Format.to_json

More information to come. Generated form #7.

  • Copy/paste the provided ElixirDoc/DocTest
  • Add poison as a dependency (look into how to do that)
  • Write the appropriate code to call the appropriate poison functions

Crutches.Format.Number.as_human

@doc ~S"""
Pretty prints (formats and approximates) a `number` in a way it is more readable 
by humans (eg.: 1200000000 becomes “1.2 Billion”). This is useful for numbers 
that can get very large (and too hard to read).

See `as_human_size` if you want to print a file size.

You can also define you own unit-quantifier names if you want to use other 
decimal units (eg.: 1500 becomes “1.5 kilometers”, 0.150 becomes 
“150 milliliters”, etc). You may define a wide range of unit quantifiers, even 
fractional ones (centi, deci, mili, etc).

The `as_human!` method raises an exception if the input is not a valid 
number

# Options

  * `:locale` - Sets the locale to be used for formatting (defaults to current 
    locale).
  * `:precision` - Sets the precision of the number (defaults to 3).
  * `:significant` - If true, precision will be the # of significant_digits. If 
    false, the # of fractional digits (defaults to true)
  * `:separator` - Sets the separator between the fractional and integer digits
    (defaults to “.”).
  * `:delimiter` - Sets the thousands delimiter (defaults to “”).
  * `:strip_insignificant_zeros` - If true removes insignificant zeros after the
    decimal separator (defaults to true)
  * `:units` - A Hash of unit quantifier names. Or a string containing an i18n 
    scope where to find this hash. It might have the following keys:
    + `integers`: :unit, :ten, :hundred, :thousand, :million, :billion, 
      :trillion, :quadrillion
    + `fractionals`: :deci, :centi, :mili, :micro, :nano, :pico, :femto
  * `:format` - Sets the format of the output string (defaults to “%n %u”). 
    The field types are:
    +  %u - The quantifier (ex.: 'thousand')
    +  %n - The number

# Examples

  iex> Number.as_human(123)                                          
  "123"

  iex> Number.as_human(1234)                                         
  "1.23 Thousand"

  iex> Number.as_human(12345)                                        
  "12.3 Thousand"

  iex> Number.as_human(1234567)                                      
  "1.23 Million"

  iex> Number.as_human(1234567890)                                   
  "1.23 Billion"

  iex> Number.as_human(1234567890123)                                
  "1.23 Trillion"

  iex> Number.as_human(1234567890123456)                             
  "1.23 Quadrillion"

  iex> Number.as_human(1234567890123456789)                          
  "1230 Quadrillion"

  iex> Number.as_human(489939, precision: 2)                         
  "490 Thousand"

  iex> Number.as_human(489939, precision: 4)                         
  "489.9 Thousand"

  iex> Number.as_human(1234567, precision: 4, significant: false)    
  "1.2346 Million"

  iex> Number.as_human(1234567, precision: 1,separator: ',', significant: false)
  "1,2 Million"

  iex> Number.as_human(500000000, precision: 5)                      
  "500 Million"

  iex> Number.as_human(12345012345, significant: false)              
  "12.345 Billion"

  iex> Number.as_human!("abc")
  ** (ArithmeticError) bad input number

"""

Compatible license with Elixir's one

Hi, i just found out through the elixir mailing list about this project.
I have thought about something like this for a while, so kudos for creating something like this,
I have code to contribute, but before moving forward I would like to make a comment that can be taking into consideration.
Given the nature of the project, it is very likely that at some point some of the functions may end up making it into Elixir code base.
So i think to avoid conflicts in the future, it should be considered to release the code under a dual license, MIT/APACHE2, or maybe a public license.

I think if still be needed to release the rights to the elixir project if they want to be included as a special mention in the NOTICE file is unlikely to happen.

Maybe there's an easier solution, like anybody submitting code, agrees that it could potentially be added to Elixir project, maybe we could include the credits in the commit message when added to elixir.

Project status.

As the idea of the project is to create kind of an Active Support migration. Would be nice to have a checklist of ActiveSupport features and what is already done. This will generate a better notion of the project status.

What do you think of this?

Options.combine!

Currently, I'm seeing something along these lines a lot:

@function_name [
  valid_options: [:some, :option],
  default_options: [
    some: "foo"
    option: "bar"
  ]
]
def function_name(args, opts \\ @function_name[:default_options])
def function_name(args, opts) do
  Crutches.Keyword.validate_keys!(opts, @function_name[:valid_options])
  options = Keyword.merge(@function_name[:default_options], opts)

  ...
end

I think it would be nice if we instead could write something like this:

@function_name [
  valid: [:some, :option],
  defaults: [
    some: "foo",
    option: "bar"
  ]
]
def function_name(args, opts \\ @function_name[:defaults])
def function_name(args, opts) do
  # This validates and merges the options, throwing on error.
  opts = Crutches.Options.combine!(opts, @function_name)

  ...
end

It is less code to keep track of, it makes the intent more clear and is a bit less to type. I also think it is a better API.

I'll work on this if we end up liking this. Going to be lots of work and be a little invasive to adopt this everywhere.

What kind of variants seem to be good? I have thought of:

  • Options.combine!(options, configuration) — throwing
  • Options.combine(options, configuration) — non-throwing
  • Options.combine!(options, configuration, combinator) — throwing, with custom combinator.
  • Options.combine(options, configuration, combinator) — non-throwing, with custom combinator.

Anything else? Feedback welcome :)

Do you have a list of issues that are coming?

Hey there.
I saw your post on reddit and this looks like a fun project to help with. I'm an Elixir newbie, but the easier issues seem like a great place to start. Seems like they're all being worked on though. Do you have more coming soon, or a suggestion for a missing feature?

Expose bad_options_check

  @doc ~S"""
  Checks a keyword list for unexpected keys, by using a default list of keys. When a bad key is detected it returns false, else it returns true.

  ## Examples

      iex> Keyword.all_keys_valid?([good: "", good_opt: ".", bad: "!"], [:good, :good_opt])
      false

      iex> Keyword.all_keys_valid?([good: "", good_opt: "."], [:good, :good_opt])
      true
  """

Hints to get started:

  • Create a Crutches.Keyword module (if it does not exist)
  • Copy in the above doctest.
  • TDD to solve (mix test)
  • Add more tests as needed.

Additional resources:
The bad_options_check where most functionality will reside
Keyword intro
Keyword documentation

Wiki Design: Discussion

Initial layout proposal for wiki design. Obviously we want it so that it covers enough information for a beginner to get started. I have no intentions of duplicating efforts around Elixir documentation, but there will be a links section for those who are totally new to the language. Most of the documentation will link to the code where the functions are described in more detail. The FAQ will outline some of the questions and concerns we've talked about in issues and PRs.

Feedback and thoughts always welcome!

Wiki Design (Very rough)

  • Welcome
    • Links
  • How to Contribute
    • Getting started
    • Styleguide
    • FAQ for contributors
  • Documentation
    • Enum
    • Integer
    • Keyword
    • List
    • String

Got an idea?

If you'd like to see something implemented into Crutches, please post it here. I'll do the leg work of writing up the documentation for the issue, I just need your ideas!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.