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.
@@ -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
@@ -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.
@@ -0,0 +1,4 @@
1
+ require 'ritual'
2
+
3
+ require 'rake/testtask'
4
+ Rake::TestTask.new(:test) { |t| t.pattern = 'test/**/*.rb' }
@@ -0,0 +1,3 @@
1
+ require 'gem_fuzzy/errors'
2
+ require 'gem_fuzzy/fuzzy_matcher'
3
+ require 'gem_fuzzy/runner'
@@ -0,0 +1,4 @@
1
+ module GemFuzzy
2
+ Error = Class.new(RuntimeError)
3
+ UsageError = Class.new(Error)
4
+ end
@@ -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,11 @@
1
+ module GemFuzzy
2
+ VERSION = [1, 0, 0]
3
+
4
+ class << VERSION
5
+ include Comparable
6
+
7
+ def to_s
8
+ join('.')
9
+ end
10
+ end
11
+ 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: []