nestedtext 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfafdf3e9638459777da2f7209954955473758103c72533b58a66cc23f4020e3
4
- data.tar.gz: 400fd879811f4d09c193da219ffa0ff61853ee0e51baac386c58b7016dfbe354
3
+ metadata.gz: 195cf273687c9cf4af35eaea661eef6086bdb8b1f47578092e7473a4cb56a418
4
+ data.tar.gz: 32ca43c2433eea7065cd56e2809c85accd1165a3bf734e5ba0525fe3a256f56a
5
5
  SHA512:
6
- metadata.gz: 708025814b4038b1b5c6eea70378762e1155ae73e933cc902a17d26d4ce3efbb2a5b52f7d535c385818e34484fe12278f981c253469d80a875e97aa8f25b20c1
7
- data.tar.gz: fe87505719301bf79a71cdef1c9d89d71f9058318f5f59f1305ac79b0b69007b79976d6e288a4846824c6cc89323021b4b29df56b8f14f534cd59906d55b0843
6
+ metadata.gz: 8869b326141ccf9e56653bade9795f5a110f45d628df8eb1c372763a7cf5bfe7cb8a1077ff0fb36e5b0ec466f5f9f286fe877e1aaf1a4af3271c4ce5f8f718ed
7
+ data.tar.gz: ac63098b99b0d5d4f2060ecae53d8f325ca64af240e7250e07f3757088d7aee9ef81f495f8b4969b7a139f373b2c77d8c0711d947421ef41075f6671b2d9c453
data/CHANGELOG.md CHANGED
@@ -6,6 +6,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [4.0.0] - 2022-01-28
10
+ ### Changed
11
+ - **Breaking change**: Renamed `NTEncodeMixin` to `ToNTMixin`.
12
+ - All code linted with RuboCop
13
+
14
+ ## [3.2.1] - 2022-01-27
15
+ ### Fixed
16
+ - Fix logo at rubydoc.info
17
+
18
+ ## [3.2.0] - 2022-01-27
19
+ ### Changed
20
+ - Switch from rdoc formatting syntax to Markdown with Redcarpet to be able to render README.md properly.
21
+
22
+ ## [3.1.0] - 2022-01-27
23
+ ### Changed
24
+ - Switch from rdoc to YARD to match rubydoc.info that is used automatically for Gems uploaded to rubygems.org.
25
+
9
26
  ## [3.0.0] - 2022-01-27
10
27
  ### Added
11
28
  - API documentation generated with rdoc.
@@ -14,7 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
31
  - Removed leaked `NT_MIXIN` constant in core extensions.
15
32
 
16
33
  ### Changed
17
- - **Breaking change**: `#to_nt` on `String`, `Array` and `Hash` is no longer strict by default for consistency an unexpected surprises e.g. when having an array of CustomObjects and calling the method on the array.
34
+ - **Breaking change**: `#to_nt` on `String`, `Array` and `Hash` is no longer strict by default for consistency an unexpected surprises e.g. when having an array of Custom Objects and calling the method on the array.
18
35
  - Internal clean-up and simplifications on helper classes and methods.
19
36
 
20
37
  ## [2.1.0] - 2022-01-27
@@ -37,7 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
37
54
 
38
55
  ## [1.1.1] - 2022-01-25
39
56
  ### Fixed
40
- - Renamed `NTEncodeMixing` to `NTEncodeMixin` .
57
+ - Renamed `ToNTMixing` to `ToNTMixin` .
41
58
 
42
59
  ## [1.1.0] - 2022-01-25
43
60
  ### Added
@@ -58,13 +75,13 @@ The library is now useful for users!
58
75
  - Publish Gem to GitHub Packages
59
76
 
60
77
  ## [0.4.0] - 2022-01-24
61
- - Iteration on CD GitHub Actins workflow.
78
+ - Iteration on CD GitHub Actions workflow.
62
79
 
