gem-fuzzy 1.0.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 +7 -0
- data/CHANGELOG +17 -0
- data/LICENSE +20 -0
- data/Rakefile +4 -0
- data/lib/gem_fuzzy.rb +3 -0
- data/lib/gem_fuzzy/errors.rb +4 -0
- data/lib/gem_fuzzy/fuzzy_matcher.rb +53 -0
- data/lib/gem_fuzzy/runner.rb +131 -0
- data/lib/gem_fuzzy/version.rb +11 -0
- data/lib/rubygems_plugin.rb +130 -0
- metadata +56 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9551e93e90d329a56873fc09948fdbedcbd2349541f60952f576bbce6ae04b7b
|
4
|
+
data.tar.gz: 57d83ddb75e77fc181ef7654cad60a37ed07db49d5610508014ce18b795bb45e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c079f4f4ad2baebc7989bc891e1ef85daf7dbd155b60d581db2dd3d5f7f3372a3271b8dce90bce8379d382e5fee32b1e4438d1f7581d7c317e5e7f8f85866382
|
7
|
+
data.tar.gz: 373ae90752e57ffca57a15fd17d7b6b1f8ef52099dc18cc7f3fb27e1526fe25e80e5c3a7db7fa4fce994f395ae7369fe8935c37502a1a57654b1560a78113227
|
data/CHANGELOG
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
== 1.0.0 2019-05-14
|
2
|
+
|
3
|
+
* Command is now "gem fuzzy ...", as gem now has its own "info" command.
|
4
|
+
* The gem is now called gem-fuzzy to match.
|
5
|
+
|
6
|
+
== 0.1.1 2011-12-28
|
7
|
+
|
8
|
+
* Silenced deprecation warnings for Rubygems 1.8.x.
|
9
|
+
* Fixed %dependencies for Rubygems >= 1.3.6.
|
10
|
+
|
11
|
+
== 0.1.0 2011-04-09
|
12
|
+
|
13
|
+
* Support for Rubygems 1.7.
|
14
|
+
|
15
|
+
== 0.0.1 2010-03-17
|
16
|
+
|
17
|
+
* Hi.
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 George Ogata
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/lib/gem_fuzzy.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module GemFuzzy
|
2
|
+
class FuzzyMatcher
|
3
|
+
def initialize(name, version)
|
4
|
+
@name = name
|
5
|
+
@version = version
|
6
|
+
end
|
7
|
+
|
8
|
+
def all_available_matches
|
9
|
+
matches([])
|
10
|
+
end
|
11
|
+
|
12
|
+
def matches(specs)
|
13
|
+
specs = matches_for(specs, :name, @name)
|
14
|
+
specs = matches_for(specs, :version, @version) if @version
|
15
|
+
specs
|
16
|
+
end
|
17
|
+
|
18
|
+
def matches_for(specs, attribute, value)
|
19
|
+
[:exact, :substring, :subsequence].each do |type|
|
20
|
+
matches = send("#{type}_matches", specs, attribute, value)
|
21
|
+
return matches if !matches.empty?
|
22
|
+
end
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def exact_matches(specs, attribute, value)
|
29
|
+
specs.select{|spec| spec.send(attribute).to_s == value}
|
30
|
+
end
|
31
|
+
|
32
|
+
def substring_matches(specs, attribute, value)
|
33
|
+
specs.select{|spec| spec.send(attribute).to_s.include?(value)}
|
34
|
+
end
|
35
|
+
|
36
|
+
def subsequence_matches(specs, attribute, value)
|
37
|
+
specs.select{|spec| include_subsequence?(spec.send(attribute).to_s, value)}
|
38
|
+
end
|
39
|
+
|
40
|
+
def include_subsequence?(string, subsequence)
|
41
|
+
string_index = 0
|
42
|
+
subsequence_index = 0
|
43
|
+
while string_index < string.length
|
44
|
+
if string[string_index] == subsequence[subsequence_index]
|
45
|
+
subsequence_index += 1
|
46
|
+
return true if subsequence_index == subsequence.length
|
47
|
+
end
|
48
|
+
string_index += 1
|
49
|
+
end
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module GemFuzzy
|
2
|
+
class Runner
|
3
|
+
def self.run(options, *args)
|
4
|
+
Runner.new(options, *args).run
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(options={}, *args)
|
8
|
+
@options = options
|
9
|
+
@args = args
|
10
|
+
@output = STDOUT
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :options, :args, :output
|
14
|
+
|
15
|
+
def run
|
16
|
+
parse_args
|
17
|
+
parse_options
|
18
|
+
matcher = FuzzyMatcher.new(@name, @version)
|
19
|
+
specs = matcher.matches(installed_specs)
|
20
|
+
validate_exactly_one(specs)
|
21
|
+
output_formatted(specs)
|
22
|
+
end
|
23
|
+
|
24
|
+
def installed_specs
|
25
|
+
version = Gem::Version.new(Gem::VERSION)
|
26
|
+
if version >= Gem::Version.new('1.8.0')
|
27
|
+
Gem::Specification.to_a
|
28
|
+
elsif version >= Gem::Version.new('1.7.0')
|
29
|
+
Gem.source_index.gems.values
|
30
|
+
else
|
31
|
+
Gem.source_index.all_gems.values
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def parse_args
|
38
|
+
case @args.length
|
39
|
+
when 1
|
40
|
+
@name, @version = @args.first, nil
|
41
|
+
when 2
|
42
|
+
@name, @version = *@args
|
43
|
+
else
|
44
|
+
raise UsageError
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_options
|
49
|
+
@format = options[:format] || "%name %version"
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate_exactly_one(specs)
|
53
|
+
if @options[:exactly_one]
|
54
|
+
if specs.empty?
|
55
|
+
raise Error, "no gems matching \"#{@name}\" \"#{@version}\""
|
56
|
+
elsif specs.length > 1
|
57
|
+
message = "#{specs.length} matching gems:\n" +
|
58
|
+
specs.map{|spec| " #{spec.name}-#{spec.version}\n"}.join
|
59
|
+
raise Error, message
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def output_formatted(specs)
|
65
|
+
specs.each do |spec|
|
66
|
+
output.print format(spec)
|
67
|
+
output.print "\n" unless options[:no_newlines]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def format(spec)
|
72
|
+
@format.gsub(format_regexp) do |match|
|
73
|
+
if match =~ /\A%date/
|
74
|
+
expand_date(spec, match)
|
75
|
+
else
|
76
|
+
self.class.expansions[match].call(spec)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def expand_date(spec, match)
|
82
|
+
date = spec.date
|
83
|
+
if match =~ /\[(.*)\]/
|
84
|
+
date.strftime($1)
|
85
|
+
else
|
86
|
+
date.to_s
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def format_regexp
|
91
|
+
@format_regexp ||= Regexp.union(*self.class.expansions.keys)
|
92
|
+
end
|
93
|
+
|
94
|
+
class << self
|
95
|
+
def expand(token, &expansion)
|
96
|
+
@expansions ||= {}
|
97
|
+
expansions[token] = expansion
|
98
|
+
end
|
99
|
+
attr_reader :expansions
|
100
|
+
end
|
101
|
+
|
102
|
+
expand('%rubygems_version'){|spec| spec.rubygems_version}
|
103
|
+
expand('%specification_version'){|spec| spec.specification_version}
|
104
|
+
expand('%name'){|spec| spec.name}
|
105
|
+
expand('%version'){|spec| spec.version}
|
106
|
+
expand(/%date(?:\[.*?\])?/) # handled specially
|
107
|
+
expand('%summary'){|spec| spec.summary}
|
108
|
+
expand('%email'){|spec| spec.email}
|
109
|
+
expand('%homepage'){|spec| spec.homepage}
|
110
|
+
expand('%rubyforge_project'){|spec| spec.rubyforge_project}
|
111
|
+
expand('%description'){|spec| spec.description}
|
112
|
+
expand('%executables'){|spec| spec.executables.join(', ')}
|
113
|
+
expand('%bindir'){|spec| spec.bindir}
|
114
|
+
expand('%required_ruby_version'){|spec| spec.required_ruby_version}
|
115
|
+
expand('%required_rubygems_version'){|spec| spec.required_rubygems_version}
|
116
|
+
expand('%platform'){|spec| spec.platform}
|
117
|
+
expand('%signing_key'){|spec| spec.signing_key}
|
118
|
+
expand('%cert_chain'){|spec| Array(spec.cert_chain).join("\n\n")}
|
119
|
+
expand('%post_install_message'){|spec| spec.post_install_message}
|
120
|
+
expand('%authors'){|spec| spec.authors.join(', ')}
|
121
|
+
expand('%licenses'){|spec| spec.licenses.join(', ')}
|
122
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.3.6')
|
123
|
+
expand('%dependencies'){|spec| spec.dependencies.map{|dep| "#{dep.name} #{dep.requirement}"}.join(', ')}
|
124
|
+
else
|
125
|
+
expand('%dependencies'){|spec| spec.dependencies.map{|dep| "#{dep.name} #{dep.version_requirements}"}.join(', ')}
|
126
|
+
end
|
127
|
+
expand('%path'){|spec| spec.full_gem_path}
|
128
|
+
expand('%%'){|spec| '%'}
|
129
|
+
expand('%N'){|spec| "\n"}
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'rubygems/command_manager'
|
2
|
+
require 'gem_fuzzy'
|
3
|
+
|
4
|
+
Gem::CommandManager.instance.register_command :fuzzy
|
5
|
+
|
6
|
+
module Gem
|
7
|
+
module Commands
|
8
|
+
class FuzzyCommand < Command
|
9
|
+
def initialize
|
10
|
+
super 'fuzzy', "Search for gems with fuzzy matching."
|
11
|
+
add_option('-1', '--exactly-one', "Fail if not exactly 1 match.") do |value, options|
|
12
|
+
options[:exactly_one] = true
|
13
|
+
end
|
14
|
+
add_option('-f', '--format STRING', "Format of output (see below).") do |value, options|
|
15
|
+
options[:format] = value
|
16
|
+
end
|
17
|
+
add_option('-N', '--no-newlines', "Suppress printing of newlines after each gem") do |value, options|
|
18
|
+
options[:no_newlines] = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def arguments
|
23
|
+
<<-EOS.gsub(/^ *\|/, '')
|
24
|
+
|NAME (fuzzy) name of the gem
|
25
|
+
|VERSION (fuzzy) version of the gem
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
|
29
|
+
def usage
|
30
|
+
"#{program_name} NAME [VERSION]"
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_str
|
34
|
+
''
|
35
|
+
end
|
36
|
+
|
37
|
+
def description
|
38
|
+
<<-EOS.gsub(/^ *\|/, '')
|
39
|
+
|Print information about matching gems. The NAME and
|
40
|
+
|VERSION are fuzzy-matched according to the following
|
41
|
+
|algorithm:
|
42
|
+
|
|
43
|
+
| * Look for gems exactly matching NAME.
|
44
|
+
| * If none found, look for gems containing NAME. e.g.,
|
45
|
+
| "fuz" matches "gem-fuzzy"
|
46
|
+
| * If none found, look for gems containing the characters
|
47
|
+
| of NAME in the same order. e.g, "e_zy" matches
|
48
|
+
| "gem-fuzzy"
|
49
|
+
| * Filter the results above with the version string in the
|
50
|
+
| same way.
|
51
|
+
|
|
52
|
+
|The format string (--format option) has the following
|
53
|
+
|escapes available:
|
54
|
+
|
|
55
|
+
|%rubygems_version
|
56
|
+
| Rubygems version that built the gemspec
|
57
|
+
|%specification_version
|
58
|
+
| Version of the gem's gemspec
|
59
|
+
|%name
|
60
|
+
| Gem name
|
61
|
+
|%version
|
62
|
+
| Gem version
|
63
|
+
|%date
|
64
|
+
|%date[STRFTIME_FORMAT]
|
65
|
+
| Date the gem was released. STRFTIME_FORMAT may contain
|
66
|
+
| any %-escapes honored by Time#strftime
|
67
|
+
|%summary
|
68
|
+
| Summary of the gem
|
69
|
+
|%email
|
70
|
+
| Email address of the gem author
|
71
|
+
|%homepage
|
72
|
+
| Homepage of the gem
|
73
|
+
|%rubyforge_project
|
74
|
+
| Name of the rubyforge project
|
75
|
+
|%description
|
76
|
+
| Gem description
|
77
|
+
|%executables
|
78
|
+
| List of executables (comma separated)
|
79
|
+
|%bindir
|
80
|
+
| Directory the gem's executables are installed into
|
81
|
+
|%required_ruby_version
|
82
|
+
| Ruby version required for the gem
|
83
|
+
|%required_rubygems_version
|
84
|
+
| Rubygems version required for the gem
|
85
|
+
|%platform
|
86
|
+
| Platform the gem is built for
|
87
|
+
|%signing_key
|
88
|
+
| Key which signed the gem
|
89
|
+
|%cert_chain
|
90
|
+
| Certificate chain used for signing ("\\n\\n" separated)
|
91
|
+
|%post_install_message
|
92
|
+
| Message displayed upon installation
|
93
|
+
|%authors
|
94
|
+
| List of author names (comma separated)
|
95
|
+
|%licenses
|
96
|
+
| List of license names (comma separated)
|
97
|
+
|%dependencies
|
98
|
+
| List of dependencies (comma separated)
|
99
|
+
|%path
|
100
|
+
| Path of the installed gem
|
101
|
+
|%%
|
102
|
+
| A '%' character
|
103
|
+
|%N
|
104
|
+
| A newline
|
105
|
+
EOS
|
106
|
+
end
|
107
|
+
|
108
|
+
def execute
|
109
|
+
begin
|
110
|
+
GemFuzzy::Runner.run(options, *options[:args])
|
111
|
+
rescue GemFuzzy::UsageError
|
112
|
+
STDERR.puts "USAGE: #{usage}"
|
113
|
+
terminate_interaction(1)
|
114
|
+
rescue GemFuzzy::Error => e
|
115
|
+
STDERR.puts e.message
|
116
|
+
terminate_interaction(1)
|
117
|
+
rescue Object => e
|
118
|
+
puts "Unexpected error! Debug with DEBUG=1"
|
119
|
+
if ENV['DEBUG']
|
120
|
+
STDERR.puts "#{exception.class}: #{exception.message}"
|
121
|
+
exception.backtrace.each do |line|
|
122
|
+
STDERR.puts " #{line}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
raise
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gem-fuzzy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- George Ogata
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-14 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |
|
14
|
+
A Rubygems plugin which adds a 'fuzzy' command which fuzzy-searches for
|
15
|
+
gems and prints information about each match.
|
16
|
+
|
17
|
+
Options provide precise control over output format, making it friendly both
|
18
|
+
on the command line and in scripts.
|
19
|
+
email: george.ogata@gmail.com
|
20
|
+
executables: []
|
21
|
+
extensions: []
|
22
|
+
extra_rdoc_files: []
|
23
|
+
files:
|
24
|
+
- CHANGELOG
|
25
|
+
- LICENSE
|
26
|
+
- Rakefile
|
27
|
+
- lib/gem_fuzzy.rb
|
28
|
+
- lib/gem_fuzzy/errors.rb
|
29
|
+
- lib/gem_fuzzy/fuzzy_matcher.rb
|
30
|
+
- lib/gem_fuzzy/runner.rb
|
31
|
+
- lib/gem_fuzzy/version.rb
|
32
|
+
- lib/rubygems_plugin.rb
|
33
|
+
homepage: http://github.com/oggy/gem-fuzzy
|
34
|
+
licenses:
|
35
|
+
- MIT
|
36
|
+
metadata: {}
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubygems_version: 3.0.3
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: Search for gems, fuzzily.
|
56
|
+
test_files: []
|