findyml 0.1.2 → 0.2.1

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: 52cf98578abdfc460a7dd2983b91aa5d8121de3f43846033112ab7da4151f3d3
4
- data.tar.gz: 367437456f64b85060592b5deab077375ad39b7915d4e99cdf0e9d7f61692a8c
3
+ metadata.gz: f31f5831219175be491f1d62f61877d025677ab6dbee1eeb2256e11224e9bf37
4
+ data.tar.gz: f07bef53eac5dd15bebbc2a2e0f2575633f4fc0b2dc6807053cd543466864a67
5
5
  SHA512:
6
- metadata.gz: c4d8d89095e22b5c066f291b45884b9990fe025edf8a41699b266837026f773d06c8de64ed823c244b8afe64ca37439daac5b4eb6741ae1f9b07c8794600cb86
7
- data.tar.gz: 2926cd54e783a5bb7d978da7dfc08f878d497998e3d1fd6ad9acad5f1c33434c102f90a6d7062652bc3b1457f24938a3160e7580fb5ca9e76bb3043cd1733632
6
+ metadata.gz: 6f44c5e2048fc217d93546cc7b4a4bfc06ad1db324170622bc0d27217e5de9c17532d3897e41e284b5f4ff258c64cc33df407a8c05ca47353419f965dee71276
7
+ data.tar.gz: e0e0328d166b35214158c50baf79dfb309fc209657c9f62e9e328fc487d90a1aaf0e0c1d6a931750ddc2b07d87ce1e0e0df23e8e47d35ab569d0c7dc04fa0323
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.2"
4
+ VERSION = "0.2.1"
5
5
  end
data/lib/findyml.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "yaml"
4
+ require "pathname"
4
5
 
5
6
  require_relative "findyml/version"
6
7
 
@@ -21,6 +22,10 @@ module Findyml
21
22
  def inspect
22
23
  "#{path.map(&:inspect).join('.')} -> #{self}"
23
24
  end
25
+
26
+ def location
27
+ [file, line, col].join(':')
28
+ end
24
29
  end
25
30
 
26
31
  class KeyNode
@@ -73,14 +78,23 @@ module Findyml
73
78
  end
74
79
 
75
80
  class FileExtractor
76
- def self.call(file, &block)
77
- new(file).extract(&block)
81
+ def self.call(file, **kwargs, &block)
82
+ new(file, **kwargs).extract(&block)
78
83
  end
79
84
 
80
- def initialize(file)
85
+ def initialize(file, dedup: false)
81
86
  @file = File.expand_path(file)
82
87
  @yaml = YAML.parse_file(@file)
83
88
  @anchors = {}
89
+ @dups = {} if dedup
90
+ end
91
+
92
+ def dedup?
93
+ !!@dups
94
+ end
95
+
96
+ def yielded?(key)
97
+ @dups[[key.line, key.col]]
84
98
  end
85
99
 
86
100
  def extract(&block)
@@ -97,7 +111,11 @@ module Findyml
97
111
  nodes.each do |key_node, (children, yaml_node, alias_node)|
98
112
  new_path = [*path, key_node.to_s]
99
113
  new_alias_path = [*alias_path, *alias_node]
100
- yield Key.new(@file, key_node.node, new_path, children.nil?, new_alias_path)
114
+ key = Key.new(@file, key_node.node, new_path, children.nil?, @dups ? [] : new_alias_path)
115
+ if !dedup? || !yielded?(key)
116
+ @dups[[key.line, key.col]] = true if dedup?
117
+ yield key
118
+ end
101
119
  extract_nodes(children, new_path, new_alias_path, &block) if children
102
120
  end
103
121
  end
@@ -148,26 +166,14 @@ module Findyml
148
166
  end
149
167
  end
150
168
 
151
- def self.parse_options
152
- case ARGV.size
153
- when 1
154
- [Dir.pwd, ARGV.last]
155
- when 2
156
- ARGV
157
- else
158
- puts "Usage: #{$0} [path] query"
159
- exit(1)
160
- end
161
- end
162
-
163
- def self.find(query_string, dir = Dir.pwd)
164
- return to_enum(:find, query_string, dir) unless block_given?
169
+ def self.find(query_string, dir = Dir.pwd, dedup: false)
170
+ return to_enum(:find, query_string, dir, dedup:) unless block_given?
165
171
 
166
172
  # TODO: cache fast key lookup in a temporary sqlite db?
167
173
  query = parse_key(query_string)
168
174
  files = Dir.glob(File.join(dir, '**', '*.yml'))
169
175
  files.each do |file|
170
- FileExtractor.call(file) do |key|
176
+ FileExtractor.call(file, dedup:) do |key|
171
177
  yield key if key_match?(key.path, query)
172
178
  end
173
179
  rescue YAML::SyntaxError
@@ -177,9 +183,18 @@ module Findyml
177
183
  end
178
184
  end
179
185
 
180
- def self.find_and_print(*args)
181
- find(*args) do |key|
182
- puts "#{key.file}:#{key.line}:#{key.col}#{key.alias_path.map{"(#{_1.start_line+1})"}.join('')}"
186
+ def self.find_and_print(*args, print_relative_paths: false, show_aliases: false)
187
+ find(*args, dedup: !show_aliases) do |key|
188
+ file = key.file
189
+ if print_relative_paths
190
+ file = Pathname.new(file).relative_path_from(Dir.pwd).to_s
191
+ end
192
+ output = [file, key.line, key.col].join(':')
193
+ if show_aliases
194
+ output = [output, *key.alias_path.map { _1.start_line + 1 }].join(' <- ')
195
+ end
196
+ puts output
197
+ # puts "#{key.file}:#{key.line}:#{key.col}#{key.alias_path.map{"(#{_1.start_line+1})"}.join('')}"
183
198
  end
184
199
  end
185
200
 
@@ -222,16 +237,10 @@ module Findyml
222
237
 
223
238
  # includes a dot
224
239
  when /\./
225
- # invalid unless something before the dot
226
- invalid_key! if $`.empty?
227
-
228
- k = $` == '*' ? :splat : $`
240
+ pre = $`.empty? ? :splat : $`
229
241
 
230
242
  # parse everything after the dot
231
- [k, *parse_key_parts($')]
232
-
233
- # splat at the end of the string
234
- when '*' then [:splat]
243
+ [pre, *parse_key_parts($')]
235
244
 
236
245
  # single key query
237
246
  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.2
4
+ version: 0.2.1
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: []