findyml 0.1.1 → 0.2.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: 964b255cb131f3caf96e5365470ecca91efdbfacead42d4b12bdba79ac461dcd
4
- data.tar.gz: 1d6660d1b928dd4936a346f67d3364fcde388b681de188a105bfa8011dab0024
3
+ metadata.gz: f4d5da18159d29c04d47739dd1c4761bcbe6b6cc0586bc6b46af1e2b08ab2b0f
4
+ data.tar.gz: 3133810f4ca036c7b5f8108eba68c11906e30864c732bcb37f2313363ca1d680
5
5
  SHA512:
6
- metadata.gz: b12382da9ac27279eda62b894928b23896c4f45dbdbec81203f380b5bb46a4bccac60d940760a572bb564deef2d94621809f55fc09ca84947920d532bc84a18e
7
- data.tar.gz: 9888c755fbe23cf6991ece635bbab2b2c7391e9af0790bbed3a8572f9bf3ed09d4ba77b2152f238468a97c6c8f10314c824243fbc0e104804ab6a9aba4d86780
6
+ metadata.gz: ace304e0a1e1bc8c0d137a7633b7e47f5facdf2d53cf83e4ed6a55b9de6baa938c138ba816e9c384b070e4ea509a9cf04acb2a735c931d1a250136fa0da948b7
7
+ data.tar.gz: 337a9138a8f38d7bb33cb36e6813fe39d5c1fae6dec3907f717760766fb9cc7952f3a9e6b3bd71a35c89232467aa665ed3b18576be8eae2b498fd915c7952ae1
data/README.md CHANGED
@@ -27,23 +27,20 @@ findyml config/locales en.activerecord.attributes
27
27
  # config/locales/active_record.en.yml:3:6
28
28
  ```
29
29
 
30
- You can also do partial matches, by starting/ending with a dot or putting an asterisk (`*`) in place of a key.
30
+ You can also do partial matches, by starting/ending with a dot or putting a double-dot `..` in the middle.
31
31
 
32
32
  ```sh
33
33
  findyml .activerecord.attributes
34
- findyml 'en.*.attributes'
34
+ findyml en..attributes
35
35
  ```
36
36
 
37
- (You have to quote the query if you use `*` because your shell might thing it is a dir glob)
38
-
39
- **NOTE**: if you end with a dot, or the last key is an asterisk, it will return _every single sub key_. i.e. careful if you try `findyml en.` or `findyml en.*`, you will get every line of every locale file 🙃.
37
+ **NOTE**: if you end with a dot, it will return _every single sub key_. i.e. careful if you try `findyml en.`, you will get every line of every english locale file 🙃.
40
38
 
41
39
  ## TODO
42
40
 
43
41
  - Allow optional keys in query: `foo.[bar,baz].qux` (`qux` key in either `bar` or `baz` parent key)
44
42
  - Allow negated keys in query: `foo.!bar.baz` (`baz` with any parent but `bar`)
45
43
  - Partial key matches: `foo.bar_*` (any key starting with `bar_`)
46
- - Allow `*` and `**` like directory globbing.
47
44
  - Fuzzy matching?
48
45
  - Find and fix bugs
49
46
  - Optimisation, caching
data/exe/findyml CHANGED
@@ -3,7 +3,34 @@
3
3
 
4
4
  $0 = "findyml"
5
5
 
6
+ require "optparse"
6
7
  require "findyml"
7
8
 
8
- dir, query = Findyml.parse_options
9
- Findyml.find_and_print(query, dir)
9
+ options = { path: Dir.pwd }
10
+ option_parser = OptionParser.new do |parser|
11
+ parser.banner = "Usage: #{$0} [-ar] [-p path] query"
12
+
13
+ parser.on("-a", "--[no-]aliases", "Show aliases") do |v|
14
+ options[:show_aliases] = v
15
+ end
16
+
17
+ parser.on("-r", "--[no-]relative", "Print relative paths") do |v|
18
+ options[:print_relative_paths] = v
19
+ end
20
+
21
+ parser.on("-p PATH", "--path=PATH", "Path to search from (default PWD)") do |v|
22
+ options[:path] = v
23
+ end
24
+
25
+ parser.on("-h", "--help", "Prints this help") do
26
+ puts parser
27
+ exit
28
+ end
29
+ end.parse!
30
+
31
+ if ARGV.length != 1
32
+ puts option_parser
33
+ exit(1)
34
+ end
35
+
36
+ Findyml.find_and_print(ARGV.first, options.delete(:path), **options)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Findyml
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/findyml.rb CHANGED
@@ -21,6 +21,10 @@ module Findyml
21
21
  def inspect
22
22
  "#{path.map(&:inspect).join('.')} -> #{self}"
23
23
  end
24
+
25
+ def location
26
+ [file, line, col].join(':')
27
+ end
24
28
  end
25
29
 
26
30
  class KeyNode
@@ -73,17 +77,28 @@ module Findyml
73
77
  end
74
78
 
75
79
  class FileExtractor
76
- def self.call(file, &block)
77
- new(file).extract(&block)
80
+ def self.call(file, **kwargs, &block)
81
+ new(file, **kwargs).extract(&block)
78
82
  end
79
83
 
80
- def initialize(file)
84
+ def initialize(file, dedup: false)
81
85
  @file = File.expand_path(file)
82
86
  @yaml = YAML.parse_file(@file)
83
87
  @anchors = {}
88
+ @dups = {} if dedup
89
+ end
90
+
91
+ def dedup?
92
+ !!@dups
93
+ end
94
+
95
+ def yielded?(key)
96
+ @dups[[key.line, key.col]]
84
97
  end
85
98
 
86
99
  def extract(&block)
100
+ return unless @yaml
101
+
87
102
  all_nodes = @yaml.children.map { construct_nodes(_1) }
88
103
 
89
104
  all_nodes.each do |nodes, _|
@@ -95,7 +110,11 @@ module Findyml
95
110
  nodes.each do |key_node, (children, yaml_node, alias_node)|
96
111
  new_path = [*path, key_node.to_s]
97
112
  new_alias_path = [*alias_path, *alias_node]
98
- yield Key.new(@file, key_node.node, new_path, children.nil?, new_alias_path)
113
+ key = Key.new(@file, key_node.node, new_path, children.nil?, @dups ? [] : new_alias_path)
114
+ if !dedup? || !yielded?(key)
115
+ @dups[[key.line, key.col]] = true if dedup?
116
+ yield key
117
+ end
99
118
  extract_nodes(children, new_path, new_alias_path, &block) if children
100
119
  end
101
120
  end
@@ -146,26 +165,14 @@ module Findyml
146
165
  end
147
166
  end
148
167
 
149
- def self.parse_options
150
- case ARGV.size
151
- when 1
152
- [Dir.pwd, ARGV.last]
153
- when 2
154
- ARGV
155
- else
156
- puts "Usage: #{$0} [path] query"
157
- exit(1)
158
- end
159
- end
160
-
161
- def self.find(query_string, dir = Dir.pwd)
162
- return to_enum(:find, query_string, dir) unless block_given?
168
+ def self.find(query_string, dir = Dir.pwd, dedup: false)
169
+ return to_enum(:find, query_string, dir, dedup:) unless block_given?
163
170
 
164
171
  # TODO: cache fast key lookup in a temporary sqlite db?
165
172
  query = parse_key(query_string)
166
173
  files = Dir.glob(File.join(dir, '**', '*.yml'))
167
174
  files.each do |file|
168
- FileExtractor.call(file) do |key|
175
+ FileExtractor.call(file, dedup:) do |key|
169
176
  yield key if key_match?(key.path, query)
170
177
  end
171
178
  rescue YAML::SyntaxError
@@ -175,9 +182,18 @@ module Findyml
175
182
  end
176
183
  end
177
184
 
178
- def self.find_and_print(*args)
179
- find(*args) do |key|
180
- puts "#{key.file}:#{key.line}:#{key.col}#{key.alias_path.map{"(#{_1.start_line+1})"}.join('')}"
185
+ def self.find_and_print(*args, print_relative_paths: false, show_aliases: false)
186
+ find(*args, dedup: !show_aliases) do |key|
187
+ file = key.file
188
+ if print_relative_paths
189
+ file = Pathname.new(file).relative_path_from(Dir.pwd).to_s
190
+ end
191
+ output = [file, key.line, key.col].join(':')
192
+ if show_aliases
193
+ output = [output, *key.alias_path.map { _1.start_line + 1 }].join(' <- ')
194
+ end
195
+ puts output
196
+ # puts "#{key.file}:#{key.line}:#{key.col}#{key.alias_path.map{"(#{_1.start_line+1})"}.join('')}"
181
197
  end
182
198
  end
183
199
 
@@ -220,16 +236,10 @@ module Findyml
220
236
 
221
237
  # includes a dot
222
238
  when /\./
223
- # invalid unless something before the dot
224
- invalid_key! if $`.empty?
225
-
226
- k = $` == '*' ? :splat : $`
239
+ pre = $`.empty? ? :splat : $`
227
240
 
228
241
  # parse everything after the dot
229
- [k, *parse_key_parts($')]
230
-
231
- # splat at the end of the string
232
- when '*' then [:splat]
242
+ [pre, *parse_key_parts($')]
233
243
 
234
244
  # single key query
235
245
  else [key]
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: findyml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danielle Smith
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2023-10-02 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: Ever wondered where that i18n locale was defined but your project is
14
13
  massive and legacy and has multiple competing inconsistent standards of organisation?
@@ -34,7 +33,6 @@ metadata:
34
33
  homepage_uri: https://github.com/danini-the-panini/findyml
35
34
  source_code_uri: https://github.com/danini-the-panini/findyml
36
35
  changelog_uri: https://github.com/danini-the-panini/findyml/releases
37
- post_install_message:
38
36
  rdoc_options: []
39
37
  require_paths:
40
38
  - lib
@@ -49,8 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
47
  - !ruby/object:Gem::Version
50
48
  version: '0'
51
49
  requirements: []
52
- rubygems_version: 3.4.17
53
- signing_key:
50
+ rubygems_version: 4.0.3
54
51
  specification_version: 4
55
52
  summary: Search for yaml keys across multiple files
56
53
  test_files: []