README.adoc in refinements-7.14.0 vs README.adoc in refinements-7.15.0

- old
+ new

@@ -26,10 +26,11 @@ * Hash * IO * Pathname * String * StringIO +* Structs == Requirements . https://www.ruby-lang.org[Ruby]. . A solid understanding of link:https://www.alchemists.io/articles/ruby_refinements[Ruby refinements @@ -73,10 +74,11 @@ require "refinements/hashes" require "refinements/ios" require "refinements/pathnames" require "refinements/strings" require "refinements/string_ios" +require "refinements/structs" ---- === Using Much like including/extending a module, you’ll need to modify your object(s) to use the @@ -92,10 +94,11 @@ using Refinements::Hashes using Refinements::IOs using Refinements::Pathnames using Refinements::Strings using Refinements::StringIOs + using Refinements::Structs end ---- === Examples @@ -479,15 +482,12 @@ stream. When given a block, the stream will automatically close upon block exit. When not given a block, you'll need to close the stream manually. [source,ruby] ---- -io = IO.void -io.closed? # => false - -io = IO.void { |void| void.write "nevermore" } -io.closed? # => true +io = IO.void # => #<IO:fd 20> +io = IO.void { |void| void.write "nevermore" } # => #<IO:(closed)> ---- ===== #redirect Redirects current stream to other stream when given a block. Without a block, the original stream is @@ -496,15 +496,12 @@ [source,ruby] ---- io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+") other = IO.new IO.sysopen(Pathname("other.txt").to_s, "w+") -io.redirect other # => `io` - -io.redirect(other) { |stream| stream.write "test" } - .close # => "" -other.close # => "test" +io.redirect other # => #<IO:fd 20> +io.redirect(other) { |stream| stream.write "test" } # => #<IO:fd 21> ---- ===== #reread Answers full stream by rewinding to beginning of stream and reading all content. @@ -516,34 +513,35 @@ io.reread # => "This is a test." io.reread 4 # => "This" buffer = "".dup -io.reread(buffer: buffer) -buffer # => "This is a test." +io.reread(buffer: buffer) # => "This is a test." +buffer # => "This is a test." ---- ===== #squelch -Temporarily ignores any reads/writes for current stream for all code executed within the block. When -not given a block, it answers itself. +Temporarily ignores any reads/writes for code executed within a block. Answers itself without any +arguments or when given a block. [source,ruby] ---- io = IO.new IO.sysopen(Pathname("test.txt").to_s, "w+") -io.squelch { io.write "Test" } -io.reread # => "" +io.squelch # => #<IO:fd 20> +io.squelch { io.write "Test" } # => #<IO:fd 20> +io.reread # => "" ---- ==== Pathname ===== Pathname -Enhances the conversion function -- refined from `Kernel` -- which casts `nil` into a pathname in -order to avoid: `TypeError (no implicit conversion of nil into String)`. The pathname is still -invalid but at least you have an instance of `Pathname`, which behaves like a _Null Object_, that -can still be used to construct a valid path. +Enhances the `Kernel` conversion function which casts `nil` into a pathname in order to avoid: +`TypeError (no implicit conversion of nil into String)`. The pathname remains invalid but at least +you have an instance of `Pathname`, which behaves like a _Null Object_, that can be used to +construct a valid path. [source,ruby] ---- Pathname(nil) # => Pathname("") ---- @@ -557,27 +555,27 @@ ---- Pathname.pwd # => "/" Pathname("/test").make_dir.change_dir # => Pathname "/test" Pathname.pwd # => "/test" -Pathname.pwd # => "/" -Pathname("/test").make_dir.change_dir { # Implementation details } # => Pathname "/test" -Pathname.pwd # => "/" +Pathname.pwd # => "/" +Pathname("/test").make_dir.change_dir { "example" } # => "example" +Pathname.pwd # => "/" ---- ===== #copy -Copies file from current location to new location. +Copies file from current location to new location while answering itself so it can be chained. [source,ruby] ---- -Pathname("input.txt").copy Pathname("output.txt") +Pathname("input.txt").copy Pathname("output.txt") # => Pathname("input.txt") ---- ===== #directories -Answers all or filtered directories for current path. +Answers all directories or filtered directories for current path. [source,ruby] ---- Pathname("/example").directories # => [Pathname("a"), Pathname("b")] Pathname("/example").directories "a*" # => [Pathname("a")] @@ -593,11 +591,11 @@ Pathname("example.txt.erb").extensions # => [".txt", ".erb"] ---- ===== #files -Answers all or filtered files for current path. +Answers all files or filtered files for current path. [source,ruby] ---- Pathname("/example").files # => [Pathname("a.txt"), Pathname("a.png")] Pathname("/example").files "*.png" # => [Pathname("a.png")] @@ -621,13 +619,13 @@ Ensures all ancestor directories are created for a path. [source,ruby] ---- -Pathname("/one/two").make_ancestors -Pathname("/one").exist? # => true -Pathname("/one/two").exist? # => false +Pathname("/one/two").make_ancestors # => Pathname("/one/two") +Pathname("/one").exist? # => true +Pathname("/one/two").exist? # => false ---- ===== #make_dir Provides alternative `#mkdir` behavior by always answering itself (even when directory exists) and @@ -706,23 +704,36 @@ When given a block, it provides the contents of the recently read file for manipulation and immediate writing back to the same file. [source,ruby] ---- -Pathname("/test.txt").rewrite { |content| content.sub "[placeholder]", "example" } +Pathname("/test.txt").rewrite # => Pathname("/test.txt") +Pathname("/test.txt").rewrite { |body| body.sub "[token]", "example" } # => Pathname("/test.txt") ---- ===== #touch Updates access and modification times for path. Defaults to current time. [source,ruby] ---- -Pathname("example.txt").touch -Pathname("example.txt").touch at: Time.now - 1 +Pathname("example.txt").touch # => Pathname("example.txt") +Pathname("example.txt").touch at: Time.now - 1 # => Pathname("example.txt") ---- +===== #write + +Writes to file and answers itself so it can be chained. See `IO.write` for details on additional +options. + +[source,ruby] +---- +Pathname("example.txt").write "test" # => Pathname("example.txt") +Pathname("example.txt").write "test", offset: 1 # => Pathname("example.txt") +Pathname("example.txt").write "test", mode: "a" # => Pathname("example.txt") +---- + ==== String ===== #blank? Answers `true`/`false` based on whether string is blank, `<space>`, `\n`, `\t`, and/or `\r`. @@ -836,11 +847,55 @@ io.reread # => "This is a test." io.reread 4 # => "This" buffer = "".dup -io.reread(buffer: buffer) -buffer # => "This is a test." +io.reread(buffer: buffer) # => "This is a test." +buffer # => "This is a test." +---- + +==== Struct + +===== #merge + +Merges multiple attributes without mutating itself. + +[source,ruby] +---- +Example = Struct.new :a, :b, :c +example = Example[1, 2, 3] +example.merge a: 10 # => #<struct a=10, b=2, c=3> +example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30> +example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30> +example # => #<struct a=1, b=2, c=3> + +Example = Struct.new :a, :b, :c, keyword_init: true +example = Example[a: 1, b: 2, c: 3] +example.merge a: 10 # => #<struct a=10, b=2, c=3> +example.merge a: 10, c: 30 # => #<struct a=10, b=2, c=30> +example.merge a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30> +example # => #<struct a=1, b=2, c=3> +---- + +===== #merge! + +Merges multiple attributes while mutating itself. + +[source,ruby] +---- +Example = Struct.new :a, :b, :c +example = Example[1, 2, 3] +example.merge! a: 10 # => #<struct a=10, b=2, c=3> +example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30> +example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30> +example # => #<struct a=10, b=20, c=30> + +Example = Struct.new :a, :b, :c, keyword_init: true +example = Example[a: 1, b: 2, c: 3] +example.merge! a: 10 # => #<struct a=10, b=2, c=3> +example.merge! a: 10, c: 30 # => #<struct a=10, b=2, c=30> +example.merge! a: 10, b: 20, c: 30 # => #<struct a=10, b=20, c=30> +example # => #<struct a=10, b=20, c=30> ---- == Development To contribute, run: