yalphabetize 0.0.0 → 0.1.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: e77cd0148a5d6e1d6c31b90a12d9d7cf85fbccea7e5efa6f4240c6f60759e69e
4
- data.tar.gz: d1c1b0c394f0c35a23b41fb05d1ebd39cfcf53f1bbc8c316a7dac4ee3d6fc046
3
+ metadata.gz: b507c005e0407945299b4d297a443fe5f019f876e90bba19e930630c11be8881
4
+ data.tar.gz: 624a56393c2cf67a529ed4542f66a8308c409739c216052d62b4e75997b8b5eb
5
5
  SHA512:
6
- metadata.gz: 3478dcee26fe4f22d25bc81cc6f9bc874c8af9599c76971ae6c51b619c5ee6215600c161d34b36714f27e5a1b579c643f8679a770ce5e2470bf89d17203be085
7
- data.tar.gz: a1bdafe93d32883ebbd8ed601a83f5521ec7519597a02e8f0f6f325c17bb502b291350529c94dfd5b709e6eb83d8ace98a48c12a88a3c2e327e92b5b62341078
6
+ metadata.gz: b77dd2c3d7e92e97e7c7d16cdd9359c6bd5b7084fe7006651a03d3416de73429403f17fcbd0b45f2d09225b842cb4bfb83adb9f48519b3ceb32853339e356e48
7
+ data.tar.gz: 27495a87a0594f9c33751a7f48e67234b1d7e8067b2e095d5dd90d162237fb309243d0c3c0617795638f1f4b837cf478be1d3969b3ff245668bf45645bca5724
data/bin/yalphabetize ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'yalphabetize/reader'
5
+ require 'yalphabetize/alphabetizer'
6
+ require 'yalphabetize/writer'
7
+ require 'yalphabetize/offence_detector'
8
+ require 'yalphabetize/yaml_finder'
9
+ require 'yalphabetize/logger'
10
+ require 'yalphabetizer'
11
+
12
+ reader = Yalphabetize::Reader
13
+ finder = Yalphabetize::YamlFinder.new
14
+ alphabetizer = Yalphabetize::Alphabetizer
15
+ writer = Yalphabetize::Writer
16
+ offence_detector = Yalphabetize::OffenceDetector
17
+ logger = Yalphabetize::Logger.new
18
+
19
+ exit Yalphabetizer.call(
20
+ ARGV,
21
+ reader: reader,
22
+ finder: finder,
23
+ alphabetizer: alphabetizer,
24
+ writer: writer,
25
+ offence_detector: offence_detector,
26
+ logger: logger
27
+ )
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yalphabetize
4
+ class Alphabetizer
5
+ def initialize(stream_node)
6
+ @stream_node = stream_node
7
+ end
8
+
9
+ def call
10
+ alphabetize(stream_node)
11
+ stream_node
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :stream_node
17
+
18
+ def alphabetize(node)
19
+ if node.mapping?
20
+ alphabetize_children(node)
21
+ unpair_children(node)
22
+ end
23
+
24
+ node.children&.each { |child_node| alphabetize(child_node) }
25
+ end
26
+
27
+ def alphabetize_children(node)
28
+ node.children.sort_by! { |key, _value| key.value }
29
+ end
30
+
31
+ def unpair_children(node)
32
+ children_clone = node.children.dup
33
+
34
+ children_clone.each do |slice|
35
+ node.children.push(*slice)
36
+ node.children.shift
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,76 @@
1
+ module Yalphabetize
2
+ class Logger
3
+ def initialize
4
+ @inspected_count = 0
5
+ @offences = {}
6
+ end
7
+
8
+ def task_summary(file_paths)
9
+ puts "Inspecting #{file_paths.size} YAML files"
10
+ end
11
+
12
+ def log_offence(file_path)
13
+ @inspected_count += 1
14
+ offences[file_path] = :detected
15
+ print red 'O'
16
+ end
17
+
18
+ def log_no_offence
19
+ @inspected_count += 1
20
+ print green '.'
21
+ end
22
+
23
+ def log_inspected_count
24
+ puts "\nInspected: #{inspected_count}"
25
+ end
26
+
27
+ def list_offences
28
+ puts send(list_offences_color, "Offences: #{offences.size}")
29
+
30
+ @offences.each do |file_path, status|
31
+ case status
32
+ when :detected
33
+ puts yellow file_path
34
+ when :corrected
35
+ puts("#{yellow(file_path)} #{green("CORRECTED")}")
36
+ end
37
+ end
38
+ end
39
+
40
+ def offences?
41
+ @offences.any?
42
+ end
43
+
44
+ def log_correction(file_path)
45
+ offences[file_path] = :corrected
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :offences, :inspected_count
51
+
52
+ def list_offences_color
53
+ if offences?
54
+ :red
55
+ else
56
+ :green
57
+ end
58
+ end
59
+
60
+ def red(string)
61
+ with_color(31, string)
62
+ end
63
+
64
+ def yellow(string)
65
+ with_color(33, string)
66
+ end
67
+
68
+ def green(string)
69
+ with_color(32, string)
70
+ end
71
+
72
+ def with_color(color, string)
73
+ "\e[#{color}m#{string}\e[0m"
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yalphabetize
4
+ class OffenceDetector
5
+ def initialize(stream_node)
6
+ @stream_node = stream_node
7
+ end
8
+
9
+ def offences?
10
+ !alphabetized?(stream_node)
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :stream_node
16
+
17
+ def alphabetized?(node)
18
+ return false if node.mapping? && !alphabetized_children?(node)
19
+
20
+ if node.children
21
+ each_child_also_alphabetized?(node.children)
22
+ else
23
+ true
24
+ end
25
+ end
26
+
27
+ def alphabetized_children?(node)
28
+ node.children.each_cons(2).all? { |a, b| (a.first.value <=> b.first.value) <= 0 }
29
+ end
30
+
31
+ def each_child_also_alphabetized?(children)
32
+ children.flatten&.inject(true) { |bool, child_node| bool && alphabetized?(child_node) }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'psych'
4
+
5
+ module Yalphabetize
6
+ class Reader
7
+ def initialize(path)
8
+ @path = path
9
+ end
10
+
11
+ def to_ast
12
+ transform(stream_node)
13
+ stream_node
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :path
19
+
20
+ def stream_node
21
+ @stream_node ||= Psych.parse_stream File.read(path)
22
+ end
23
+
24
+ def transform(node)
25
+ node.children&.each(&method(:transform))
26
+
27
+ return unless node.mapping?
28
+
29
+ pair_up_children(node)
30
+ end
31
+
32
+ def pair_up_children(node)
33
+ children_clone = node.children.dup
34
+
35
+ children_clone.each_slice(2) do |slice|
36
+ node.children.push(slice)
37
+ node.children.shift
38
+ node.children.shift
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yalphabetize
4
+ class Writer
5
+ def initialize(stream_node, path)
6
+ @stream_node = stream_node
7
+ @path = path
8
+ end
9
+
10
+ def call
11
+ File.open(path, 'w') do |file|
12
+ file.write(stream_node.to_yaml)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :stream_node, :path
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yalphabetize
4
+ class YamlFinder
5
+ def paths
6
+ @_paths ||= begin
7
+ return if `sh -c 'command -v git'`.empty?
8
+
9
+ output, _error, status = Open3.capture3(
10
+ 'git', 'ls-files', '-z', './**/*.yml',
11
+ '--exclude-standard', '--others', '--cached', '--modified'
12
+ )
13
+
14
+ return unless status.success?
15
+
16
+ output.split("\0").uniq.map { |git_file| "#{Dir.pwd}/#{git_file}" }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+ require 'pry'
5
+
6
+ class Yalphabetizer
7
+ def self.call(args = [], **options)
8
+ new(args, options).call
9
+ end
10
+
11
+ def initialize(args, options)
12
+ @args = args
13
+
14
+ @reader = options[:reader]
15
+ @finder = options[:finder]
16
+ @alphabetizer = options[:alphabetizer]
17
+ @writer = options[:writer]
18
+ @offence_detector = options[:offence_detector]
19
+ @logger = options[:logger]
20
+ end
21
+
22
+ def call
23
+ logger.task_summary(file_paths)
24
+
25
+ file_paths.each do |file_path|
26
+ unsorted_stream_node = reader.new(file_path).to_ast
27
+
28
+ if offences?(unsorted_stream_node)
29
+ logger.log_offence(file_path)
30
+ autocorrect(unsorted_stream_node, file_path) if autocorrect?
31
+ else
32
+ logger.log_no_offence
33
+ end
34
+ end
35
+
36
+ logger.log_inspected_count
37
+ logger.list_offences
38
+
39
+ logger.offences? ? 1 : 0
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :args, :reader, :finder, :alphabetizer, :writer, :offence_detector, :logger
45
+
46
+ def file_paths
47
+ finder.paths
48
+ end
49
+
50
+ def autocorrect?
51
+ return true if args.include? '-a'
52
+ return true if args.include? '-autocorrect'
53
+
54
+ false
55
+ end
56
+
57
+ def autocorrect(unsorted_stream_node, file_path)
58
+ sorted_stream_node = alphabetizer.new(unsorted_stream_node).call
59
+ writer.new(sorted_stream_node, file_path).call
60
+ logger.log_correction(file_path)
61
+ end
62
+
63
+ def offences?(stream_node)
64
+ offence_detector.new(stream_node).offences?
65
+ end
66
+ end
metadata CHANGED
@@ -1,22 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yalphabetize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Jenkins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-21 00:00:00.000000000 Z
11
+ date: 2021-05-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
15
- executables: []
15
+ executables:
16
+ - yalphabetize
16
17
  extensions: []
17
18
  extra_rdoc_files: []
18
19
  files:
19
- - lib/yalphabetize.rb
20
+ - bin/yalphabetize
21
+ - lib/yalphabetize/alphabetizer.rb
22
+ - lib/yalphabetize/logger.rb
23
+ - lib/yalphabetize/offence_detector.rb
24
+ - lib/yalphabetize/reader.rb
25
+ - lib/yalphabetize/writer.rb
26
+ - lib/yalphabetize/yaml_finder.rb
27
+ - lib/yalphabetizer.rb
20
28
  homepage:
21
29
  licenses: []
22
30
  metadata: {}
@@ -35,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
35
43
  - !ruby/object:Gem::Version
36
44
  version: '0'
37
45
  requirements: []
38
- rubygems_version: 3.0.3
46
+ rubygems_version: 3.1.4
39
47
  signing_key:
40
48
  specification_version: 4
41
49
  summary: Alphabetize your YAML files
data/lib/yalphabetize.rb DELETED
@@ -1,8 +0,0 @@
1
- class Yalphabetize
2
- def self.call
3
- {
4
- a: :b,
5
- c: :d
6
- }
7
- end
8
- end