tocer 10.5.0 → 12.0.2

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: 0ba1e651bf48853c263f315d485ec8bcda29f9139b28eac4910c0e5f6b856008
4
- data.tar.gz: e86c40bbb6076d4b9cdb086eda67a2e3259d8cee340a4a5905eeba2b76ef749b
3
+ metadata.gz: e87cdc42651955652ee2d24f27b95c6722561c4b284a0ff5fb6b3341425f9eb8
4
+ data.tar.gz: 6170cd85486b4e8c5a9168b265ba1d3d6127fab7e662ea26f8095a028f7e9699
5
5
  SHA512:
6
- metadata.gz: 8c4bbe93b91fa446d7af523ac0c884f0c80183e869851b3376231f734eb00cd5d165c39c7cb5715d76fed135057ce06b0e3fa6a2b164682f57d890cc13d04731
7
- data.tar.gz: 6abf86c41ce959e5803484c96f37a444c5a092d149089500dcd82d21cdc0d69684c0243a2ea0cad7d4732402b586328f372dff9286e178568083ffaf0821ac11
6
+ metadata.gz: 012aca333c7cd34bc26bba320e1ddce5fb25f138f93378efdf551d6c65873eba8745960ccdccc296616569359681f4f6e68342f9c52d0ce10d6eba30b2d1f080
7
+ data.tar.gz: 3f9a398064fbb8521952cf6ac5e9749eaa2373ff6ca48c865ea23b6eb814d1e11f046e0656e6230264a3e55d35c39838f867817baf44e0124f98e32ae9457dbc
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -45,22 +45,18 @@ gem install tocer
45
45
 
46
46
  === Command Line Interface (CLI)
47
47
 
48
- From the command line, type: `+tocer --help+`
48
+ From the command line, run: `tocer --help`
49
49
 
50
50
  ....
51
- tocer -c, [--config] # Manage gem configuration.
52
- tocer -g, [--generate=PATH] # Generate table of contents.
53
- tocer -h, [--help=COMMAND] # Show this message or get help for a command.
54
- tocer -v, [--version] # Show gem version.
55
- ....
56
-
57
- For specific `+--generate+` options, run `+tocer --help --generate+` to see the following:
58
-
59
- ....
60
- -l, [--label=LABEL] # Label
61
- # Default: ## Table of Contents
62
- -i, [--includes=one two three] # File include list
63
- # Default: ["README.md"]
51
+ USAGE:
52
+ -b, --build [PATH] Build table of contents. Default path: "."
53
+ -c, --config ACTION Manage gem configuration: edit or view.
54
+ -h, --help Show this message.
55
+ -v, --version Show gem version.
56
+
57
+ BUILD OPTIONS:
58
+ -i, --includes [a,b,c] Include pattern list. Default: ["README.md"].
59
+ -l, --label [LABEL] Label. Default: "## Table of Contents".
64
60
  ....
65
61
 
66
62
  To generate the table of contents at a specific position within your Markdown files, add the
@@ -72,10 +68,6 @@ following lines to your file(s) prior to generation:
72
68
  <!-- Tocer[finish] -->
73
69
  ----
74
70
 
75
- Alternatively, you can run `+tocer -g <directory>+` on files that do not have Tocer support and it
76
- will prepend the table of contents to your file(s), complete with an auto-generated table of
77
- contents.
78
-
79
71
  In the case that Tocer has already auto-generated a table of contents for a Markdown file, the
80
72
  existing table of contents has become stale, or placement of the table of contents has changed you
81
73
  can re-run Tocer on that file to auto-update it with new table of contents.
@@ -101,8 +93,8 @@ Feel free to take this default configuration, modify, and save as your own custo
101
93
 
102
94
  The `configuration.yml` file can be configured as follows:
103
95
 
104
- * `label`: The header label for the table of contents. Default: `"# Table of Contents"`.
105
- * `includes`: The list of included files. Default: `"*.md"`.
96
+ * `label`: The header label for the table of contents.
97
+ * `includes`: The list of included files.
106
98
 
