tocer 10.4.0 → 12.0.0

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: f502b2c16f1de6f7fa1bfb7a14a121d4c6813a4377e4d8d39ff3148a1fb9c51d
4
- data.tar.gz: a158d9b183195ddc25c8aabac843cd0c40736a72dc269c1091db1b982bb308f3
3
+ metadata.gz: '096af23217cee6fd1f0fc3193a733eae8fff2cc586bce9058fde6d67c409aca3'
4
+ data.tar.gz: e491575b96fe2dfdad444015d228cd5150d2e8a2aebd85f98977fed6b598e268
5
5
  SHA512:
6
- metadata.gz: f40354ec43eadb99aaad94d6155071c2ef15fc13598e23ba39ca082659aaffa9881ee731bde4878d2a4a027f9a056f1a1fbccdadc67b959b9c05710e0bf8d4d4
7
- data.tar.gz: e59e9975bb17627a41fd8d2e6c7e1f99d0d1e5cb2d5a4172249afa09fe49d0771836aa70af88d9e81d8a82900a3876819d68a7e8cfaa3d9fedfc296deadcb31e
6
+ metadata.gz: 51f72f12821e8101fac9ce9f062879756493916725d4bc5c25129e9a4b13338f5b524a51ce66a4f9387404499ea8baa3d7eb1db764ef58315af9f1c9bc9ee37e
7
+ data.tar.gz: 5ea05ed97e8a350c3a32470f7627e47e60d2be56368da9e738ea5e9a302a5998dae9ea93706f9e7f9c19609b0f7d98dd324a621ea0eb3a2b6fc36fb410e8c766
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,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "runcom"
4
+
5
+ module Tocer
6
+ module CLI
7
+ module Parsers
8
+ SECTIONS = [Core, Build].freeze # Order is important.
9
+
10
+ # Assembles and parses all Command Line Interface (CLI) options.
11
+ class Assembler
12
+ def initialize configuration: CLI::Configuration::Loader.call,
13
+ sections: SECTIONS,
14
+ client: CLIENT
15
+ @options = configuration.to_h
16
+ @sections = sections
17
+ @client = client
18
+ end
19
+
20
+ def call arguments = []
21
+ sections.each { |parser| parser.call client: client, options: options }
22
+ client.parse! arguments
23
+ options
24
+ end
25
+
26
+ def to_h = options
27
+
28
+ def to_s = client.to_s
29
+
30
+ private
31
+
32
+ attr_reader :options, :client, :sections
33
+ end
34
+ end
35
+ end
36
+ 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,63 @@
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
29
+ private_methods.sort.grep(/add_/).each { |method| __send__ method }
30
+ end
31
+
32
+ def add_config
33
+ client.on(
34
+ "-c",
35
+ "--config ACTION",
36
+ %i[edit view],
37
+ "Manage gem configuration: edit or view."
38
+ ) do |action|
39
+ options[:config] = action
40
+ end
41
+ end
42
+
43
+ def add_build
44
+ client.on "-b", "--build [PATH]", %(Build table of contents. Default path: ".") do |value|
45
+ options[:build] = value || "."
46
+ end
47
+ end
48
+
49
+ def add_version
50
+ client.on "-v", "--version", "Show gem version." do
51
+ options[:version] = Identity::VERSION_LABEL
52
+ end
53
+ end
54
+
55
+ def add_help
56
+ client.on "-h", "--help", "Show this message." do
57
+ options[:help] = true
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ 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,48 @@
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 = {
8
+ config: Processors::Config.new,
9
+ build: Processors::Build.new
10
+ }.freeze
11
+
12
+ def initialize parser: Parsers::Assembler.new, processors: PROCESSORS
13
+ @parser = parser
14
+ @processors = processors
15
+ end
16
+
17
+ def call arguments = []
18
+ parse arguments
19
+
20
+ case options
21
+ in config: action then process_config action
22
+ in build: path then process_build path
23
+ in version: then puts version
24
+ in help: then usage
25
+ else usage
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :parser, :processors
32
+
33
+ def parse arguments = []
34
+ parser.call arguments
35
+ rescue StandardError => error
36
+ puts error.message
37
+ end
38
+
39
+ def process_config(action) = processors.fetch(:config).call(action)
40
+
41
+ def process_build(path) = processors.fetch(:build).call(path, options)
42
+
43
+ def options = parser.to_h
44
+
45
+ def usage = puts(parser.to_s)
46
+ end
47
+ end
48
+ 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.4.0"
8
+ VERSION = "12.0.0"
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,}/]
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).call
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
@@ -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,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "refinements/pathnames"
4
+
3
5
  module Tocer