63
80
  ## [0.3.0] - 2022-01-24
64
- - Iteration on CD GitHub Actins workflow.
81
+ - Iteration on CD GitHub Actions workflow.
65
82
 
66
83
  ## [0.2.0] - 2022-01-24
67
- - Iteration on CD GitHub Actins workflow.
84
+ - Iteration on CD GitHub Actions workflow.
68
85
 
69
86
  ## [0.1.0] - 2022-01-24
70
87
  ### Added
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # NestedText Ruby Library [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=NestedText,%20the%20human%20friendly%20data%20format,%20has%20a%20now%20a%20ruby%20library%20for%20easy%20encoding%20and%20decoding&url=https://github.com/erikw/nestedtext-ruby&via=erik_westrup&hashtags=nestedtext,ruby,gem)
2
2
  [![Gem Version](https://badge.fury.io/rb/nestedtext.svg)](https://badge.fury.io/rb/nestedtext)
3
3
  [![Gem Downloads](https://ruby-gem-downloads-badge.herokuapp.com/nestedtext?color=brightgreen&type=total&label=gem%20downloads)](https://rubygems.org/gems/nestedtext)
4
- [![Documentation](https://img.shields.io/badge/docs-API-informational?logo=readthedocs&logoColor=violet)](https://www.rubydoc.info/gems/nestedtext/)
4
+ [![Documentation](https://img.shields.io/badge/docs-API-informational?logo=readthedocs&logoColor=violet)](https://www.rubydoc.info/gems/nestedtext/NestedText)
5
5
  [![Data Format Version Supported](https://img.shields.io/badge/%F0%9F%84%BD%F0%9F%85%83%20Version%20Supported-3.2.1-blueviolet)](https://nestedtext.org/en/v3.2/)
6
6
  [![Official Tests](https://img.shields.io/badge/Official%20Tests-Passing-success?logo=cachet)](https://github.com/KenKundert/nestedtext_tests/tree/585e95a73d94ac1f48e71a154e2db0ab67cf30fa)
7
7
  [![GitHub Actions: Continuous Integration](https://github.com/erikw/nestedtext-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/erikw/nestedtext-ruby/actions/workflows/ci.yml)
@@ -16,7 +16,8 @@
16
16
 
17
17
  A ruby library for the human friendly data format [NestedText](https://nestedtext.org/).
18
18
 
19
- <a href="#" ><img src="https://raw.githubusercontent.com/erikw/nestedtext-ruby/main/img/logo.webp" align="right" width="420px" alt="Project logo" /></a>
19
+ <!-- Use URL to hosted image, so that it shows up at rubydocs.info as well. Using relative image and yardoc option "--asset img:img" did not work. -->
20
+ <a href="#" ><img src="https://raw.githubusercontent.com/erikw/nestedtext-ruby/main/img/logo.webp" align="right" width="420px" alt="nestedtext-ruby logo" /></a>
20
21
 
21
22
  Provided is support for decoding a NestedText file or string to Ruby data structures, as well as encoding Ruby objects to a NestedText file or string. Furthermore there is support for serialization and deserialization of custom classes. The supported language version of the data format can be see in the badge above. This implementation pass all the [official tests](https://github.com/KenKundert/nestedtext_tests).
22
23
 
@@ -56,7 +57,7 @@ vice president:
56
57
  See the [language introduction](https://nestedtext.org/en/latest/basic_syntax.html) for more details.
57
58
 
58
59
  # Usage
59
- The full API documentation can be found at [**rubydocs.info**](https://www.rubydoc.info/gems/nestedtext/). A minimal & fully working example of a project using this library can be found at [erikw/nestedtext-ruby-test](https://github.com/erikw/nestedtext-ruby-test).
60
+ The **full API documentation** can be found at [rubydocs.info](https://www.rubydoc.info/gems/nestedtext/NestedText). A minimal & fully working example of a project using this library can be found at [erikw/nestedtext-ruby-test](https://github.com/erikw/nestedtext-ruby-test).
60
61
 
61
62
  ## Decoding (reading NT)
62
63
  This is how you can decode NestedText from a string or directly from a file (`*.nt`) to Ruby object instances:
@@ -111,7 +112,7 @@ NestedText::dump_file(data, "path/to/data.nt")
111
112
  ### `#to_nt` Convenience
112
113
  To make it more convenient, the Ruby Core is extended with a `#to_nt` method on the supported types that will dump a String of the data structure. Here's an IRB session showing how it works:
113
114
 
114
- ```irb
115
+ ```ruby
115
116
  irb> require 'nestedtext'
116
117
  irb> puts "a\nstring".to_nt
117
118
  > a
@@ -120,7 +121,10 @@ irb> puts ["i1", "i2", "i3"].to_nt
120
121
  - i1
121
122
  - i2
122
123
  - i3
123
- irb> puts({"k1" => "v1", "multiline\nkey" => "v2", "k3" => ["a", "list"]}.to_nt)
124
+ irb> hash = {"k1" => "v1",
125
+ "multiline\nkey" => "v2",
126
+ "k3" => ["a", "list"]}
127
+ irb> puts hash.to_nt
124
128
  k1: v1
125
129
  : multiline
126
130
  : key
@@ -168,7 +172,7 @@ Other Class | String | `#to_s` will be called if there is no `#encode_nt_with`
168
172
  ## Custom Classes Serialization
169
173
  This library has support for serialization/deserialization of custom classes as well. This is done by letting the objects tell NestedText what data should be used to represent the object instance with the `#encode_nt_with` method (inspired by `YAML`'s `#encode_with` method). All objects being recursively referenced from a root object being serialized must either implement this method or be one of the core supported NestedText data types from the table above.
170
174
 
171
- A class implementing `#encode_nt_with` is refered to as `Custom Class` in this document.
175
+ A class implementing `#encode_nt_with` is referred to as `Custom Class` in this document.
172
176
 
173
177
  ```ruby
174
178
  class Apple
@@ -217,10 +221,10 @@ data:
217
221
  - 12
218
222
  ```
219
223
 
220
- If you want to add some more super powers to your custom class, you can add the `#to_nt` shortcut by including the `NTEncodeMixin`:
224
+ If you want to add some more super powers to your custom class, you can add the `#to_nt` shortcut by including the `ToNTMixin`:
221
225
  ```ruby
222
226
  class Apple
223
- include NestedText::NTEncodeMixin
227
+ include NestedText::ToNTMixin
224
228
  ...
225
229
  end
226
230
 
@@ -274,12 +278,15 @@ See [encode_custom_classes_test.rb](test/nestedtext/encode_custom_classes_test.r
274
278
  1. For local testing, install the gem on local machine with: `$ bundle exec rake install`.
275
279
  * or manually with `$ gem build *.gemscpec && gem install *.gem`
276
280
 
277
- Make sure that only intended constants and methods are exposed publicly from the module `NestedText`. Check with
278
- ```
279
- irb> require 'nestedtext'
280
- irb> NestedText.constants
281
- irb> NestedText.methods(false)
282
- ```
281
+
282
+ Extra:
283
+ * Make sure that only intended constants and methods are exposed publicly from the module `NestedText`. Check with
284
+ ```
285
+ irb> require 'nestedtext'
286
+ irb> NestedText.constants
287
+ irb> NestedText.methods(false)
288
+ ```
289
+ * To see undocumented methods with [YARD](https://www.rubydoc.info/gems/yard/file/docs/GettingStarted.md): `$ yard stats --list-undoc`
283
290
 
284
291
  # Releasing
285
292
  Instructions for releasing on rubygems.org below. Optionally make a GitHub [release](https://github.com/erikw/nestedtext-ruby/releases) after this for the pushed git tag.
@@ -1,7 +1,10 @@
1
- require "stringio"
1
+ # frozen_string_literal: true
2
+
3
+ require 'stringio'
4
+
2
5
  module NestedText
3
- TOP_LEVEL_TYPES = [Object, Hash, Array, String]
4
- CUSTOM_CLASS_KEY = "__nestedtext_class__"
6
+ TOP_LEVEL_TYPES = [Object, Hash, Array, String].freeze
7
+ CUSTOM_CLASS_KEY = '__nestedtext_class__'
5
8
 
6
9
  private_constant :TOP_LEVEL_TYPES, :CUSTOM_CLASS_KEY
7
10
  end
@@ -1,20 +1,23 @@
1
- require "nestedtext/encode_helpers"
1
+ # frozen_string_literal: true
2
2
 
3
- # Extension of Ruby core types with the NestedText::NTEncodeMixin.
4
- #
5
- # TODO: add encoding of more Ruby native classes like Integer, Float etc plus commons like Set,....? Not covered in NestedText language.
6
- # Or leave this to a schema validator 3rd party plugin maybe? And replace my custom class decoding (and also encoding?)?
7
- # Or both: add encoding/decoding of more native classes, and allow decoding + applying a schema with 3rd party.
8
- # Or encourage using Marshal from core?
3
+ require 'nestedtext/encode_helpers'
9
4
 
10
- class String include NestedText::NTEncodeMixin; end
11
- class Array include NestedText::NTEncodeMixin; end
12
- class Hash include NestedText::NTEncodeMixin; end
5
+ # Extended with the `#to_nt` method.
6
+ class String include NestedText::ToNTMixin; end
13
7
 
8
+ # Extended with the `#to_nt` method.
9
+ class Array include NestedText::ToNTMixin; end
10
+
11
+ # Extended with the `#to_nt` method.
12
+ class Hash include NestedText::ToNTMixin; end
13
+
14
+ # Extended with NestedText support.
14
15
  class NilClass
15
- include NestedText::NTEncodeMixin
16
+ include NestedText::ToNTMixin
16
17
 
18
+ # Adds support for encoding and decoding nil.
17
19
  def self.nt_create(_data) = nil
18
20
 
19
- def encode_nt_with() = ""
21
+ # Adds support for encoding and decoding nil.
22
+ def encode_nt_with() = ''
20
23
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NestedText
2
4
  # Hiding extensions for Kernel here away from users.
3
5
  # Reference: https://ruby-doc.org/core-3.1.0/doc/syntax/refinements_rdoc.html
4
6
  module CoreExtInternal
5
7
  refine String do
6
8
  def normalize_line_endings
7
- # windows/mac -> unix
9
+ # Windows/Mac -> Unix
8
10
  gsub(/\r\n?/, "\n")
9
11
  end
10
12
  end
@@ -1,44 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nestedtext/parser"
4
- require "nestedtext/errors_internal"
3
+ require 'nestedtext/parser'
4
+ require 'nestedtext/errors_internal'
5
5
 
6
- require "logger"
7
- require "stringio"
6
+ require 'logger'
7
+ require 'stringio'
8
8
 
9
9
  module NestedText
10
10
  # Decode a NestedText string to Ruby objects.
11
11
  #
12
- # [ntstring] The string containing NestedText to be decoded.
13
- # [top_class] Force the top level returned object to be of this type. Supported values are +Object+, +Array+, +Hash+ and +String+. Default is +Object+.
14
- # [strict] If strict mode should be used. +true+ or +false+. Default is +false+
12
+ # @param ntstring [String] The string containing NestedText to be decoded.
13
+ # @param top_class [String] Force the top level returned object to be of this type.
14
+ # Supported values are `Object`, `Array`, `Hash` and `String`.
15
+ # @param strict [Boolean] If strict mode should be used.
15
16
  #
16
- # Returns the parsed object.
17
+ # @return [Object, nil] The parsed object.
17
18
  #
18
- # Raises NestedText::Error if anything went wrong.
19
+ # @raise [NestedText::Error] if anything went wrong.
19
20
  def self.load(ntstring, top_class: Object, strict: false)
20
21
  raise Errors::WrongInputTypeError.new([String], ntstring) unless ntstring.nil? || ntstring.is_a?(String)
21
22
 
22
- Parser.new(StringIO.new(ntstring), top_class, strict: strict).parse
23
+ Parser.new(StringIO.new(ntstring), top_class, strict:).parse
23
24
  end
24
25
 
25
26
  # Decode a NestedText stored in a given file.
26
-
27
- # [filename] The file path to read NestedText to decode from.
28
- # [top_class] Force the top level returned object to be of this type. Supported values are +Object+, +Array+, +Hash+ and +String+. Default is +Object+.
29
- # [strict] If strict mode should be used. +true+ or +false+. Default is +false+
30
27
  #
31
- # Returns the parsed object.
28
+ # @param filename [String] The file path to read NestedText to decode from.
29
+ # @param top_class [String] Force the top level returned object to be of this type.
30
+ # Supported values are `Object`, `Array`, `Hash` and `String`.
31
+ # @param strict [Boolean] If strict mode should be used.
32
32
  #
33
- # Raises NestedText::Error if anything went wrong.
33
+ # @return [Object, nil] The parsed object.
34
34
  #
35
- # Raises +IOError+ on issue opening +filename+ for reading in text mode.
35
+ # @raise [NestedText::Error] if anything went wrong.
36
+ # @raise [IOError] on issue opening `filename` for reading in text mode.
36
37
  def self.load_file(filename, top_class: Object, strict: false)
37
38
  raise Errors::WrongInputTypeError.new([String], filename) unless !filename.nil? && filename.is_a?(String)
38
39
 
39
40
  # Open explicitly in text mode to detect \r as line ending.
40
- File.open(filename, mode = "rt") do |file|
41
- Parser.new(file, top_class, strict: strict).parse
41
+ File.open(filename, 'rt') do |file|
42
+ Parser.new(file, top_class, strict:).parse
42
43
  end
43
44
  end
44
45
  end
@@ -1,10 +1,12 @@
1
- require "nestedtext/core_ext_internal"
1
+ # frozen_string_literal: true
2
+
3
+ require 'nestedtext/core_ext_internal'
2
4
 
3
5
  module NestedText
4
6
  using NestedText.const_get(:CoreExtInternal)
5
7
 
6
8
  # Dumping with recursive DFS traversal of the object references.
7
- class Dumper
9
+ class Dumper # rubocop:disable Metrics/ClassLength
8
10
  def initialize(indentation, strict)
9
11
  @indentation = indentation
10
12
  @strict = strict
@@ -18,31 +20,31 @@ module NestedText
18
20
  dump_any obj
19
21
  end
20
22
 
21
- private
22
-
23
23
  def self.add_prefix(prefix, target)
24
24
  if target.empty? || target[0] == "\n"
25
- target.prepend(prefix)
25
+ "#{prefix}#{target}"
26
26
  else
27
- target.prepend(prefix, " ")
27
+ "#{prefix} #{target}"
28
28
  end
29
29
  end
30
30
 
31
31
  def self.multiline_key?(key)
32
- syntax1 = "{[#"
33
- syntax2 = ":->"
32
+ syntax1 = '{[#'
33
+ syntax2 = ':->'
34
34
 
35
35
  key.empty? ||
36
36
  key != key.strip ||
37
37
  key.include?("\n") ||
38
- key.include?(": ") ||
38
+ key.include?(': ') ||
39
39
  syntax1.include?(key.lstrip[0]) ||
40
- syntax2.include?(key.lstrip[0]) && key.lstrip[1] == " "
40
+ (syntax2.include?(key.lstrip[0]) && key.lstrip[1] == ' ')
41
41
  end
42
42
 
43
+ private
44
+
43
45
  def convert_key(key)
44
46
  if key.nil?
45
- ""
47
+ ''
46
48
  elsif key.is_a? String
47
49
  key.normalize_line_endings
48
50
  elsif !@strict
@@ -52,10 +54,11 @@ module NestedText
52
54
  end
53
55
  end
54
56
 
55
- def indent(target)
56
- indentstr = " " * @indentation
57
- indented = "\n" + target.lines.map { |line| indentstr + line }.join
58
- target.replace indented
57
+ def indent(target, depth)
58
+ return target unless depth.positive?
59
+
60
+ indentstr = ' ' * @indentation
61
+ "\n#{target.lines.map { |line| indentstr + line }.join}"
59
62
  end
60
63
 
61
64
  def trace_cycles(obj)
@@ -81,77 +84,79 @@ module NestedText
81
84
  def dump_any(obj, depth: 0, **kwargs)
82
85
  trace_cycles(obj) do
83
86
  case obj
84
- when Hash then dump_hash(obj, depth: depth, **kwargs)
85
- when Array then dump_array(obj, depth: depth, **kwargs)
86
- when String then dump_string(obj, depth: depth, **kwargs)
87
+ when Hash then dump_hash(obj, depth:, **kwargs)
88
+ when Array then dump_array(obj, depth:, **kwargs)
89
+ when String then dump_string(obj, depth:, **kwargs)
87
90
  when nil
88
- @strict ? "" : dump_custom_class(nil, depth: depth, **kwargs)
91
+ @strict ? '' : dump_custom_class(nil, depth:, **kwargs)
89
92
  else
90
- dump_custom_class(obj, depth: depth, **kwargs)
93
+ dump_custom_class(obj, depth:, **kwargs)
91
94
  end
92
95
  end
93
96
  end
94
97
 
95
- def dump_hash(obj, depth: 0, **kwargs)
96
- rep = if obj.empty?
97
- "{}"
98
- else
99
- obj.map do |key, value|
100
- trace_keys(key) do
101
- key = convert_key(key)
102
-
103
- if Dumper.multiline_key?(key)
104
- key_lines = key.empty? ? [""] : key.lines
105
- key_lines << "" if key_lines[-1][-1] =~ /\n|\r/
106
- rep_key = key_lines.map { |line| Dumper.add_prefix(":", line) }.join
107
- force_multiline = value.is_a? String
108
- rep_value = dump_any(value, depth: depth + 1, force_multiline: force_multiline, **kwargs)
109
- else
110
- rep_key = "#{key}:"
111
- rep_value = dump_any(value, depth: depth + 1, **kwargs)
112
- rep_key += " " unless rep_value.empty? || rep_value.include?("\n")
113
- end
114
- "#{rep_key}#{rep_value}"
115
- end
116
- end.join("\n")
117
- end
118
- indent(rep) if depth > 0
119
- rep
98
+ def dump_hash_key_multiline(key, value, depth, **kwargs)
99
+ key_lines = key.empty? ? [''] : key.lines
100
+ key_lines << '' if key_lines[-1][-1] =~ /\n|\r/
101
+ rep_key = key_lines.map { |line| Dumper.add_prefix(':', line) }.join
102
+ rep_value = dump_any(value, depth: depth + 1, force_multiline: value.is_a?(String), **kwargs)
103
+ [rep_key, rep_value].join
120
104
  end
121
105
 
122
- def dump_array(obj, depth: 0, **kwargs)
123
- rep = if obj.empty?
124
- # TODO: replace this special case with simply general inline rendering detection.
125
- "[]"
106
+ def dump_hash_key(key, value, depth, **kwargs)
107
+ rep_key = "#{key}:"
108
+ rep_value = dump_any(value, depth: depth + 1, **kwargs)
109
+ rep_key += ' ' unless rep_value.empty? || rep_value.include?("\n")
110
+ [rep_key, rep_value].join
111
+ end
112
+
113
+ def dump_hash_items(hash, depth, **kwargs)
114
+ hash.map do |key, value|
115
+ trace_keys(key) do
116
+ key = convert_key(key)
117
+ if Dumper.multiline_key?(key)
118
+ dump_hash_key_multiline(key, value, depth, **kwargs)
119
+ else
120
+ dump_hash_key(key, value, depth, **kwargs)
121
+ end
122
+ end
123
+ end.join("\n")
124
+ end
125
+
126
+ def dump_hash(hash, depth: 0, **kwargs)
127
+ rep = hash.empty? ? '{}' : dump_hash_items(hash, depth, **kwargs)
128
+ indent(rep, depth)
129
+ end
130
+
131
+ def dump_array(array, depth: 0, **kwargs)
132
+ rep = if array.empty?
133
+ '[]'
126
134
  else
127
- obj.each_with_index.map do |e, i|
135
+ array.each_with_index.map do |e, i|
128
136
  trace_keys(i) do
129
- e_rep = dump_any(e, depth: depth + 1, **kwargs)
130
- Dumper.add_prefix("-", e_rep)
137
+ Dumper.add_prefix('-', dump_any(e, depth: depth + 1, **kwargs))
131
138
  end
132
139
  end.join("\n")
133
140
  end
134
141
 
135
- indent(rep) if depth > 0
136
- rep
142
+ indent(rep, depth)
137
143
  end
138
144
 
139
- def dump_string(obj, depth: 0, force_multiline: false)
140
- obj = obj.normalize_line_endings
141
- lines = obj.lines
142
- lines << "\n" if !lines.empty? && lines[-1][-1] == "\n"
143
- if lines.length > 1 || depth == 0 || force_multiline
144
- lines.each do |line|
145
- Dumper.add_prefix(">", line)
146
- end
147
- end
145
+ def prefix_lines(lines, depth, multiline)
146
+ lines = lines.map { |line| Dumper.add_prefix('>', line) } if multiline || depth.zero?
147
+ lines << '>' if lines.empty? && (depth.zero? || multiline)
148
+ lines
149
+ end
150
+
151
+ def dump_string(string, depth: 0, force_multiline: false)
152
+ lines = string.normalize_line_endings.lines
153
+ lines << '' if !lines.empty? && lines.last[-1] == "\n"
154
+ multiline = lines.length > 1 || force_multiline
148
155
 
149
- # Case of empty input string. No space after '>'
150
- lines << ">" if lines.empty? && (depth == 0 || force_multiline)
156
+ lines = prefix_lines(lines, depth, multiline)
151
157
 
152
158
  rep = lines.join.chomp
153
- indent(rep) if !rep.empty? && depth > 0 && (rep.include?("\n") || force_multiline)
154
- rep
159
+ multiline ? indent(rep, depth) : rep
155
160
  end
156
161
 
157
162
  def dump_custom_class(obj, **kwargs)
@@ -160,8 +165,8 @@ module NestedText
160
165
  if obj.is_a? Symbol
161
166
  dump_string(obj.id2name, **kwargs)
162
167
  elsif obj.respond_to? :encode_nt_with
163
- class_name = obj.nil? ? "nil" : obj.class.name
164
- enc = { CUSTOM_CLASS_KEY => class_name, "data" => obj.encode_nt_with }
168
+ class_name = obj.nil? ? 'nil' : obj.class.name
169
+ enc = { CUSTOM_CLASS_KEY => class_name, 'data' => obj.encode_nt_with }
165
170
  dump_any(enc, **kwargs)
166
171
  else
167
172
  dump_string(obj.to_s, **kwargs)
@@ -1,23 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nestedtext/dumper"
4
- require "nestedtext/errors_internal"
3
+ require 'nestedtext/dumper'
4
+ require 'nestedtext/errors_internal'
5
5
 
6
6
  module NestedText
7
7
  # Encode a Ruby object to a NestedText string.
8
8
  #
9
- # [obj] The object to encode to NestedText.
10
- # [io] Additionally write the output to this IO object. The caller is responsible for that the IO is closed after the call to this method.
11
- # [indentation] The indentation of nested levels to use.
12
- # [strict] If strict mode should be used. +true+ or +false+. Default is +false+
9
+ # @param obj [Object] The object to encode to NestedText.
10
+ # @param io [IO] Additionally write the output to this IO object.
11
+ # The caller is responsible for that the IO is closed after the call to this method.
12
+ # @param indentation [Integer] The indentation of nested levels to use.
13
+ # @param strict [Boolean] If strict mode should be used.
13
14
  #
14
- # Returns a String containing NestedText data.
15
- #
16
- # Raises NestedText::Error if anything went wrong.
17
- #
18
- # Raises whatever the passed +io+ can raise.
15
+ # @return [String, nil] A String containing NestedText data, or nil when obj is represented as empty.
16
+ # @raise [NestedText::Error] if anything went wrong.
17
+ # @raise Whatever the `io` can raise, if supplied.
19
18
  def self.dump(obj, io: nil, indentation: 4, strict: false)
20
- raise Errors::DumpBadIOError, io unless io.nil? || io.respond_to?(:write) && io.respond_to?(:fsync)
19
+ raise Errors::DumpBadIOError, io unless io.nil? || (io.respond_to?(:write) && io.respond_to?(:fsync))
21
20
 
22
21
  dumper = Dumper.new(indentation, strict)
23
22
  result = dumper.dump obj
@@ -29,16 +28,21 @@ module NestedText
29
28
  end
30
29
 
31
30
  # Encode a Ruby object to a NestedText file.
31
+
32
+ # Apart from `filename`, this method behaves exactly like dump.
33
+ #
34
+ # @param (see dump)
35
+ # @param filename [String] The file path to write the NestedText result to. The conventional file extension is `.nt`.
32
36
  #
33
- # [filename] The file path to write the NestedText result to. The conventional file extension is +.nt+.
34
37
  #
35
- # Raises +IOError+ on issues opening the +filename+ for writing in text mode.
38
+ # @return (see dump)
39
+ # @raise (see dump)
40
+ # @raise [IOError] on issues opening the `filename` for writing in text mode.
36
41
  #
37
- # Apart from +filename+, this method behaves exactly like dump (taking same arguments, returning and raising the same values).
38
42
  def self.dump_file(obj, filename, **kwargs)
39
43
  raise Errors::DumpFileBadPathError, filename unless filename.is_a? String
40
44
 
41
- File.open(filename, mode = "wt") do |file|
45
+ File.open(filename, 'wt') do |file|
42
46
  dump(obj, io: file, **kwargs)
43
47
  end
44
48
  end
@@ -1,12 +1,13 @@
1
- require "nestedtext/dumper"
1
+ # frozen_string_literal: true
2
+
3
+ require 'nestedtext/dumper'
2
4
 
3
5
  module NestedText
4
6
  # A mixin for Custom Classes to get the to_nt shortcut.
5
- # TODO rename to: ToNTMixin
6
- module NTEncodeMixin
7
+ module ToNTMixin
7
8
  # Encode this object to a NestedText string.
8
9
  #
9
- # This method takes the same arguments as NestedText::dump.
10
+ # This method takes the same named arguments as {NestedText.dump}.
10
11
  def to_nt(**kwargs)
11
12
  NestedText.dump(self, strict: false, **kwargs)
12
13
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NestedText
2
4
  # Top level error to rescue on.
3
5
  #
4
- # +Error+ is a subclass of +StandardError+ and behaves as expected e.g. +#message+.
6
+ # Error is a subclass of StandardError and behaves as expected e.g. #message.
5
7
  class Error < StandardError
6
8
  private_class_method :new
7
9
  end