string-text 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9cb6091be55dccdd85e5ed00b7348573a768833a782725e00a0aa6258506c31b
4
- data.tar.gz: 5faa4885c3a303f1eed4ee21ad30a80b779701df7be15be9fda079ea353d9c3b
3
+ metadata.gz: 5f6c8858a8db9e8092584a772dfaf14f37ea992f5281a88419f42873f6ee2557
4
+ data.tar.gz: 1e0e8b6db1a0b3184f1141dd38891fc2c628b28f53edfedd7013c84657bed6ce
5
5
  SHA512:
6
- metadata.gz: ee4799f3ac56b221c362e00c6627282aa03dcf294af5ce88422e3134c60fa96e5d3d25eb2bbbe09ad5720a7890e205beb7bfb34c91efb22122f4e64eeead656b
7
- data.tar.gz: 8ebb89255417583f8dc30ec33ca08db50d2ea88a748c186cf95d6bf3df511eb6a6ae84d1502c077277c7585a17f569333b855210b054ba503df7e3d67a7fcebe
6
+ metadata.gz: e2f147ba4df73785325b7f7f316cfc21419b2cd79cb4cf7daa3c58a2f909c5ada95d99c566b5d7759b50d518491b96d1389e2c5fde0e78b584932f6fab2c917b
7
+ data.tar.gz: dab721a833b6afb441ec26ea881fed1975d65fd33a27843c9dbf236b6d1d2114ecccce1d1b848d01f0e03325352ed0b8819cd3b5612c72f2a4ca8a2a0619e8e2
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module String::Text
4
- VERSION = "0.5.0"
4
+ VERSION = "0.6.1"
5
5
  end
data/lib/string-text.rb CHANGED
@@ -5,11 +5,16 @@ require_relative "string-text/version"
5
5
  module String::Text
6
6
  class Error < StandardError; end
7
7
 
8
+ def self.indentation(s) s =~ /^(\s*)/; $1.size end
9
+
8
10
  refine String do
9
11
  # Indent or outdent a block of text to the given column (default 1). It
10
12
  # uses the indent of the least indented non-empty line as the indent of the
11
- # whole block that is then aligned as a whole (including internal indents)
12
- # to the given column. Initial and final empty lines are ignored
13
+ # block that is then aligned as a whole to the given column; lines starting
14
+ # at column one are realigned to the indent of the previous line. Initial
15
+ # and final empty lines are ignored.
16
+ #
17
+ # FIXME: make the special rule for lines starting at column one an option
13
18
  #
14
19
  # #align is often handy when you call methods with a %(...) argument
15
20
  # and don't want weird indentation in your output
@@ -19,36 +24,61 @@ module String::Text
19
24
  # This line will start at column 3
20
25
  # ).align
21
26
  #
22
- # If :bol is false then the first line won't be indented or outdented. It
23
- # is used when including a block of text in another block:
27
+ # This line will start at column 1
28
+ # This line will start at column 3
29
+ #
30
+ # Because unindented lines are realigned to the previous line's indent,
31
+ # lists can be indented like this
24
32
  #
25
- # innert_text = %(
26
- # first line
27
- # second line
28
- # )
33
+ # words = %w(hello world)
29
34
  # puts %(
30
- # Here is the outer text
31
- # #{inner_text.align(2, bol: false)}
32
- # Rest of the outer text
35
+ # Array elements on separate lines and starting at column 3:
36
+ # #{words.join("\n")}
33
37
  # ).align
34
38
  #
39
+ # Array elements on separate lines and starting at column 3:
40
+ # hello
41
+ # world
42
+ #
43
+ # The trick is that the words expression makes the string expand to
44
+ #
45
+ # Array elements on separate lines and starting at column 3:
46
+ # hello
47
+ # world
48
+ #
49
+ # If :bol is false then the first line won't be indented or outdented
50
+ #
35
51
  def align(column = 1, bol: true)
36
52
  column > 0 or raise ArgumentError "Illegal column: #{column}"
37
53
  initial = " " * (column - 1)
38
- lines = self.split(/\n/)
54
+
55
+ # Remove initial and final empty lines
56
+ lines = self.split(/\n/).map &:rstrip
39
57
  lines.pop while !lines.empty? && !(lines.last =~ /^\s*\S/)
40
58
  lines.shift while !lines.empty? && !(lines.first =~ /^\s*\S/)
41
59
  return "" if lines.empty?
42
60
 
43
- indent = lines.map { _1 =~ /^(\s*)/; $1.size }.select { _1 > 0 }.min || 0
61
+ # Identation level of each line
62
+ indents = lines.map { String::Text.indentation(_1) }
63
+
64
+ # Find minimal indent. If the first line is not indented the minimal
65
+ # indent is 0, otherwise the smallest non-zero indent used
66
+ indent = String::Text.indentation(lines.first) == 0 ? 0 : indents.select { _1 > 0 }.min || 0
67
+
44
68
  first = true
45
- lines.map { |line|
46
- l = line[indent..-1]&.rstrip
69
+ lines.map.with_index { |line, i|
47
70
  if !bol && first
48
71
  first = false
49
- l || ""
72
+ line[indents[0]..-1]
50
73
  else
51
- l ? initial + l : ""
74
+ if line.empty?
75
+ ""
76
+ elsif indents[i] == 0 && i > 0 # Unindented lines
77
+ indents[i] = indents[i-1] # use previous line's indent
78
+ ' ' * (indents[i] - indent) + line
79
+ else # Regular line
80
+ initial + line[indent..-1]
81
+ end
52
82
  end
53
83
  }.join("\n")
54
84
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: string-text
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen