tocer 12.1.0 → 13.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,16 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "tocer/identity"
4
+ require "refinements/structs"
4
5
 
5
6
  module Tocer
6
7
  module CLI
7
8
  module Parsers
8
9
  # Handles parsing of Command Line Interface (CLI) core options.
9
10
  class Core
10
- def self.call(options: {}, client: CLIENT) = new(options: options, client: client).call
11
+ using Refinements::Structs
11
12
 
12
- def initialize options: {}, client: CLIENT
13
- @options = options
13
+ def self.call(...) = new(...).call
14
+
15
+ def initialize configuration = Configuration::Loader.call, client: Parser::CLIENT
16
+ @configuration = configuration
14
17
  @client = client
15
18
  end
16
19
 
@@ -18,12 +21,13 @@ module Tocer
18
21
  client.banner = "#{Identity::LABEL} - #{Identity::SUMMARY}"
19
22
  client.separator "\nUSAGE:\n"
20
23
  collate
21
- arguments.empty? ? arguments : client.parse!(arguments)
24
+ client.parse arguments
25
+ configuration
22
26
  end
23
27
 
24
28
  private
25
29
 
26
- attr_reader :options, :client
30
+ attr_reader :configuration, :client
27
31
 
28
32
  def collate = private_methods.sort.grep(/add_/).each { |method| __send__ method }
29
33
 
@@ -34,25 +38,31 @@ module Tocer
34
38
  %i[edit view],
35
39
  "Manage gem configuration: edit or view."
36
40
  ) do |action|
37
- options[:config] = action
41
+ configuration.merge! action_config: action
38
42
  end
39
43
  end
40
44
 
41
- def add_build
42
- client.on "-b", "--build [PATH]", %(Build table of contents. Default path: ".") do |value|
43
- options[:build] = value || "."
45
+ def add_insert
46
+ root_dir = configuration.root_dir
47
+
48
+ client.on(
49
+ "-i",
50
+ "--insert [PATH]",
51
+ %(Insert/update table of contents. Default: "#{root_dir}".)
52
+ ) do |path|
53
+ configuration.merge! action_insert: true, root_dir: path || root_dir
44
54
  end
45
55
  end
46
56
 
47
57
  def add_version
48
58
  client.on "-v", "--version", "Show gem version." do
49
- options[:version] = Identity::VERSION_LABEL
59
+ configuration.merge! action_version: true
50
60
  end
51
61
  end
52
62
 
53
63
  def add_help
54
64
  client.on "-h", "--help", "Show this message." do
55
- options[:help] = true
65
+ configuration.merge! action_help: true
56
66
  end
57
67
  end
