crystallabs-helpers
Crystallabs-helpers
Collection of useful helper modules.
There is no disadvantage to using this shard in projects that only require part of its functionality. Crystal does not include unused functions in the resulting binary.
Installation
-
Add the dependency to your
shard.yml:dependencies: crystallabs-helpers: github: crystallabs/crystallabs-helpers.cr version: ~> 1.0 -
Run
shards install
Usage
Helper functionality is split by modules. Include the modules where you need them:
Crystallabs::Helpers::Logging
macro included
Log = ::Log.for self.name.gsub("::", '.').underscore
end
# Returns as a string the current method name and all arguments inspected.
macro my(*args)
end
Usage:
# Automatically prefixes log lines with self' name
Log.debug { ... }
# Log object/variable values inspected
Log.debug { my varx, vary, ... }
Crystallabs::Helpers::Boolean
def to_b(arg : String, empty = false)
def to_b(arg : Int, empty = false)
def to_b(arg : Char, empty = false)
def to_b(arg : Nil, empty = false)
def to_b(arg : Bool, empty = false)
def to_i(arg : Bool)
Usage:
to_b "0"
to_b 1
to_b '0'
to_b nil
to_i true
Crystallabs::Helpers::Enums
Lets callers refer to enum members by Symbol or String shorthand
(e.g. :center / "center", or {:vcenter, :right} for @[Flags]
enums) instead of spelling out the fully-qualified enum constant.
# Generic conversion, works for any enum T:
Crystallabs::Helpers::Enums.from(T.class, value)
# Declares an enum property whose setter also accepts shorthands:
macro enum_property(decl)
Usage:
Crystallabs::Helpers::Enums.from AlignFlag, :center # => Center
Crystallabs::Helpers::Enums.from AlignFlag, "center" # => Center
Crystallabs::Helpers::Enums.from AlignFlag, {:vcenter, :right} # => VCenter | Right
class Widget
Crystallabs::Helpers::Enums.enum_property align : AlignFlag = AlignFlag::Top
end
w = Widget.new
w.align = :center # => Center
w.align = {:vcenter, :right} # => VCenter | Right
w.align = AlignFlag::Left # real enum values still work
Crystallabs::Helpers::Alias_Methods
Allows aliasing methods. Use only when needed since in general Crystal ecosystem does not prefer aliases.
The alias copies each overload's parameter list (restrictions, defaults,
keyword args, block), so named arguments and blocks work. Aliasing a method
with multiple overloads via alias_previous is unreliable; use alias_method.
macro alias_method(new_method, old_method)
macro alias_previous(*new_methods)
Usage:
alias_method new_method_name, existing_method_name
alias_method :new_method_name=, :existing_method_name=
def mymethod
end
alias_previous new_name
Crystallabs::Helpers::Files
def self.find_file(start : String, target : String) : String?
Depth-first search for a file named target under start. Returns the full
path or nil. Skips /dev, /sys, /proc, /net, unreadable directories,
and does not descend into symlinked directories.
Usage:
Crystallabs::Helpers::Files.find_file "/etc", "hosts" # => "/etc/hosts"
Crystallabs::Helpers::Format
def self.humanize_bytes(bytes : Int) : String
def self.truncate(str : String, len : Int32, marker : Char = '~') : String
humanize_bytes uses binary units up to PiB. truncate shortens a string
to len characters, replacing the last kept character with marker.
Usage:
Crystallabs::Helpers::Format.humanize_bytes 842 # => "842B"
Crystallabs::Helpers::Format.humanize_bytes 3276 # => "3.2KiB"
Crystallabs::Helpers::Format.truncate "abcdef", 4 # => "abc~"
Crystallabs::Helpers::Streams
def self.extract_lines(carry : Bytes, chunk : Bytes) : {Array(String), Bytes}
Splits carry + chunk into complete lines (stripping trailing \r) and
returns them with the leftover partial line to pass as carry next time.
Usage:
lines, carry = Crystallabs::Helpers::Streams.extract_lines carry, chunk
Crystallabs::Helpers::BoundedCache
class BoundedCache(K, V)
def initialize(capacity : Int32, *, lru : Bool = false, by_identity : Bool = false)
def [](key), []?(key), []=(key, value), fetch(key, &), has_key?(key)
def delete(key), clear, size, each
A Hash-like memo cache that evicts the oldest entry past capacity
(FIFO; lru: true for least-recently-used; capacity <= 0 is unbounded).
fetch memoizes the block result, including nil.
Usage:
cache = Crystallabs::Helpers::BoundedCache(String, Int32).new 100
cache.fetch("key") { expensive_computation }
Crystallabs::Helpers::KillRing
class KillRing
def initialize(capacity : Int32 = 60)
def kill(text : String, *, prepend : Bool = false)
def yank : String?
def interrupt
def clear
Emacs/readline-style kill ring. Consecutive kills merge into one entry
(prepend: true for backward kills) until interrupt. KillRing.default
is a shared instance.
Usage:
ring = Crystallabs::Helpers::KillRing.default
ring.kill "foo"
ring.kill "bar"
ring.yank # => "foobar"
Crystallabs::Helpers::RunningAverage
class RunningAverage
def initialize(capacity : Int32)
def avg(value : Int32) : Int64
Pushes a value and returns the average over the last capacity values. capacity must be positive.
Usage:
avg = Crystallabs::Helpers::RunningAverage.new 3
avg.avg 1
avg.avg 2
avg.avg 3 # => 2