tocer 11.1.0 → 12.0.0

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: 4ec19b457ac3dc565f57323110cbaddd9132578a736deb9553a70af366a97077
4
- data.tar.gz: 95f1af9f69fb6f618f3d108b4611d96ee91efe4d64ddd54ebce08e67064cffb4
3
+ metadata.gz: '096af23217cee6fd1f0fc3193a733eae8fff2cc586bce9058fde6d67c409aca3'
4
+ data.tar.gz: e491575b96fe2dfdad444015d228cd5150d2e8a2aebd85f98977fed6b598e268
5
5
  SHA512:
6
- metadata.gz: acdf181698830f77b2e9b5fd519bb359b7d1ae3492f7cecc65b65af39030102b00a64d93fc95d500ca875198c080b5092822f89ff3a0f5bf4fd2b3baa1f99fe4
7
- data.tar.gz: 68b931c8521026959aa12fee39d282b35ac987a1f4b9a2c9236413fb6fd56f3fed6c83815680fdd2e0f2873699bb45e4ea86d7586d91b5748268f59501498f8c
6
+ metadata.gz: 51f72f12821e8101fac9ce9f062879756493916725d4bc5c25129e9a4b13338f5b524a51ce66a4f9387404499ea8baa3d7eb1db764ef58315af9f1c9bc9ee37e
7
+ data.tar.gz: 5ea05ed97e8a350c3a32470f7627e47e60d2be56368da9e738ea5e9a302a5998dae9ea93706f9e7f9c19609b0f7d98dd324a621ea0eb3a2b6fc36fb410e8c766
checksums.yaml.gz.sig CHANGED
@@ -1,2 +1 @@
1
- �/R=K]��/�k>.+i�#b��?�Z'IRZ��ק�p$}X��4gt��1�#z����nR����iQ�0�idžGG1����Zh
2
- �o/���Dw��%{<�����(*\�?R[#gݒ���*2�N�uba�󛕅�� �3T_Jn��Rx@�P��TU�C0
1
+ z����dZ�D���������F tG��״)\R�m%�b���&|��_@ ��^�0����|��]����({NArc�����FC��=Fv���{�S��\&���ERsE��L ���d�ɒ����s\xm��{
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 = "11.1.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,}/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).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: 11.1.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: 2021-01-20 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
@@ -58,20 +58,6 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '7.0'
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
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
@@ -122,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
116
  - !ruby/object:Gem::Version
123
117
  version: '0'
124
118
  requirements: []
125
- rubygems_version: 3.2.5
119
+ rubygems_version: 3.2.16
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