litbuild 1.0.9 → 1.0.11

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: 021106eb1915ada36b41382da16fdde8d9c2762d3e250dc0cbdb5067c7432bcf
4
- data.tar.gz: a42ebf4088c9c1f7b9ae2d3d4f238ec2e9610c17c6fd07da1e0af6a5938c71dd
3
+ metadata.gz: 450a93fb7a60735ed6618b58aff828dd2c6a8846b7664e7916df70ca319f1f4c
4
+ data.tar.gz: 0f7523cd36707b6748f868b6229d69413874503282511929891e1d4ea344d8df
5
5
  SHA512:
6
- metadata.gz: 93da197d79732d1944ec9821f2d567c76962408923e68a2642789a4408176ab341dcf6e2fb61b2274413b98272e2d4f3cf979c38b20d11186d7f80a6a8e90238
7
- data.tar.gz: 2a38bdce9e787c5685ccaf92fca51cffc16da80c900694701fc6a169aef9c9e8797eedbf8fe53d317e2129000126bff9076d69ba4da0f0bba086630e367b6928
6
+ metadata.gz: '08ee5269104135777fb2dd06c225b03854b8b38c61723c0652b98aebc1fef19cad4ded3267249312e8821de764fab8360189216bf50e6b039f442a48cc9ed169'
7
+ data.tar.gz: 4626ce942e4afd88bca32d3613488bd2ac509107c90f467ae0deb3f14c0086ff6fd401647a9173ab5906284a042422802c0dc0fb067e80645217cf70e98e4686
@@ -3,6 +3,7 @@
3
3
  require 'stringio'
4
4
  require 'litbuild/multi_part_visitor'
5
5
  require 'litbuild/service_dir'
6
+ require 'litbuild/string_indentation'
6
7
 
7
8
  module Litbuild
8
9
  ##
@@ -15,6 +16,8 @@ module Litbuild
15
16
  # blueprint (phase). AsciiDocVisitor can also write a top-level
16
17
  # AsciiDoc document that includes all top-level fragments.
17
18
  class AsciiDocVisitor < MultiPartVisitor
19
+ include StringIndentation
20
+
18
21
  def initialize(parameters:)
19
22
  @parameters = parameters
20
23
  super(directory: @parameters['DOCUMENT_DIR'])
@@ -274,7 +277,7 @@ module Litbuild
274
277
  end
275
278
  svc.multiline_files.keys.sort.each do |filename|
276
279
  doc.puts("|#{filename.capitalize} script\nl|")
277
- doc.puts(svc.multiline_files[filename])
280
+ doc.puts(strip_indentation_from_value(svc.multiline_files[filename]))
278
281
  doc.puts
279
282
  end
280
283
  end
@@ -358,7 +361,7 @@ module Litbuild
358
361
  end
359
362
  doc.puts('[source,indent=0]')
360
363
  doc.puts('----')
361
- doc.puts(file['content'])
364
+ doc.puts(strip_indentation_from_value(file['content']))
362
365
  doc.puts('----')
363
366
  end
364
367
 
@@ -371,7 +374,7 @@ module Litbuild
371
374
  doc.puts("=== #{filename}\n\n")
372
375
  doc.puts('[source,indent=0]')
373
376
  doc.puts('----')
374
- doc.puts(files[filename])
377
+ doc.puts(strip_indentation_from_string(files[filename].join))
375
378
  doc.puts('----')
376
379
  end
377
380
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'litbuild/service_dir'
4
4
  require 'litbuild/source_code_manager'
5
+ require 'litbuild/string_indentation'
5
6
  require 'litbuild/visitor'
6
7
 
7
8
  module Litbuild
@@ -13,6 +14,8 @@ module Litbuild
13
14
  # phase) has already been written to any directory, BashScriptVisitor
14
15
  # will ignore subsequent requests to write that blueprint (phase).
15
16
  class BashScriptVisitor < Visitor
17
+ include StringIndentation
18
+
16
19
  INSTALL_GID = 9999
17
20
 
18
21
  attr_reader :blueprint_dir
@@ -179,7 +182,7 @@ module Litbuild
179
182
  blueprint.files.keys.sort.map do |name|
180
183
  accum = StringIO.new
181
184
  accum.puts("cat > #{name} <<'LBEOF'")
182
- accum.puts(blueprint.files[name].string)
185
+ accum.puts(strip_indentation_from_string(blueprint.files[name].string))
183
186
  accum.puts('LBEOF')
184
187
  accum.string
185
188
  end
@@ -534,7 +537,7 @@ module Litbuild
534
537
  end
535
538
  multiline = sd.multiline_files
536
539
  deps = sd.dependencies
537
- multiline['dependencies'] = deps.join("\n") unless deps.empty?
540
+ multiline['dependencies'] = [deps.join("\n")] unless deps.empty?
538
541
  multiline.keys.sort.each do |filename|
539
542
  # I always terminate here documents in litbuild-generated
540
543
  # scripts with "LBEOF", partly because I'm thinking "Litbuild
@@ -542,7 +545,7 @@ module Litbuild
542
545
  # Shia LaBoeuf, and then I remember the Rob Cantor song of
543
546
  # that name and giggle.
544
547
  script.puts("cat > #{sd.name}/#{filename} <<'LBEOF'")
545
- script.puts(multiline[filename])
548
+ script.puts(strip_indentation_from_value(multiline[filename]))
546
549
  script.puts('LBEOF')
547
550
  end
548
551
  env = sd.env
@@ -7,6 +7,15 @@ require 'litbuild/logfile_namer'
7
7
  require 'litbuild/visitor'
8
8
 
9
9
  module Litbuild
10
+ # Blueprints are described in the `doc` directory.
11
+ #
12
+ # tl;dr: Blueprints are considered as "chunks" separated by blank
13
+ # lines. Each chunk can be either directives or narrative. Narrative
14
+ # is AsciiDoc and does not get parsed or transformed. Directives are
15
+ # basically a simplified version of YAML.
16
+ #
17
+ # After parsing, the narrative is found in the `grafs` variables and
18
+ # directives are found in `directive` hashes.
10
19
  class Blueprint
11
20
  class << self
12
21
  # This should simply be the name of the directory where blueprints
@@ -1,20 +1,18 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  require 'litbuild/errors'
4
+ require 'litbuild/string_indentation'
4
5
  require 'json'
5
6
 
6
7
  module Litbuild
7
8
  # This is a kludgy hand-built parser. Blueprint structure is not (at
8
9
  # least, at this point) complicated enough that I can see any point in
9
10
  # defining a grammar and using a parser generator. The structure of
10
- # blueprint directives is described informally in
11
- # `doc/blueprints.txt` (and blueprint-type-specific files under `doc`
12
- # as well).
13
- #
14
- # tl;dr: each paragraph can be either directives or narrative.
15
- # Narrative is AsciiDoc and does not get parsed or transformed.
16
- # Directives are basically a simplified version of YAML.
11
+ # blueprints is described informally in `doc/blueprints.txt` (and
12
+ # blueprint-type-specific files under `doc` as well).
17
13
  class BlueprintParser
14
+ include StringIndentation
15
+
18
16
  # _directives_ are for use in scripts. _grafs_ are for use in
19
17
  # documents.
20
18
  attr_reader :base_directives, :phase_directives, :base_grafs, :phase_grafs
@@ -30,9 +28,8 @@ module Litbuild
30
28
  # blueprint. If there are no phase directives, this is the entire
31
29
  # blueprint, obvs.
32
30
  @base_grafs = []
33
- base = parse_phase(phase_chunks.shift, {}, @base_grafs)
34
- base['full-name'] ||= base['name']
35
- @base_directives = base
31
+ @base_directives = parse_phase(phase_chunks.shift, {}, @base_grafs)
32
+ @base_directives['full-name'] ||= @base_directives['name']
36
33
 