4
6
  # Writes table of contents to a Markdown document.
7
+ # :reek:DataClump
5
8
  class Writer
9
+ using Refinements::Pathnames
10
+
6
11
  def self.add start_index:, old_lines:, new_lines:
7
12
  computed_new_lines = start_index.zero? ? new_lines : new_lines + "\n"
8
13
  old_lines.insert start_index, *computed_new_lines
@@ -13,26 +18,22 @@ module Tocer
13
18
  lines.reject.with_index { |_, index| range.include? index }
14
19
  end
15
20
 
16
- def initialize file_path, label: "## Table of Contents", builder: Builder.new(label: label)
17
- @file_path = file_path
21
+ def initialize builder: Builder.new
18
22
  @builder = builder
19
23
  end
20
24
 
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 }
25
+ def call path, label: CLI::Configuration::Loader.call.label
26
+ path.rewrite do |body|
27
+ lines = body.each_line.to_a
28
+ builder.prependable?(lines) ? prepend(lines, label) : replace(lines, label)
29
+ end
25
30
  end
26
31
 
27
32
  private
28
33
 
29
- attr_reader :file_path, :builder
30
-
31
- def content lines
32
- builder.call lines
33
- end
34
+ attr_reader :builder
34
35
 
35
- def replace lines
36
+ def replace lines, label
36
37
  start_index = builder.start_index lines
37
38
  finish_index = builder.finish_index lines
38
39
  klass = self.class
@@ -40,12 +41,12 @@ module Tocer
40
41
  klass.add(
41
42
  start_index: start_index,
42
43
  old_lines: klass.remove(start_index, finish_index, lines),
43
- new_lines: content(lines[finish_index, lines.length])
44
+ new_lines: content(lines[finish_index, lines.length], label)
44
45
  ).join
45
46
  end
46
47
 
47
- def prepend lines
48
- content(lines) + "\n" + lines.join
49
- end
48
+ def prepend(lines, label) = content(lines, label) + "\n" + lines.join
49
+
50
+ def content(lines, label) = builder.call(lines, label: label)
50
51
  end
51
52
  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.4.0