107
99
  There are multiple ways the include list can be defined. Here are some examples:
108
100
 
data/bin/tocer CHANGED
@@ -2,8 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "tocer"
5
- require "tocer/cli"
6
- require "tocer/identity"
7
5
 
8
6
  Process.setproctitle Tocer::Identity::VERSION_LABEL
9
- Tocer::CLI.start
7
+ Tocer::CLI::Shell.new.call ARGV
data/lib/tocer.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "tocer/identity"
4
- require "tocer/configuration"
5
4
  require "tocer/elements/comment_block"
6
5
  require "tocer/parsers/header"
7
6
  require "tocer/transformers/link"
@@ -10,4 +9,12 @@ require "tocer/transformers/finder"
10
9
  require "tocer/builder"
11
10
  require "tocer/writer"
12
11
  require "tocer/runner"
13
- require "tocer/cli"
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"
data/lib/tocer/builder.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "forwardable"
4
4
 
5
5
  module Tocer
6
- # Builds a table of contents for a Markdown document.
6
+ # Builds table of contents for a Markdown document.
7
7
  class Builder
8
8
  extend Forwardable
9
9
 
@@ -11,33 +11,35 @@ module Tocer
11
11
 
12
12
  def_delegators :comment_block, :start_index, :finish_index, :prependable?
13
13
 
14
- def initialize label: "## Table of Contents", comment_block: Elements::CommentBlock.new
15
- @label = label
14
+ def initialize comment_block: Elements::CommentBlock.new, transformer: Transformers::Finder.new
16
15
  @comment_block = comment_block
16
+ @transformer = transformer
17
17
  @url_count = Hash.new 0
18
18
  @code_block = false
19
19
  end
20
20
 
21
- def call lines
21
+ def call lines, label: CLI::Configuration::Loader.call.label
22
22
  return "" if headers(lines).empty?
23
23
 
24
- [
25
- "#{comment_block.start_tag}\n\n",
26
- "#{label}\n\n",
27
- links(lines).join("\n"),
28
- "\n\n#{comment_block.finish_tag}\n"
29
- ].join
24
+ assemble(lines, label).join
30
25
  end
31
26
 
32
27
  private
33
28
 
34
- attr_reader :label, :comment_block, :url_count
29
+ attr_reader :comment_block, :transformer, :url_count
35
30
  attr_accessor :code_block
36
31
 
37
- def links lines
38
- headers(lines).map { |markdown| transform markdown }
32
+ def assemble lines, label
33
+ [
34
+ "#{comment_block.start_tag}\n\n",
35
+ "#{label}\n\n",
36
+ links(lines).join("\n"),
37
+ "\n\n#{comment_block.finish_tag}\n"
38
+ ]
39
39
  end
40
40
 
41
+ def links(lines) = headers(lines).map { |markdown| transform markdown }
42
+
41
43
  def headers lines
42
44
  lines.select do |line|
43
45
  toggle_code_block line
@@ -52,16 +54,14 @@ module Tocer
52
54
  end
53
55
 
54
56
  def transform markdown
55
- Transformers::Finder.new.call(markdown).then do |transformer|
56
- url = transformer.url
57
- link = transformer.call url_suffix: url_suffix(url)
57
+ transformer.call(markdown).then do |instance|
58
+ url = instance.url
59
+ link = instance.call url_suffix: url_suffix(url)
58
60
  url_count[url] += 1
59
61
  link
60
62
  end
61
63
  end
62
64
 
63
- def url_suffix url
64
- url_count[url].then { |count| count.zero? ? "" : count }
65
- end
65
+ def url_suffix(url) = url_count[url].then { |count| count.zero? ? "" : count }
66
66
  end
67
67
  end