37
34
  # The rest of the blueprint, if any, consists of directives and
38
35
  # narrative for specific phases. The directives for each phase
@@ -42,13 +39,15 @@ module Litbuild
42
39
  phase_name = phase_chunks.shift
43
40
  phase_contents = phase_chunks.shift
44
41
  grafs = []
45
- @phase_directives[phase_name] = parse_phase(phase_contents, base, grafs)
42
+ @phase_directives[phase_name] = parse_phase(phase_contents,
43
+ @base_directives,
44
+ grafs)
46
45
  @phase_grafs[phase_name] = grafs
47
46
  end
48
47
 
49
48
  # Any directives at the beginning of a blueprint are actually a
50
- # file header that should not be rendered as part of the narrative
51
- # for it.
49
+ # file header that should not be considered as part of the
50
+ # narrative for it.
52
51
  @base_grafs.shift while @base_grafs[0].is_a?(Hash)
53
52
  rescue StandardError => e
54
53
  msg = "Cannot parse blueprint starting: #{@text.lines[0..3].join}"
@@ -122,8 +121,8 @@ module Litbuild
122
121
  end
123
122
  directive_name = md[1]
124
123
  firstline_value = md[2]
125
- value_lines = related_lines(directive_line, lines_to_process)
126
- value = parse_directive_value(firstline_value, value_lines)
124
+ value_lines, indent = related_lines(directive_line, lines_to_process)
125
+ value = parse_directive_value(firstline_value, value_lines, indent)
127
126
  graf_directives[directive_name] << if value == "''"
128
127
  ''
129
128
  else
@@ -137,7 +136,9 @@ module Litbuild
137
136
  # Regardless of what kind of directive structure we're dealing with,
138
137
  # all of the lines that are indented more than the initial directive
139
138
  # line are part of that directive. This method finds all those
140
- # related lines and strips away the common initial indentation.
139
+ # related lines and strips away the common initial indentation; it
140
+ # returns both the related lines and the amount of indentation that
141
+ # was removed.
141
142
  def related_lines(directive_line, lines_to_process)
142
143
  directive_indent = indent_for(directive_line)
143
144
  related = []
@@ -145,16 +146,15 @@ module Litbuild
145
146
  (indent_for(lines_to_process[0]) > directive_indent)
146
147
  related << lines_to_process.shift
147
148
  end
148
- common_indent = related.map { |l| indent_for(l) }.min
149
- related.map { |l| l.slice(common_indent..-1) }
149
+ strip_indentation_from_array(related)
150
150
  end
151
151
 
152
152
  # What kind of directive are we dealing with? Could be a simple
153
153
  # value (with zero or more continuation lines), or a multiline
154
154
  # value, or an array, or a subdirective block.
155
- def parse_directive_value(firstline_value, other_lines)
155
+ def parse_directive_value(firstline_value, other_lines, indentation)
156
156
  if firstline_value == '|'
157
- multiline_value(other_lines)
157
+ multiline_value(other_lines, indentation)
158
158
  elsif other_lines.empty?
159
159
  firstline_value
160
160
  elsif other_lines[0].match?(/^ *- /)
@@ -175,8 +175,15 @@ module Litbuild
175
175
  stripped.join(" \\\n ")
176
176
  end
177
177
 
178
- def multiline_value(lines)
179
- "#{lines.join("\n")}\n"
178
+ # While parsing multiline values, we want to restore the indentation
179
+ # that was previously stripped away -- this is typically used for
180
+ # `file` directives, which often appear in multiple directive blocks
181
+ # and should be treated as a whole. The indentation for multi-line
182
+ # values must be removed *later*, during rendering of scripts and
183
+ # documents.
184
+ def multiline_value(lines, indentation)
185
+ lines_with_indentation = lines.map { |l| (' ' * indentation) + l }
186
+ "#{lines_with_indentation.join("\n")}\n"
180
187
  end
181
188
 
182
189
  def array_value(lines)
@@ -184,8 +191,8 @@ module Litbuild
184
191
  until lines.empty?