58
68
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Tocer
6
+ module CLI
7
+ module Parsers
8
+ # Handles parsing of Command Line Interface (CLI) flags.
9
+ class Flag
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration = Configuration::Loader.call, client: Parser::CLIENT
15
+ @configuration = configuration
16
+ @client = client
17
+ end
18
+
19
+ def call arguments = []
20
+ client.separator "\nOPTIONS:\n"
21
+ private_methods.sort.grep(/add_/).each { |method| __send__ method }
22
+ client.parse arguments
23
+ configuration
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :configuration, :client
29
+
30
+ def add_label
31
+ client.on(
32
+ "--label [LABEL]",
33
+ %(Add label. Default: "#{configuration.label}".)
34
+ ) do |value|
35
+ configuration.merge! label: value if value
36
+ end
37
+ end
38
+
39
+ def add_include
40
+ client.on(
41
+ "--includes [a,b,c]",
42
+ Array,
43
+ %(Add include patterns. Default: #{configuration.includes}.)
44
+ ) do |items|
45
+ configuration.merge! includes: items if items
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -4,39 +4,35 @@ module Tocer
4
4
  module CLI
5
5
  # The main Command Line Interface (CLI) object.
6
6
  class Shell
7
- PROCESSORS = {config: Processors::Config.new, build: Processors::Build.new}.freeze
7
+ ACTIONS = {config: Actions::Config.new, insert: Actions::Insert.new}.freeze
8
8
 
9
- def initialize parser: Parsers::Assembler.new, processors: PROCESSORS
9
+ def initialize parser: Parser.new, actions: ACTIONS
10
10
  @parser = parser
11
- @processors = processors
11
+ @actions = actions
12
12
  end
13
13
 
14
14
  def call arguments = []
15
- parse arguments
16
-
17
- case options
18
- in config: action then process_config action
19
- in build: path then process_build path
20
- in version: then puts version
21
- else usage
22
- end
15
+ perform parser.call(arguments)
16
+ rescue OptionParser::ParseError => error
17
+ puts error.message
23
18
  end
24
19
 
25
20
  private
26
21
 
27
- attr_reader :parser, :processors
22
+ attr_reader :parser, :actions
28
23
 
29
- def parse arguments = []
30
- parser.call arguments
31
- rescue StandardError => error
32
- puts error.message
24
+ def perform configuration
25
+ case configuration
26
+ in action_config: Symbol => action then process_config action
27
+ in action_insert: true then process_insert configuration
28
+ in action_version: true then puts Identity::VERSION_LABEL
29
+ else usage
30
+ end
33
31
  end
34
32
 
35
- def process_config(action) = processors.fetch(:config).call(action)
36
-
37
- def process_build(path) = processors.fetch(:build).call(path, options)
33
+ def process_config(action) = actions.fetch(:config).call(action)
38
34
 
39
- def options = parser.to_h
35
+ def process_insert(configuration) = actions.fetch(:insert).call(configuration)
40
36
 
41
37
  def usage = puts(parser.to_s)
42
38
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tocer
4
+ module Configuration
5
+ # Defines the content of the configuration for use throughout the gem.
6
+ Content = Struct.new(
7
+ :action_config,
8
+ :action_help,
9
+ :action_insert,
10
+ :action_version,
11
+ :includes,
12
+ :label,
13
+ :root_dir,
14
+ keyword_init: true
15
+ ) do
16
+ def initialize *arguments
17
+ super
18
+ freeze
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,4 @@
1
1
  :label: "## Table of Contents"
2
2
  :includes:
3
3
  - "README.md"
4
+ :root_dir: "."
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "refinements/structs"
5
+ require "runcom"
6
+ require "yaml"
7
+
8
+ module Tocer
9
+ module Configuration
10
+ # Represents the fully assembled Command Line Interface (CLI) configuration.
11
+ class Loader
12
+ using Refinements::Structs
13
+
14
+ DEFAULTS = YAML.load_file(Pathname(__dir__).join("defaults.yml")).freeze
15
+ CLIENT = Runcom::Config.new "#{Identity::NAME}/configuration.yml", defaults: DEFAULTS
16
+
17
+ def self.call = new.call
18
+
19
+ def self.with_defaults = new(client: DEFAULTS)
20
+
21
+ def initialize content: Content.new, client: CLIENT
22
+ @content = content
23
+ @client = client
24
+ end
25
+
26
+ def call = content.merge(**client.to_h)
27
+
28
+ private
29
+
30
+ attr_reader :content, :client
31
+ end
32
+ end
33
+ end
@@ -17,6 +17,8 @@ module Tocer
17
17
  @message = message
18
18
  end
19
19
 
20
+ def comments = "#{start_tag}\n#{finish_tag}\n"
21
+
20
22
  def start_index(lines) = self.class.index(lines, start_id)
21
23
 
22
24
  def start_tag = comment(start_id, message)
@@ -25,6 +27,8 @@ module Tocer
25
27
 
26
28
  def finish_tag = comment(finish_id, message)
27
29
 
30
+ def empty?(lines) = (finish_index(lines) - start_index(lines)) == 1
31
+
28
32
  def prependable?(lines) = start_index(lines).zero? && finish_index(lines).zero?
29
33
 
30
34
  private
@@ -5,7 +5,7 @@ module Tocer
5
5
  module Identity
6
6
  NAME = "tocer"
7
7
  LABEL = "Tocer"
8
- VERSION = "12.1.0"
8
+ VERSION = "13.0.2"
9
9
  VERSION_LABEL = "#{LABEL} #{VERSION}".freeze
10
10
  SUMMARY = "A command line interface for generating table of contents for Markdown files."
11
11
  end
@@ -13,7 +13,7 @@ module Tocer
13
13
 
14
14
  def self.setup = new.install
15
15
 
16
- def initialize configuration: CLI::Configuration::Loader.new.call, runner: Runner.new
16
+ def initialize configuration = Configuration::Loader.call, runner: Runner.new
17
17
  @configuration = configuration
18
18
  @runner = runner
19
19
  end
@@ -21,7 +21,7 @@ module Tocer
21
21
  def install
22
22
  desc "Add/Update Table of Contents (README)"
23
23
  task :toc, %i[label includes] do |_task, arguments|
24
- runner.call(**configuration.merge(**arguments.to_h).to_h)
24
+ runner.call configuration.merge(**arguments.to_h)
25
25
  end
26
26
  end
27
27
 
data/lib/tocer/runner.rb CHANGED
@@ -7,21 +7,20 @@ module Tocer
7
7
  class Runner
8
8
  using Refinements::Pathnames
9
9
 
10
- def initialize configuration: CLI::Configuration::Loader.call, writer: Writer.new
11
- @configuration = configuration
10
+ def initialize writer: Writer.new
12
11
  @writer = writer
13
12
  end
14
13
 
15
- def call root_dir: ".", label: configuration.label, includes: configuration.includes
16
- Pathname(root_dir).files(%({#{includes.join ","}}))
17
- .each do |path|
18
- yield path if block_given?
19
- writer.call path, label: label
20
- end
14
+ def call configuration = Configuration::Loader.call
15
+ Pathname(configuration.root_dir).files(%({#{configuration.includes.join ","}}))
16
+ .each do |path|
17
+ yield path if block_given?
18
+ writer.call path, label: configuration.label
19
+ end
21
20
  end
22
21
 
23
22
  private
24
23
 
25
- attr_reader :configuration, :writer
24
+ attr_reader :writer
26
25
  end
27
26
  end
@@ -11,8 +11,9 @@ module Tocer
11
11
  end
12
12
 
13
13
  def call markdown
14
- transformers.find { |pattern, transformer| break transformer if pattern.match? markdown }
15
- .then { |transformer| transformer.new markdown }
14
+ transformers.find do |pattern, transformer|
15
+ break transformer.new(markdown) if pattern.match? markdown
16
+ end
16
17
  end
17
18
 
18
19
  private
data/lib/tocer/writer.rb CHANGED
@@ -24,7 +24,7 @@ module Tocer
24
24
  @builder = builder
25
25
  end
26
26
 
27
- def call path, label: CLI::Configuration::Loader.call.label
27
+ def call path, label: Configuration::Loader.call.label
28
28
  path.rewrite do |body|
29
29
  lines = body.each_line.to_a
30
30
  builder.prependable?(lines) ? prepend(lines, label) : replace(lines, label)
@@ -41,14 +41,22 @@ module Tocer
41
41
  klass = self.class
42
42
 
43
43
  klass.add(
44
- start_index: start_index,
44
+ start_index:,
45
45
  old_lines: klass.remove(start_index, finish_index, lines),
46
- new_lines: content(lines[finish_index, lines.length], label)
46
+ new_lines: new_lines(lines, label, finish_index)
47
47
  ).join
48
48
  end
49
49
 
50
+ def new_lines lines, label, finish_index
51
+ if builder.unbuildable?(lines)
52
+ builder.comments
53
+ else
54
+ content(lines[finish_index, lines.length], label)
55
+ end
56
+ end
57
+
50
58
  def prepend(lines, label) = [content(lines, label), lines.join].compress.join("\n")
51
59
 
52
- def content(lines, label) = builder.call(lines, label: label)
60
+ def content(lines, label) = builder.call(lines, label:)
53
61
  end
54
62
  end
data/lib/tocer.rb CHANGED
@@ -1,20 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "tocer/identity"
4
- require "tocer/elements/comment_block"
5
- require "tocer/parsers/header"
6
- require "tocer/transformers/link"
7
- require "tocer/transformers/text"
8
- require "tocer/transformers/finder"
9
- require "tocer/builder"
10
- require "tocer/writer"
11
- require "tocer/runner"
12
- require "tocer/cli/configuration/content"
13
- require "tocer/cli/configuration/loader"
14
- require "tocer/cli/parsers"
15
- require "tocer/cli/parsers/build"
16
- require "tocer/cli/parsers/core"
17
- require "tocer/cli/parsers/assembler"
18
- require "tocer/cli/processors/build"
19
- require "tocer/cli/processors/config"
20
- require "tocer/cli/shell"
3
+ require "zeitwerk"
4
+
5
+ Zeitwerk::Loader.for_gem.then do |loader|
6
+ loader.inflector.inflect "cli" => "CLI"
7
+ loader.ignore "#{__dir__}/tocer/rake"
8
+ loader.setup
9
+ end
10
+
11
+ # Main namespace.
12
+ module Tocer
13
+ end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tocer
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.1.0
4
+ version: 13.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
@@ -28,7 +28,7 @@ cert_chain:
28
28
  lkHilIrX69jq8wMPpBhlaw2mRmeSL50Wv5u6xVBvOHhXFSP1crXM95vfLhLyRYod
29
29
  W2A=
30
30
  -----END CERTIFICATE-----
31
- date: 2021-10-03 00:00:00.000000000 Z
31
+ date: 2022-01-13 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: refinements
@@ -36,28 +36,42 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '8.4'
39
+ version: '9.0'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '8.4'
46
+ version: '9.0'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: runcom
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '7.0'
53
+ version: '8.0'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '7.0'
60
+ version: '8.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: zeitwerk
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.5'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.5'
61
75
  description:
62
76
  email:
63
77
  - brooke@alchemists.io
@@ -70,19 +84,18 @@ extra_rdoc_files:
70
84
  files:
71
85
  - LICENSE.adoc
72
86
  - README.adoc
73
- - bin/tocer
87
+ - exe/tocer
74
88
  - lib/tocer.rb
75
89
  - lib/tocer/builder.rb
76
- - lib/tocer/cli/configuration/content.rb
77
- - lib/tocer/cli/configuration/defaults.yml
78
- - lib/tocer/cli/configuration/loader.rb
79
- - lib/tocer/cli/parsers.rb
80
- - lib/tocer/cli/parsers/assembler.rb
81
- - lib/tocer/cli/parsers/build.rb
90
+ - lib/tocer/cli/actions/config.rb
91
+ - lib/tocer/cli/actions/insert.rb
92
+ - lib/tocer/cli/parser.rb
82
93
  - lib/tocer/cli/parsers/core.rb
83
- - lib/tocer/cli/processors/build.rb
84
- - lib/tocer/cli/processors/config.rb
94
+ - lib/tocer/cli/parsers/flag.rb
85
95
  - lib/tocer/cli/shell.rb
96
+ - lib/tocer/configuration/content.rb
97
+ - lib/tocer/configuration/defaults.yml
98
+ - lib/tocer/configuration/loader.rb
86
99
  - lib/tocer/elements/comment_block.rb
87
100
  - lib/tocer/identity.rb
88
101
  - lib/tocer/parsers/header.rb
@@ -95,11 +108,12 @@ files:
95
108
  - lib/tocer/writer.rb
96
109
  homepage: https://www.alchemists.io/projects/tocer
97
110
  licenses:
98
- - Apache-2.0
111
+ - Hippocratic-3.0
99
112
  metadata:
100
113
  bug_tracker_uri: https://github.com/bkuhlmann/tocer/issues
101
- changelog_uri: https://www.alchemists.io/projects/tocer/changes.html
114
+ changelog_uri: https://www.alchemists.io/projects/tocer/versions
102
115
  documentation_uri: https://www.alchemists.io/projects/tocer
116
+ rubygems_mfa_required: 'true'
103
117
  source_code_uri: https://github.com/bkuhlmann/tocer
104
118
  post_install_message:
105
119
  rdoc_options: []
@@ -109,14 +123,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
123
  requirements:
110
124
  - - "~>"
111
125
  - !ruby/object:Gem::Version
112
- version: '3.0'
126
+ version: '3.1'
113
127
  required_rubygems_version: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
116
130
  - !ruby/object:Gem::Version
117
131
  version: '0'
118
132
  requirements: []
119
- rubygems_version: 3.2.28
133
+ rubygems_version: 3.3.4
120
134
  signing_key:
121
135
  specification_version: 4
122
136
  summary: A command line interface for generating table of contents for Markdown files.
metadata.gz.sig CHANGED
Binary file
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Tocer
4
- module CLI
5
- module Configuration
6
- # Defines the content of the configuration for use throughout the gem.
7
- Content = Struct.new :label, :includes, keyword_init: true
8
- end
9
- end
10
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "pathname"
4
- require "refinements/structs"
5
- require "runcom"
6
- require "yaml"
7
-
8
- module Tocer
9
- module CLI
10
- module Configuration
11
- # Represents the fully assembled Command Line Interface (CLI) configuration.
12
- class Loader
13
- using Refinements::Structs
14
-
15
- DEFAULTS = YAML.load_file(Pathname(__dir__).join("defaults.yml")).freeze
16
- CLIENT = Runcom::Config.new "#{Identity::NAME}/configuration.yml", defaults: DEFAULTS
17
-
18
- def self.call = new.call
19
-
20
- def initialize content: Content.new, client: CLIENT
21
- @content = content
22
- @client = client
23
- end
24
-
25
- def call = content.merge(**client.to_h)
26
-
27
- private
28
-
29
- attr_reader :content, :client
30
- end
31
- end
32
- end
33
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Tocer
4
- module CLI
5
- module Parsers
6
- # Assembles and parses all Command Line Interface (CLI) options.
7
- class Assembler
8
- SECTIONS = [Core, Build].freeze # Order is important.
9
-
10
- def initialize configuration: CLI::Configuration::Loader.call,
11
- sections: SECTIONS,
12
- client: CLIENT
13
- @options = configuration.to_h
14
- @sections = sections
15
- @client = client
16
- end
17
-
18
- def call arguments = []
19
- sections.each { |parser| parser.call client: client, options: options }
20
- client.parse! arguments
21
- options
22
- end
23
-
24
- def to_h = options
25
-
26
- def to_s = client.to_s
27
-
28
- private
29
-
30
- attr_reader :options, :sections, :client
31
- end
32
- end
33
- end
34
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Tocer
4
- module CLI
5
- module Parsers
6
- # Handles parsing of Command Line Interface (CLI) build options.
7
- class Build
8
- def self.call options: {}, configuration: Configuration::Loader.call, client: CLIENT
9
- new(options: options, configuration: configuration, client: client).call
10
- end
11
-
12
- def initialize options: {}, configuration: Configuration::Loader.call, client: CLIENT
13
- @options = options
14
- @configuration = configuration
15
- @client = client
16
- end
17
-
18
- def call arguments = []
19
- client.separator "\nBUILD OPTIONS:\n"
20
- private_methods.sort.grep(/add_/).each { |method| __send__ method }
21
- arguments.empty? ? arguments : client.parse!(arguments)
22
- end
23
-
24
- private
25
-
26
- attr_reader :options, :configuration, :client
27
-
28
- def add_label
29
- client.on(
30
- "-l",
31
- "--label [LABEL]",
32
- %(Label. Default: "#{CLI::Configuration::Loader.call.label}".)
33
- ) do |value|
34
- options[:label] = value || configuration.to_h.fetch(:label)
35
- end
36
- end
37
-
38
- def add_include
39
- client.on(
40
- "-i",
41
- "--includes [a,b,c]",
42
- Array,
43
- %(Include pattern list. Default: #{CLI::Configuration::Loader.call.includes}.)
44
- ) do |value|
45
- list = Array value
46
- options[:includes] = list.empty? ? configuration.to_h.fetch(:includes) : list
47
- end
48
- end
49
- end
50
- end
51
- end
52
- end