@@ -0,0 +1,10 @@
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
@@ -0,0 +1,3 @@
1
+ :label: "## Table of Contents"
2
+ :includes:
3
+ - "README.md"
@@ -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 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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+
5
+ module Tocer
6
+ module CLI
7
+ module Parsers
8
+ CLIENT = OptionParser.new nil, 40, " "
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,52 @@
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
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tocer/identity"
4
+
5
+ module Tocer
6
+ module CLI
7
+ module Parsers
8
+ # Handles parsing of Command Line Interface (CLI) core options.
9
+ class Core
10
+ def self.call(options: {}, client: CLIENT) = new(options: options, client: client).call
11
+
12
+ def initialize options: {}, client: CLIENT
13
+ @options = options
14
+ @client = client
15
+ end
16
+
17
+ def call arguments = []
18
+ client.banner = "#{Identity::LABEL} - #{Identity::SUMMARY}"
19
+ client.separator "\nUSAGE:\n"
20
+ collate
21
+ arguments.empty? ? arguments : client.parse!(arguments)
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :options, :client
27
+
28
+ def collate = private_methods.sort.grep(/add_/).each { |method| __send__ method }
29
+
30
+ def add_config
31
+ client.on(
32
+ "-c",
33
+ "--config ACTION",
34
+ %i[edit view],
35
+ "Manage gem configuration: edit or view."
36
+ ) do |action|
37
+ options[:config] = action
38
+ end
39
+ end
40
+
41
+ def add_build
42
+ client.on "-b", "--build [PATH]", %(Build table of contents. Default path: ".") do |value|
43
+ options[:build] = value || "."
44
+ end
45
+ end
46
+
47
+ def add_version
48
+ client.on "-v", "--version", "Show gem version." do
49
+ options[:version] = Identity::VERSION_LABEL
50
+ end
51
+ end
52
+
53
+ def add_help
54
+ client.on "-h", "--help", "Show this message." do
55
+ options[:help] = true
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tocer
4
+ module CLI
5
+ module Processors
6
+ # Handles the Command Line Interface (CLI) for building of table of contents.
7
+ class Build
8
+ def initialize runner: Runner.new
9
+ @runner = runner
10
+ end
11
+
12
+ def call root_dir = ".", configuration = {}
13
+ runner.call(root_dir: root_dir, **configuration.slice(:label, :includes)) do |path|
14
+ puts " #{path}"
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :runner
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tocer
4
+ module CLI
5
+ module Processors
6
+ # Handles the Command Line Interface (CLI) configuration processing.
7
+ class Config
8
+ def initialize configuration: CLI::Configuration::Loader::CLIENT, kernel: Kernel
9
+ @configuration = configuration
10
+ @kernel = kernel
11
+ end
12
+
13
+ def call action
14
+ case action
15
+ when :edit then edit
16
+ when :view then view
17
+ else fail StandardError, "Invalid configuration action: #{action}."
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :configuration, :kernel
24
+
25
+ def edit = kernel.system("$EDITOR #{configuration.current}")
26
+
27
+ def view = kernel.system("cat #{configuration.current}")
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tocer
4
+ module CLI
5
+ # The main Command Line Interface (CLI) object.
6
+ class Shell
7
+ PROCESSORS = {config: Processors::Config.new, build: Processors::Build.new}.freeze
8
+
9
+ def initialize parser: Parsers::Assembler.new, processors: PROCESSORS
10
+ @parser = parser
11
+ @processors = processors
12
+ end
13
+
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
+ in help: then usage
22
+ else usage
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :parser, :processors
29
+
30
+ def parse arguments = []
31
+ parser.call arguments
32
+ rescue StandardError => error
33
+ puts error.message
34
+ end
35
+
36
+ def process_config(action) = processors.fetch(:config).call(action)
37
+
38
+ def process_build(path) = processors.fetch(:build).call(path, options)
39
+
40
+ def options = parser.to_h
41
+
42
+ def usage = puts(parser.to_s)
43
+ end
44
+ end
45
+ end
@@ -17,33 +17,21 @@ module Tocer
17
17
  @message = message
18
18
  end
19
19
 
20
- def start_index lines
21
- self.class.index lines, start_id
22
- end
20
+ def start_index(lines) = self.class.index(lines, start_id)
23
21
 