4
+ version: 12.0.0
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-11-14 00:00:00.000000000 Z
31
+ date: 2021-04-17 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: refinements
@@ -36,238 +36,28 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '7.14'
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.14'
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'
75
- - !ruby/object:Gem::Dependency
76
- name: bundler-audit
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '0.7'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.7'
89
- - !ruby/object:Gem::Dependency
90
- name: bundler-leak
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '0.2'
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '0.2'
103
- - !ruby/object:Gem::Dependency
104
- name: climate_control
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '0.1'
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - "~>"
115
- - !ruby/object:Gem::Version
116
- version: '0.1'
117
- - !ruby/object:Gem::Dependency
118
- name: guard-rspec
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '4.7'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '4.7'
131
- - !ruby/object:Gem::Dependency
132
- name: pry
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '0.13'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '0.13'
145
- - !ruby/object:Gem::Dependency
146
- name: pry-byebug
147
- requirement: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - "~>"
150
- - !ruby/object:Gem::Version
151
- version: '3.9'
152
- type: :development
153
- prerelease: false
154
- version_requirements: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '3.9'
159
- - !ruby/object:Gem::Dependency
160
- name: rake
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
164
- - !ruby/object:Gem::Version
165
- version: '13.0'
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - "~>"
171
- - !ruby/object:Gem::Version
172
- version: '13.0'
173
- - !ruby/object:Gem::Dependency
174
- name: reek
175
- requirement: !ruby/object:Gem::Requirement
176
- requirements:
177
- - - "~>"
178
- - !ruby/object:Gem::Version
179
- version: '6.0'
180
- type: :development
181
- prerelease: false
182
- version_requirements: !ruby/object:Gem::Requirement
183
- requirements:
184
- - - "~>"
185
- - !ruby/object:Gem::Version
186
- version: '6.0'
187
- - !ruby/object:Gem::Dependency
188
- name: rspec
189
- requirement: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - "~>"
192
- - !ruby/object:Gem::Version
193
- version: '3.10'
194
- type: :development
195
- prerelease: false
196
- version_requirements: !ruby/object:Gem::Requirement
197
- requirements:
198
- - - "~>"
199
- - !ruby/object:Gem::Version
200
- version: '3.10'
201
- - !ruby/object:Gem::Dependency
202
- name: rubocop
203
- requirement: !ruby/object:Gem::Requirement
204
- requirements:
205
- - - "~>"
206
- - !ruby/object:Gem::Version
207
- version: '1.3'
208
- type: :development
209
- prerelease: false
210
- version_requirements: !ruby/object:Gem::Requirement
211
- requirements:
212
- - - "~>"
213
- - !ruby/object:Gem::Version
214
- version: '1.3'
215
- - !ruby/object:Gem::Dependency
216
- name: rubocop-performance
217
- requirement: !ruby/object:Gem::Requirement
218
- requirements:
219
- - - "~>"
220
- - !ruby/object:Gem::Version
221
- version: '1.8'
222
- type: :development
223
- prerelease: false
224
- version_requirements: !ruby/object:Gem::Requirement
225
- requirements:
226
- - - "~>"
227
- - !ruby/object:Gem::Version
228
- version: '1.8'
229
- - !ruby/object:Gem::Dependency
230
- name: rubocop-rake
231
- requirement: !ruby/object:Gem::Requirement
232
- requirements:
233
- - - "~>"
234
- - !ruby/object:Gem::Version
235
- version: '0.5'
236
- type: :development
237
- prerelease: false
238
- version_requirements: !ruby/object:Gem::Requirement
239
- requirements:
240
- - - "~>"
241
- - !ruby/object:Gem::Version
242
- version: '0.5'
243
- - !ruby/object:Gem::Dependency
244
- name: rubocop-rspec
245
- requirement: !ruby/object:Gem::Requirement
246
- requirements:
247
- - - "~>"
248
- - !ruby/object:Gem::Version
249
- version: '2.0'
250
- type: :development
251
- prerelease: false
252
- version_requirements: !ruby/object:Gem::Requirement
253
- requirements:
254
- - - "~>"
255
- - !ruby/object:Gem::Version
256
- version: '2.0'
257
- - !ruby/object:Gem::Dependency
258
- name: simplecov
259
- requirement: !ruby/object:Gem::Requirement
260
- requirements:
261
- - - "~>"
262
- - !ruby/object:Gem::Version
263
- version: '0.19'
264
- type: :development
265
- prerelease: false
266
- version_requirements: !ruby/object:Gem::Requirement
267
- requirements:
268
- - - "~>"
269
- - !ruby/object:Gem::Version
270
- version: '0.19'
60
+ version: '7.0'
271
61
  description:
272
62
  email:
273
63
  - brooke@alchemists.io
@@ -283,8 +73,16 @@ files:
283
73
  - bin/tocer
284
74
  - lib/tocer.rb
285
75
  - lib/tocer/builder.rb
286
- - lib/tocer/cli.rb
287
- - 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
288
86
  - lib/tocer/elements/comment_block.rb
289
87
  - lib/tocer/identity.rb
290
88
  - lib/tocer/parsers/header.rb
@@ -311,14 +109,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
311
109
  requirements:
312
110
  - - "~>"
313
111
  - !ruby/object:Gem::Version
314
- version: '2.7'
112
+ version: '3.0'
315
113
  required_rubygems_version: !ruby/object:Gem::Requirement
316
114
  requirements:
317
115
  - - ">="
318
116
  - !ruby/object:Gem::Version
319
117
  version: '0'
320
118
  requirements: []
321
- rubygems_version: 3.1.4
119
+ rubygems_version: 3.2.16
322
120
  signing_key:
323
121
  specification_version: 4
324
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