tocer 10.4.1 → 12.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 452eb2486a977b33b270cb7b27a6e8727bf041c81688109e5224aaf5ef979ad5
4
- data.tar.gz: '0197473f62a7ced04811202ab00ec744d8ffb0057c1863960fd7fc3f604d5cde'
3
+ metadata.gz: fbb0b5122d22bc49315768eaa8da1ad803be7a116dbbc628d0cf21fc0e7f3e5e
4
+ data.tar.gz: e271feacaaa9643cc05d656f32ac00dfba47a7f7a63cfa4c330e4f33188d4ca0
5
5
  SHA512:
6
- metadata.gz: 4e27b3e32c8d35da618c53e84a78f034a80b5d18fcbc5cb695d82f2d7ff872a41451d0d1fa6f26ab3c89110fc93c714919a88000a96449a58e6e83097e1471c7
7
- data.tar.gz: 3be7dff91e1d60b442a35f34f21b91c6570b73ae81dc7a080444a3c91c2dda99bc84f9ac08eec090d29af438accaab1cfdfc6328df2da8aa9c465c3835a6d126
6
+ metadata.gz: fbfd2fcf7ae70d445c41fef7d1f190f43b23f8af12985e2ad0c75996e7a38795423b620f0865e48171637d545914c95fc8020244413ef299a3af112215562448
7
+ data.tar.gz: f24e6608ed56a388c0ec4e5acf2d906138c86c55002b8d17fcfc85a7048f490a0eaf631bb38972eb60b634ed69a4b180b22740840f12d88c7bcea586b6119d61
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,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.1"
8
+ VERSION = "12.0.1"
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
@@ -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.1
4
+ version: 12.0.1
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-21 00:00:00.000000000 Z
31
+ date: 2021-04-18 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: refinements
@@ -36,266 +36,28 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '7.15'
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.15'
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: gemsmith
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '14.8'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '14.8'
131
- - !ruby/object:Gem::Dependency
132
- name: git-lint
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '1.3'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '1.3'
145
- - !ruby/object:Gem::Dependency
146
- name: guard-rspec
147
- requirement: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - "~>"
150
- - !ruby/object:Gem::Version
151
- version: '4.7'
152
- type: :development
153
- prerelease: false
154
- version_requirements: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '4.7'
159
- - !ruby/object:Gem::Dependency
160
- name: pry
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
164
- - !ruby/object:Gem::Version
165
- version: '0.13'
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - "~>"
171
- - !ruby/object:Gem::Version
172
- version: '0.13'
173
- - !ruby/object:Gem::Dependency
174
- name: pry-byebug
175
- requirement: !ruby/object:Gem::Requirement
176
- requirements:
177
- - - "~>"
178
- - !ruby/object:Gem::Version
179
- version: '3.9'
180
- type: :development
181
- prerelease: false
182
- version_requirements: !ruby/object:Gem::Requirement
183
- requirements:
184
- - - "~>"
185
- - !ruby/object:Gem::Version
186
- version: '3.9'
187
- - !ruby/object:Gem::Dependency
188
- name: rake
189
- requirement: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - "~>"
192
- - !ruby/object:Gem::Version
193
- version: '13.0'
194
- type: :development
195
- prerelease: false
196
- version_requirements: !ruby/object:Gem::Requirement
197
- requirements:
198
- - - "~>"
199
- - !ruby/object:Gem::Version
200
- version: '13.0'
201
- - !ruby/object:Gem::Dependency
202
- name: reek
203
- requirement: !ruby/object:Gem::Requirement
204
- requirements:
205
- - - "~>"
206
- - !ruby/object:Gem::Version
207
- version: '6.0'
208
- type: :development
209
- prerelease: false
210
- version_requirements: !ruby/object:Gem::Requirement
211
- requirements:
212
- - - "~>"
213
- - !ruby/object:Gem::Version
214
- version: '6.0'
215
- - !ruby/object:Gem::Dependency
216
- name: rspec
217
- requirement: !ruby/object:Gem::Requirement
218
- requirements:
219
- - - "~>"
220
- - !ruby/object:Gem::Version
221
- version: '3.10'
222
- type: :development
223
- prerelease: false
224
- version_requirements: !ruby/object:Gem::Requirement
225
- requirements:
226
- - - "~>"
227
- - !ruby/object:Gem::Version
228
- version: '3.10'
229
- - !ruby/object:Gem::Dependency
230
- name: rubocop
231
- requirement: !ruby/object:Gem::Requirement
232
- requirements:
233
- - - "~>"
234
- - !ruby/object:Gem::Version
235
- version: '1.3'
236
- type: :development
237
- prerelease: false
238
- version_requirements: !ruby/object:Gem::Requirement
239
- requirements:
240
- - - "~>"
241
- - !ruby/object:Gem::Version
242
- version: '1.3'
243
- - !ruby/object:Gem::Dependency
244
- name: rubocop-performance
245
- requirement: !ruby/object:Gem::Requirement
246
- requirements:
247
- - - "~>"
248
- - !ruby/object:Gem::Version
249
- version: '1.8'
250
- type: :development
251
- prerelease: false
252
- version_requirements: !ruby/object:Gem::Requirement
253
- requirements:
254
- - - "~>"
255
- - !ruby/object:Gem::Version
256
- version: '1.8'
257
- - !ruby/object:Gem::Dependency
258
- name: rubocop-rake
259
- requirement: !ruby/object:Gem::Requirement
260
- requirements:
261
- - - "~>"
262
- - !ruby/object:Gem::Version
263
- version: '0.5'
264
- type: :development
265
- prerelease: false
266
- version_requirements: !ruby/object:Gem::Requirement
267
- requirements:
268
- - - "~>"
269
- - !ruby/object:Gem::Version
270
- version: '0.5'
271
- - !ruby/object:Gem::Dependency
272
- name: rubocop-rspec
273
- requirement: !ruby/object:Gem::Requirement
274
- requirements:
275
- - - "~>"
276
- - !ruby/object:Gem::Version
277
- version: '2.0'
278
- type: :development
279
- prerelease: false
280
- version_requirements: !ruby/object:Gem::Requirement
281
- requirements:
282
- - - "~>"
283
- - !ruby/object:Gem::Version
284
- version: '2.0'
285
- - !ruby/object:Gem::Dependency
286
- name: simplecov
287
- requirement: !ruby/object:Gem::Requirement
288
- requirements:
289
- - - "~>"
290
- - !ruby/object:Gem::Version
291
- version: '0.19'
292
- type: :development
293
- prerelease: false
294
- version_requirements: !ruby/object:Gem::Requirement
295
- requirements:
296
- - - "~>"
297
- - !ruby/object:Gem::Version
298
- version: '0.19'
60
+ version: '7.0'
299
61
  description:
300
62
  email:
301
63
  - brooke@alchemists.io
@@ -311,8 +73,16 @@ files:
311
73
  - bin/tocer
312
74
  - lib/tocer.rb
313
75
  - lib/tocer/builder.rb
314
- - lib/tocer/cli.rb
315
- - 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
316
86
  - lib/tocer/elements/comment_block.rb
317
87
  - lib/tocer/identity.rb
318
88
  - lib/tocer/parsers/header.rb
@@ -339,14 +109,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
339
109
  requirements:
340
110
  - - "~>"
341
111
  - !ruby/object:Gem::Version
342
- version: '2.7'
112
+ version: '3.0'
343
113
  required_rubygems_version: !ruby/object:Gem::Requirement
344
114
  requirements:
345
115
  - - ">="
346
116
  - !ruby/object:Gem::Version
347
117
  version: '0'
348
118
  requirements: []
349
- rubygems_version: 3.1.4
119
+ rubygems_version: 3.2.16
350
120
  signing_key:
351
121
  specification_version: 4
352
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