24
- def start_tag
25
- comment start_id, message
26
- end
22
+ def start_tag = comment(start_id, message)
27
23
 
28
- def finish_index lines
29
- self.class.index lines, finish_id
30
- end
24
+ def finish_index(lines) = self.class.index(lines, finish_id)
31
25
 
32
- def finish_tag
33
- comment finish_id, message
34
- end
26
+ def finish_tag = comment(finish_id, message)
35
27
 
36
- def prependable? lines
37
- start_index(lines).zero? && finish_index(lines).zero?
38
- end
28
+ def prependable?(lines) = start_index(lines).zero? && finish_index(lines).zero?
39
29
 
40
30
  private
41
31
 
42
32
  attr_reader :start_id, :finish_id, :message
43
33
 
44
- def comment id, message
45
- "<!-- #{id}: #{message} -->"
46
- end
34
+ def comment(id, message) = "<!-- #{id}: #{message} -->"
47
35
  end
48
36
  end
49
37
  end
@@ -5,7 +5,8 @@ module Tocer
5
5
  module Identity
6
6
  NAME = "tocer"
7
7
  LABEL = "Tocer"
8
- VERSION = "10.5.0"
8
+ VERSION = "12.0.2"
9
9
  VERSION_LABEL = "#{LABEL} #{VERSION}"
10
+ SUMMARY = "A command line interface for generating table of contents for Markdown files."
10
11
  end
11
12
  end
@@ -10,13 +10,9 @@ module Tocer
10
10
  @markdown = markdown
11
11
  end
12
12
 
