All Files
(
100.0%
covered at
6.5
hits/line
)
21 files in total.
264 relevant lines,
264 lines covered and
0 lines missed.
(
100.0%
)
12 total branches,
12 branches covered and
0 branches missed.
(
100.0%
)
-
# frozen_string_literal: true
-
-
1
require "zeitwerk"
-
-
1
Zeitwerk::Loader.new.then do |loader|
-
1
loader.inflector.inflect "cli" => "CLI"
-
1
loader.tag = File.basename __FILE__, ".rb"
-
1
loader.push_dir __dir__
-
1
loader.setup
-
end
-
-
# Main namespace.
-
1
module Pragmater
-
1
def self.loader registry = Zeitwerk::Registry
-
4
@loader ||= registry.loaders.each.find { |loader| loader.tag == File.basename(__FILE__, ".rb") }
-
end
-
end
-
# frozen_string_literal: true
-
-
1
Gem::Specification.new do |spec|
-
1
spec.name = "pragmater"
-
1
spec.version = "16.5.0"
-
1
spec.authors = ["Brooke Kuhlmann"]
-
1
spec.email = ["brooke@alchemists.io"]
-
1
spec.homepage = "https://alchemists.io/projects/pragmater"
-
1
spec.summary = "A command line interface for managing pragma comments."
-
1
spec.license = "Hippocratic-2.1"
-
-
1
spec.metadata = {
-
"bug_tracker_uri" => "https://github.com/bkuhlmann/pragmater/issues",
-
"changelog_uri" => "https://alchemists.io/projects/pragmater/versions",
-
"homepage_uri" => "https://alchemists.io/projects/pragmater",
-
"funding_uri" => "https://github.com/sponsors/bkuhlmann",
-
"label" => "Pragmater",
-
"rubygems_mfa_required" => "true",
-
"source_code_uri" => "https://github.com/bkuhlmann/pragmater"
-
}
-
-
1
spec.signing_key = Gem.default_key_path
-
1
spec.cert_chain = [Gem.default_cert_path]
-
-
1
spec.required_ruby_version = ">= 3.4"
-
1
spec.add_dependency "cogger", "~> 1.0"
-
1
spec.add_dependency "containable", "~> 1.1"
-
1
spec.add_dependency "dry-schema", "~> 1.13"
-
1
spec.add_dependency "etcher", "~> 3.0"
-
1
spec.add_dependency "infusible", "~> 4.0"
-
1
spec.add_dependency "refinements", "~> 13.6"
-
1
spec.add_dependency "runcom", "~> 12.0"
-
1
spec.add_dependency "sod", "~> 1.5"
-
1
spec.add_dependency "spek", "~> 4.0"
-
1
spec.add_dependency "zeitwerk", "~> 2.7"
-
-
1
spec.bindir = "exe"
-
1
spec.executables << "pragmater"
-
1
spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
-
1
spec.files = Dir["*.gemspec", "lib/**/*"]
-
end
-
# frozen_string_literal: true
-
-
1
require "sod"
-
-
1
module Pragmater
-
1
module CLI
-
1
module Actions
-
# Stores pragma comments.
-
1
class Comment < Sod::Action
-
1
include Dependencies[:settings]
-
-
1
description "Set pragma comments."
-
-
1
on %w[-c --comments], argument: "[a,b,c]"
-
-
18
default { Container[:settings].comments }
-
-
1
def call(comments = default) = settings.comments = Array(comments)
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "sod"
-
-
1
module Pragmater
-
1
module CLI
-
1
module Actions
-
# Stores file patterns.
-
1
class Pattern < Sod::Action
-
1
include Dependencies[:settings]
-
-
1
description "Set file patterns."
-
-
1
on %w[-p --patterns], argument: "[a,b,c]"
-
-
18
default { Container[:settings].patterns }
-
-
1
def call(patterns = default) = settings.patterns = Array(patterns)
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "sod"
-
-
1
module Pragmater
-
1
module CLI
-
1
module Actions
-
# Stores root path.
-
1
class Root < Sod::Action
-
1
include Dependencies[:settings]
-
-
1
description "Set root directory."
-
-
1
on %w[-r --root], argument: "[PATH]"
-
-
17
default { Container[:settings].root_dir }
-
-
1
def call(path = default) = settings.root_dir = Pathname(path)
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "sod"
-
-
1
module Pragmater
-
1
module CLI
-
1
module Commands
-
# Inserts pragmas.
-
1
class Insert < Sod::Command
-
1
include Dependencies[:settings, :io]
-
-
1
handle "insert"
-
-
1
description "Insert pragma comments."
-
-
1
on Actions::Root
-
1
on Actions::Comment
-
1
on Actions::Pattern
-
-
1
def initialize(handler: Inserter.new, **)
-
7
super(**)
-
7
@handler = handler
-
end
-
-
3
def call = handler.call { |path| io.puts path }
-
-
1
private
-
-
1
attr_reader :handler
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "sod"
-
-
1
module Pragmater
-
1
module CLI
-
1
module Commands
-
# Removes pragmas.
-
1
class Remove < Sod::Command
-
1
include Dependencies[:settings, :io]
-
-
1
handle "remove"
-
-
1
description "Remove pragma comments."
-
-
1
on Actions::Root
-
1
on Actions::Comment
-
1
on Actions::Pattern
-
-
1
def initialize(handler: Remover.new, **)
-
7
super(**)
-
7
@handler = handler
-
end
-
-
3
def call = handler.call { |path| io.puts path }
-
-
1
private
-
-
1
attr_reader :handler
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "sod"
-
-
1
module Pragmater
-
1
module CLI
-
# The main Command Line Interface (CLI) object.
-
1
class Shell
-
1
include Dependencies[:defaults_path, :xdg_config, :specification]
-
-
1
def initialize(context: Sod::Context, dsl: Sod, **)
-
5
super(**)
-
5
@context = context
-
5
@dsl = dsl
-
end
-
-
1
def call(...) = cli.call(...)
-
-
1
private
-
-
1
attr_reader :context, :dsl
-
-
1
def cli
-
5
context = build_context
-
-
5
dsl.new :pragmater, banner: specification.banner do
-
5
on(Sod::Prefabs::Commands::Config, context:)
-
5
on Commands::Insert
-
5
on Commands::Remove
-
5
on(Sod::Prefabs::Actions::Version, context:)
-
5
on Sod::Prefabs::Actions::Help, self
-
end
-
end
-
-
1
def build_context
-
5
context[defaults_path:, xdg_config:, version_label: specification.labeled_version]
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "dry/schema"
-
1
require "etcher"
-
-
1
Dry::Schema.load_extensions :monads
-
-
1
module Pragmater
-
1
module Configuration
-
1
Contract = Dry::Schema.Params do
-
1
required(:comments).array :string
-
1
required(:patterns).array :string
-
1
required(:root_dir).filled Etcher::Types::Pathname
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Configuration
-
# Defines the content of the configuration for use throughout the gem.
-
1
Model = Struct.new :comments, :patterns, :root_dir do
-
1
def initialize(**)
-
30
super
-
30
self[:comments] = Array comments
-
30
self[:patterns] = Array patterns
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "infusible"
-
-
1
module Pragmater
-
1
Dependencies = Infusible[Container]
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Formatters
-
# Formats general pragmas in a consistent manner.
-
1
class General
-
1
PATTERN = /
-
\A # Start of line.
-
\# # Start of comment.
-
\s? # Space - optional.
-
\w+ # Key - One or more word characters only.
-
: # Delimiter.
-
\s? # Space - optional.
-
[\w-]+ # Value - One or more word or dash characters.
-
\Z # End of line.
-
/x
-
-
1
def initialize string, pattern: PATTERN
-
60
@string = string
-
60
@pattern = pattern
-
end
-
-
1
def call
-
60
else: 45
then: 15
return string unless string.match? pattern
-
-
90
string.split(":").then { |key, value| "# #{key.gsub(/\#\s?/, "")}: #{value.strip}" }
-
end
-
-
1
private
-
-
1
attr_reader :string, :pattern
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Formatters
-
# Formats all pragmas in a consistent manner.
-
1
class Main
-
1
FORMATTERS = [General, Shebang].freeze
-
-
3
PATTERN = FORMATTERS.map { |formatter| formatter::PATTERN }
-
1
.then { |patterns| Regexp.union(*patterns) }
-
.freeze
-
-
1
def initialize string, formatters: FORMATTERS
-
53
@string = string
-
53
@formatters = formatters
-
end
-
-
107
def call = formatters.reduce(string) { |pragma, formatter| formatter.new(pragma).call }
-
-
1
private
-
-
1
attr_reader :string, :formatters
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Formatters
-
# Formats shebang pragmas in a consistent manner.
-
1
class Shebang
-
1
PATTERN = %r(\A\#!\s?/.*ruby\Z)
-
-
1
def initialize string, pattern: PATTERN
-
58
@string = string
-
58
@pattern = pattern
-
end
-
-
1
def call
-
58
else: 12
then: 46
return string unless string.match? pattern
-
-
24
string.split("!").then { |octothorpe, path| "#{octothorpe}! #{path.strip}" }
-
end
-
-
1
private
-
-
1
attr_reader :string, :pattern
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "refinements/pathname"
-
-
1
module Pragmater
-
# Inserts pragma comments.
-
1
class Inserter
-
1
include Dependencies[:settings]
-
-
1
using Refinements::Pathname
-
-
1
def initialize(parser: Parsers::File.new, **)
-
15
@parser = parser
-
15
super(**)
-
end
-
-
1
def call
-
11
Pathname(settings.root_dir).files("{#{settings.patterns.join ","}}").map do |path|
-
8
then: 3
else: 5
yield path if block_given?
-
8
path.write parser.call(path, settings.comments, action: :insert).join
-
end
-
end
-
-
1
private
-
-
1
attr_reader :parser
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Parsers
-
# Manages pragma comments.
-
1
class Comments
-
1
def initialize older, newer, formatter: Formatters::Main
-
33
@formatter = formatter
-
33
@older = format older
-
33
@newer = format newer
-
end
-
-
1
def insert = older.union(newer)
-
-
1
def remove = older - older.intersection(newer)
-
-
1
private
-
-
1
attr_reader :formatter, :older, :newer
-
-
51
def format(pragmas) = Array(pragmas).map { |pragma| formatter.new(pragma).call }
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Parsers
-
# Parses a file into pragma comment and body lines.
-
1
class File
-
1
def initialize pattern: Formatters::Main::PATTERN,
-
comments: Comments,
-
processor: Processors::Handler.new
-
32
@pattern = pattern
-
32
@comments = comments
-
32
@processor = processor
-
end
-
-
1
def call path, new_comments, action:
-
20
path.each_line
-
14
.partition { |line| line.match? pattern }
-
.then do |old_comments, body|
-
20
processor.call action, wrap_in_new_line(old_comments, new_comments, action), body
-
end
-
end
-
-
1
private
-
-
1
attr_reader :pattern, :comments, :processor
-
-
1
def wrap_in_new_line old_comments, new_comments, action
-
33
comments.new(old_comments, new_comments).public_send(action).map { |line| "#{line}\n" }
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Processors
-
# Handles the insertion or removal of pragma comments.
-
1
class Handler
-
1
DEFAULTS = {insert: Inserter, remove: Remover}.freeze
-
-
1
def initialize processors: DEFAULTS
-
35
@processors = processors
-
end
-
-
1
def call(action, comments, body) = processors.fetch(action).new(comments, body).call
-
-
1
private
-
-
1
attr_reader :processors
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Processors
-
# Inserts new pragma comments.
-
1
class Inserter
-
1
def initialize comments, body
-
16
@comments = comments
-
16
@body = body
-
end
-
-
1
def call
-
16
body.first.then do |first|
-
16
else: 12
then: 4
comments.append "\n" unless first == "\n" || body.empty?
-
16
comments + body
-
end
-
end
-
-
1
private
-
-
1
attr_reader :comments, :body
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module Pragmater
-
1
module Processors
-
# Removes existing pragma comments.
-
1
class Remover
-
1
def initialize comments, body
-
12
@comments = comments
-
12
@body = body
-
end
-
-
1
def call
-
12
body.first.then do |first_line|
-
12
then: 3
else: 9
body.delete_at 0 if first_line == "\n" && comments.empty?
-
12
comments + body
-
end
-
end
-
-
1
private
-
-
1
attr_reader :comments, :body
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require "refinements/pathname"
-
-
1
module Pragmater
-
# Removes pragma comments.
-
1
class Remover
-
1
include Dependencies[:settings]
-
-
1
using Refinements::Pathname
-
-
1
def initialize(parser: Parsers::File.new, **)
-
10
@parser = parser
-
10
super(**)
-
end
-
-
1
def call
-
6
Pathname(settings.root_dir).files("{#{settings.patterns.join ","}}").map do |path|
-
5
then: 3
else: 2
yield path if block_given?
-
5
path.write parser.call(path, settings.comments, action: :remove).join
-
end
-
end
-
-
1
private
-
-
1
attr_reader :parser
-
end
-
end