185
192
  array_member = lines.shift
186
193
  firstline_value = /^- *(.*)$/.match(array_member)[1]
187
- related = related_lines(array_member, lines)
188
- value << parse_directive_value(firstline_value, related)
194
+ related, indentation = related_lines(array_member, lines)
195
+ value << parse_directive_value(firstline_value, related, indentation)
189
196
  end
190
197
  value
191
198
  rescue StandardError
@@ -198,11 +205,5 @@ module Litbuild
198
205
  def subdirective_value(lines)
199
206
  parse_lines(lines)
200
207
  end
201
-
202
- # Utility method to find the amount of blank space at the beginning
203
- # of a line.
204
- def indent_for(line)
205
- /^([[:blank:]]*).*/.match(line)[1].size
206
- end
207
208
  end
208
209
  end
@@ -35,8 +35,8 @@ module Litbuild
35
35
 
36
36
  blueprints = self['blueprints'].clone || []
37
37
  if $DEBUG
38
- warn("Explicit blueprints for section #{name}:" \
39
- " #{blueprints.join(', ')}")
38
+ warn("Explicit blueprints for section #{name}: " \
39
+ "#{blueprints.join(', ')}")
40
40
  end
41
41
  blueprints << automatic_inclusions
42
42
  deduped = blueprints.flatten.uniq
@@ -56,8 +56,8 @@ module Litbuild
56
56
  end
57
57
  end
58
58
  if $DEBUG
59
- warn("Automatically-added blueprints for section #{name}:" \
60
- " #{auto_adds.sort.join(', ')}")
59
+ warn("Automatically-added blueprints for section #{name}: " \
60
+ "#{auto_adds.sort.join(', ')}")
61
61
  end
62
62
  auto_adds.sort
63
63
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: false
2
+
3
+ module Litbuild
4
+ module StringIndentation
5
+ # Utility method to find the amount of blank space at the beginning
6
+ # of a line.
7
+ def indent_for(line)
8
+ /^([[:blank:]]*).*/.match(line)[1].size
9
+ end
10
+
11
+ # Utility method to strip the common indentation from all strings in
12
+ # an array. Returns both the stripped strings and the amount of
13
+ # indentation removed.
14
+ def strip_indentation_from_array(strings)
15
+ common_indent = strings.map { |l| indent_for(l) }.min
16
+ [strings.map { |l| l.slice(common_indent..-1) }, common_indent]
17
+ end
18
+
19
+ # Utility method to strip the common indentation from all lines of a
20
+ # multi-line string. (Does not return the amount of indentation
21
+ # removed.)
22
+ def strip_indentation_from_string(string)
23
+ strip_indentation_from_array(string.lines)[0]
24
+ end
25
+
26
+ # Utility method to strip the common indentation from all lines of a
27
+ # directive value (which is expected to be an array containing a
28
+ # single string element)
29
+ def strip_indentation_from_value(value)
30
+ strip_indentation_from_string(value[0])
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Litbuild
4
- VERSION = '1.0.9'
4
+ VERSION = '1.0.11'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: litbuild
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Neumeier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-25 00:00:00.000000000 Z
11
+ date: 2022-12-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A build system based on Knuth's idea of literate programming.
14
14
  email:
@@ -39,6 +39,7 @@ files:
39
39
  - lib/litbuild/service_dir.rb
40
40
  - lib/litbuild/source_code_manager.rb
41
41
  - lib/litbuild/source_files_visitor.rb
42
+ - lib/litbuild/string_indentation.rb
42
43
  - lib/litbuild/url_visitor.rb
43
44
  - lib/litbuild/version.rb
44
45
  - lib/litbuild/visitor.rb
@@ -62,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
63
  - !ruby/object:Gem::Version
63
64
  version: '0'
64
65
  requirements: []
65
- rubygems_version: 3.3.3
66
+ rubygems_version: 3.2.3
66
67
  signing_key:
67
68
  specification_version: 4
68
69
  summary: A literate build system