13
- def prefix
14
- String markdown[/#{PUNCTUATION}{1,}/o]
15
- end
13
+ def prefix = String(markdown[/#{PUNCTUATION}{1,}/o])
16
14
 
17
- def content
18
- markdown[prefix.length + 1, markdown.length].strip
19
- end
15
+ def content = markdown[prefix.length + 1, markdown.length].strip
20
16
 
21
17
  private
22
18
 
@@ -2,17 +2,18 @@
2
2
 
3
3
  require "rake"
4
4
  require "tocer"
5
+ require "refinements/structs"
5
6
 
6
7
  module Tocer
7
8
  module Rake
9
+ # Provides Rake tasks for convenience.
8
10
  class Tasks
9
11
  include ::Rake::DSL
12
+ using Refinements::Structs
10
13
 
11
- def self.setup
12
- new.install
13
- end
14
+ def self.setup = new.install
14
15
 
15
- def initialize configuration: Tocer::Configuration.default, runner: Runner
16
+ def initialize configuration: CLI::Configuration::Loader.new.call, runner: Runner.new
16
17
  @configuration = configuration
17
18
  @runner = runner
18
19
  end
@@ -20,9 +21,7 @@ module Tocer
20
21
  def install
21
22
  desc "Add/Update Table of Contents (README)"
22
23
  task :toc, %i[label includes] do |_task, arguments|
23
- inputs = {label: arguments[:label], includes: arguments[:includes]}.compact
24
- updated_configuration = configuration.merge inputs
25
- runner.new(configuration: updated_configuration.to_h).call
24
+ runner.call(**configuration.merge(**arguments.to_h).to_h)
26
25
  end
27
26
  end
28
27
 
data/lib/tocer/runner.rb CHANGED
@@ -1,32 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
3
+ require "refinements/pathnames"
4
4
 
5
5
  module Tocer
6
- # Generates/updates Table of Contents for files in given path.
6
+ # Generates/updates Table of Contents for files in root path.
7
7
  class Runner
8
- def initialize path = ".", configuration: {}, writer: Writer
9
- @path = Pathname path
8
+ using Refinements::Pathnames
9
+
10
+ def initialize configuration: CLI::Configuration::Loader.call, writer: Writer.new
10
11
  @configuration = configuration
11
12
  @writer = writer
12
13
  end
13
14
 
14
- def files
15
- return [] unless path.exist? && path.directory? && !includes.empty?
16
-
17
- Pathname.glob(%(#{path}/{#{includes.join ","}})).select(&:file?)
18
- end
19
-
20
- def call
21
- files.each { |file| writer.new(file, label: configuration.fetch(:label)).call }
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
22
21
  end
23
22
 
24
23
  private
25
24
 
26
- attr_reader :path, :configuration, :writer
27
-
28
- def includes
29
- Array configuration[:includes]
30
- end
25
+ attr_reader :configuration, :writer
31
26
  end
32
27
  end
@@ -4,10 +4,7 @@ module Tocer
4
4
  module Transformers
5
5
  # Finds appropriate header transformer for matching pattern.
6
6
  class Finder
7
- TRANSFORMERS = {
8
- /\[.+\]\(.+\)/ => Transformers::Link,
9
- /.*/ => Transformers::Text
10
- }.freeze
7
+ TRANSFORMERS = {/\[.+\]\(.+\)/ => Transformers::Link, /.*/ => Transformers::Text}.freeze
11
8
 
12
9
  def initialize transformers: TRANSFORMERS
13
10
  @transformers = transformers
@@ -12,45 +12,27 @@ module Tocer
12
12
  @parser = parser.new text
13
13
  end
14
14
 
15
- def label
16
- parser.content.gsub embedded_link, embedded_link_label
17
- end
15
+ def label = parser.content.gsub(embedded_link, embedded_link_label)
18
16
 
19
- def url
20
- label.downcase.gsub(/\s/, "-").gsub(/[^\w\-]+/, "")
21
- end
17
+ def url = label.downcase.gsub(/\s/, "-").gsub(/[^\w\-]+/, "")
22
18
 
23
- def call url_suffix: ""
24
- "#{indented_bullet}[#{label}](##{computed_url url_suffix})"
25
- end
19
+ def call(url_suffix: "") = "#{indented_bullet}[#{label}](##{computed_url url_suffix})"
26
20
 
27
21
  private
28
22
 
29
23
  attr_reader :parser
30
24
 
31
- def computed_url suffix = ""
32
- [url, suffix.to_s].compress.join "-"
33
- end
25
+ def computed_url(suffix = "") = [url, suffix.to_s].compress.join("-")
34
26
 
35
- def embedded_link
36
- "[#{embedded_link_label}](#{embedded_link_url})"
37
- end
27
+ def embedded_link = "[#{embedded_link_label}](#{embedded_link_url})"
38
28
 
39
- def embedded_link_label
40
- parser.content[/\[(.*)\]/, 1]
41
- end
29
+ def embedded_link_label = parser.content[/\[(.*)\]/, 1]
42
30
 
43
- def embedded_link_url
44
- parser.content[/\((.*)\)/, 1]
45
- end
31
+ def embedded_link_url = parser.content[/\((.*)\)/, 1]
46
32
 
47
- def indented_bullet
48
- prefix_to_spaces.gsub(/\s{2}$/, "- ")
49
- end
33
+ def indented_bullet = prefix_to_spaces.gsub(/\s{2}$/, "- ")
50
34
 
51
- def prefix_to_spaces
52
- Array.new(parser.prefix.length, " ").join
53
- end
35
+ def prefix_to_spaces = Array.new(parser.prefix.length, " ").join
54
36
  end
55
37
  end
56
38
  end
@@ -12,33 +12,21 @@ module Tocer
12
12
  @parser = parser.new text
13
13
  end
14
14
 
15
- def label
16
- parser.content
17
- end
15
+ def label = parser.content
18
16
 
19
- def url
20
- label.downcase.gsub(/\s/, "-").gsub(/[^\w\-]+/, "")
21
- end
17
+ def url = label.downcase.gsub(/\s/, "-").gsub(/[^\w\-]+/, "")
22
18
 
23
- def call url_suffix: ""
24
- "#{indented_bullet}[#{label}](##{computed_url url_suffix})"
25
- end
19
+ def call(url_suffix: "") = "#{indented_bullet}[#{label}](##{computed_url url_suffix})"
26
20
 
27
21
  private
28
22
 
29
23
  attr_reader :parser
30
24
 
31
- def computed_url suffix = ""
32
- [url, suffix.to_s].compress.join "-"
33
- end
25
+ def computed_url(suffix = "") = [url, suffix.to_s].compress.join("-")
34
26
 
35
- def indented_bullet
36
- prefix_to_spaces.gsub(/\s{2}$/, "- ")
37
- end
27
+ def indented_bullet = prefix_to_spaces.gsub(/\s{2}$/, "- ")
38
28
 
39
- def prefix_to_spaces
40
- Array.new(parser.prefix.length, " ").join
41
- end
29
+ def prefix_to_spaces = Array.new(parser.prefix.length, " ").join
42
30
  end
43
31
  end
44
32
  end
data/lib/tocer/writer.rb CHANGED
@@ -1,8 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "refinements/arrays"
4
+ require "refinements/pathnames"
5
+
3
6
  module Tocer
4
7
  # Writes table of contents to a Markdown document.
8
+ # :reek:DataClump
5
9
  class Writer
10
+ using Refinements::Arrays
11
+ using Refinements::Pathnames
12
+
6
13
  def self.add start_index:, old_lines:, new_lines:
7
14
  computed_new_lines = start_index.zero? ? new_lines : new_lines + "\n"
8
15
  old_lines.insert start_index, *computed_new_lines
@@ -13,26 +20,22 @@ module Tocer
13
20
  lines.reject.with_index { |_, index| range.include? index }
14
21
  end
15
22
 
16
- def initialize file_path, label: "## Table of Contents", builder: Builder.new(label: label)
17
- @file_path = file_path
23
+ def initialize builder: Builder.new
18
24
  @builder = builder
19
25
  end
20
26
 
21
- def call
22
- lines = File.readlines file_path
23
- body = builder.prependable?(lines) ? prepend(lines) : replace(lines)
24
- File.open(file_path, "w") { |file| file.write body }
27
+ def call path, label: CLI::Configuration::Loader.call.label
28
+ path.rewrite do |body|
29
+ lines = body.each_line.to_a
30
+ builder.prependable?(lines) ? prepend(lines, label) : replace(lines, label)
31
+ end
25
32
  end
26
33
 
27
34
  private
28
35
 
29
- attr_reader :file_path, :builder
30
-
31
- def content lines
32
- builder.call lines
33
- end
36
+ attr_reader :builder
34
37
 
35
- def replace lines
38
+ def replace lines, label
36
39
  start_index = builder.start_index lines
37
40
  finish_index = builder.finish_index lines
38
41
  klass = self.class
@@ -40,12 +43,12 @@ module Tocer
40
43
  klass.add(
41
44
  start_index: start_index,
42
45
  old_lines: klass.remove(start_index, finish_index, lines),
43
- new_lines: content(lines[finish_index, lines.length])
46
+ new_lines: content(lines[finish_index, lines.length], label)
44
47
  ).join
45
48
  end
46
49
 
47
- def prepend lines
48
- content(lines) + "\n" + lines.join
49
- end
50
+ def prepend(lines, label) = [content(lines, label), lines.join].compress.join("\n")
51
+
52
+ def content(lines, label) = builder.call(lines, label: label)
50
53
  end
51
54
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tocer
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.5.0
4
+ version: 12.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -10,9 +10,9 @@ bindir: bin
10
10
  cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
- MIIC/jCCAeagAwIBAgIBAzANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBpicm9v
14
- a2UvREM9YWxjaGVtaXN0cy9EQz1pbzAeFw0yMDAzMTUxNDQ1MzJaFw0yMTAzMTUx
15
- NDQ1MzJaMCUxIzAhBgNVBAMMGmJyb29rZS9EQz1hbGNoZW1pc3RzL0RDPWlvMIIB
13
+ MIIC/jCCAeagAwIBAgIBBDANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBpicm9v
14
+ a2UvREM9YWxjaGVtaXN0cy9EQz1pbzAeFw0yMTAzMTkxMjQ4MDZaFw0yMjAzMTkx
15
+ MjQ4MDZaMCUxIzAhBgNVBAMMGmJyb29rZS9EQz1hbGNoZW1pc3RzL0RDPWlvMIIB
16
16
  IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6l1qpXTiomH1RfMRloyw7MiE
17
17
  xyVx/x8Yc3EupdH7uhNaTXQGyORN6aOY//1QXXMHIZ9tW74nZLhesWMSUMYy0XhB
18
18
  brs+KkurHnc9FnEJAbG7ebGvl/ncqZt72nQvaxpDxvuCBHgJAz+8i5wl6FhLw+oT
@@ -20,15 +20,15 @@ cert_chain:
20
20
  D5vkU0YlAm1r98BymuJlcQ1qdkVEI1d48ph4kcS0S0nv1RiuyVb6TCAR3Nu3VaVq
21
21
  3fPzZKJLZBx67UvXdbdicWPiUR75elI4PXpLIic3xytaF52ZJYyKZCNZJhNwfQID
22
22
  AQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU0nzow9vc
23
- 2CdikiiE3fJhP/gY4ggwDQYJKoZIhvcNAQELBQADggEBAIHhAlD3po4sTYqacXaQ
24
- XI9jIhrfMy//2PgbHWcETtlJPBeNUbbSNBABcllUHKqYsVDlSvSmss034KSWNR8F
25
- bF1GcloicyvcCC4y6IoW4it0COAcdeaaxkxiBSgKdQFpff9REnDlIKK4uQ9lLxIo
26
- Y2G5xubiziKZkyfWFuSr67PIjW3Bu673D1JVBArhA1qbgQmYQcy1CkGOjo+iO8Nf
27
- 7u/QSfBHb+r/bXhKscDgPpnKwbUmvgO2+94zJG9KsrmIydlzYfsD09aXKx0t6Xy4
28
- 2XV8FRa7/JimI07sPLC13eLY3xd/aYTi85Z782KIA4j0G8XEEWAX0ouBhlXPocZv
29
- QWc=
23
+ 2CdikiiE3fJhP/gY4ggwDQYJKoZIhvcNAQELBQADggEBAEjpaOXHHp8s/7GL2qCb
24
+ YAs7urOLv9VHSPfQWAwaTMVnSsIf3Sw4xzISOP/mmfEPBPXtz61K5esrE/uTFtgb
25
+ FyjxQk2H0sEWgrRXGGNHBWQRhhEs7LP/TByoC15A0br++xLxRz4r7HBLGAWQQDpg
26
+ 66BJ2TBVjxS6K64tKbq7+ACyrOZGgTfNHACh4M076y0x0oRf/rwBrU39/KRfuhbb
27
+ cm+nNCEtO35gTmZ2bVDHLGvWazi3gJt6+huQjfXTCUUG2YYBxwhu+GPdAGQPxpf9
28
+ lkHilIrX69jq8wMPpBhlaw2mRmeSL50Wv5u6xVBvOHhXFSP1crXM95vfLhLyRYod
29
+ W2A=
30
30
  -----END CERTIFICATE-----
31
- date: 2020-12-13 00:00:00.000000000 Z
31
+ date: 2021-05-20 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: refinements
@@ -36,42 +36,28 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '7.16'
39
+ version: '8.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: '7.16'
46
+ version: '8.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: '6.4'
53
+ version: '7.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: '6.4'
61
- - !ruby/object:Gem::Dependency
62
- name: thor
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '0.20'
68
- type: :runtime
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '0.20'
60
+ version: '7.0'
75
61
  description:
76
62
  email:
77
63
  - brooke@alchemists.io
@@ -87,8 +73,16 @@ files:
87
73
  - bin/tocer
88
74
  - lib/tocer.rb
89
75
  - lib/tocer/builder.rb
90
- - lib/tocer/cli.rb
91
- - lib/tocer/configuration.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
82
+ - lib/tocer/cli/parsers/core.rb
83
+ - lib/tocer/cli/processors/build.rb
84
+ - lib/tocer/cli/processors/config.rb
85
+ - lib/tocer/cli/shell.rb
92
86
  - lib/tocer/elements/comment_block.rb
93
87
  - lib/tocer/identity.rb
94
88
  - lib/tocer/parsers/header.rb
@@ -115,14 +109,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
109
  requirements:
116
110
  - - "~>"
117
111
  - !ruby/object:Gem::Version
118
- version: '2.7'
112
+ version: '3.0'
119
113
  required_rubygems_version: !ruby/object:Gem::Requirement
120
114
  requirements:
121
115
  - - ">="
122
116
  - !ruby/object:Gem::Version
123
117
  version: '0'
124
118
  requirements: []
125
- rubygems_version: 3.2.0
119
+ rubygems_version: 3.2.17
126
120
  signing_key:
127
121
  specification_version: 4
128
122
  summary: A command line interface for generating table of contents for Markdown files.
metadata.gz.sig CHANGED
Binary file
data/lib/tocer/cli.rb DELETED
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "thor"
4
- require "thor/actions"
5
- require "runcom"
6
-
7
- module Tocer
8
- # The Command Line Interface (CLI) for the gem.
9
- class CLI < Thor
10
- include Thor::Actions
11
-
12
- package_name Identity::VERSION_LABEL
13
-
14
- def initialize args = [], options = {}, config = {}
15
- super args, options, config
16
- @configuration = Tocer::Configuration.default
17
- rescue Runcom::Errors::Base => error
18
- abort error.message
19
- end
20
-
21
- desc "-g, [--generate=PATH]", "Generate table of contents."
22
- map %w[-g --generate] => :generate
23
- method_option :label,
24
- aliases: "-l",
25
- desc: "Label",
26
- type: :string,
27
- default: Tocer::Configuration.default.to_h.fetch(:label)
28
- method_option :includes,
29
- aliases: "-i",
30
- desc: "File include list",
31
- type: :array,
32
- default: Tocer::Configuration.default.to_h.fetch(:includes)
33
- # :reek:TooManyStatements
34
- def generate path = "."
35
- updated_configuration = configuration.merge label: options.label, includes: options.includes
36
- runner = Runner.new path, configuration: updated_configuration.to_h
37
- files = runner.files
38
-
39
- return if files.empty?
40
-
41
- runner.call
42
-
43
- say "Processed table of contents for:"
44
- files.each { |file| say " #{file}" }
45
- end
46
-
47
- desc "-c, [--config]", "Manage gem configuration."
48
- map %w[-c --config] => :config
49
- method_option :edit,
50
- aliases: "-e",
51
- desc: "Edit gem configuration.",
52
- type: :boolean,
53
- default: false
54
- method_option :info,
55
- aliases: "-i",
56
- desc: "Print gem configuration.",
57
- type: :boolean,
58
- default: false
59
- def config
60
- path = configuration.current
61
-
62
- if options.edit? then `#{ENV["EDITOR"]} #{path}`
63
- elsif options.info?
64
- path ? say(path) : say("Configuration doesn't exist.")
65
- else help :config
66
- end
67
- end
68
-
69
- desc "-v, [--version]", "Show gem version."
70
- map %w[-v --version] => :version
71
- def version
72
- say Identity::VERSION_LABEL
73
- end
74
-
75
- desc "-h, [--help=COMMAND]", "Show this message or get help for a command."
76
- map %w[-h --help] => :help
77
- def help task = nil
78
- say and super
79
- end
80
-
81
- private
82
-
83
- attr_reader :configuration
84
- end
85
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "runcom"
4
-
5
- module Tocer
6
- module Configuration
7
- def self.default
8
- Runcom::Config.new "#{Identity::NAME}/configuration.yml",
9
- defaults: {
10
- label: "## Table of Contents",
11
- includes: ["README.md"]
12
- }
13
- end
14
- end
15
- end