salad 0.0.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 +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +9 -0
- data/README.md +123 -0
- data/exe/salad +5 -0
- data/lib/salad/bond_completer.rb +104 -0
- data/lib/salad/catalogue_of_life.rb +43 -0
- data/lib/salad/console.rb +503 -0
- data/lib/salad/gem_help.rb +2163 -0
- data/lib/salad/generate_gem_help.rb +242 -0
- data/lib/salad/version.rb +5 -0
- data/lib/salad.rb +126 -0
- metadata +297 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Generates gem_help.rb by extracting documentation from gem source files
|
|
5
|
+
# Usage: ruby generate_gem_help.rb > lib/salad/gem_help.rb
|
|
6
|
+
|
|
7
|
+
require 'json'
|
|
8
|
+
|
|
9
|
+
def get_gem_description(gem_name)
|
|
10
|
+
descriptions = {
|
|
11
|
+
bananomia: "Wrapper for Bionomia API - access specimen and collection records",
|
|
12
|
+
bell_pepper: "Wrapper for BELS API - georeference locality descriptions via the Biodiversity Enhanced Location Services",
|
|
13
|
+
bok_choy: "Wrapper for BHLnames API - access Biodiversity Heritage Library names data",
|
|
14
|
+
checkerberry: "Wrapper for GNverifier API - verify and search scientific names across curated databases",
|
|
15
|
+
colrapi: "Wrapper for Catalogue of Life (ChecklistBank) API - access global taxonomic checklists and name data",
|
|
16
|
+
crawlyflower: "Wrapper for WoRMS API - access World Register of Marine Species data",
|
|
17
|
+
hookkaido: "Wrapper for OWL Ontology API - access ontology data",
|
|
18
|
+
nasturtium: "Wrapper for iNaturalist API - access species observations and biodiversity data",
|
|
19
|
+
plazucchini: "Wrapper for Plazi TreatmentBank API - access taxonomic treatments and species data",
|
|
20
|
+
syconium: "Wrapper for OpenAlex API - access research publications and academic data",
|
|
21
|
+
wikimelon: "Wrapper for Wikidata API - access linked open knowledge data"
|
|
22
|
+
}
|
|
23
|
+
descriptions[gem_name] || "API wrapper for biodiversity data"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def get_gem_api_url(gem_name)
|
|
27
|
+
urls = {
|
|
28
|
+
bananomia: "https://bionomia.net",
|
|
29
|
+
bell_pepper: "https://bels.geo-vocab.org/",
|
|
30
|
+
bok_choy: "https://www.biodiversitylibrary.org/api",
|
|
31
|
+
checkerberry: "https://verifier.globalnames.org",
|
|
32
|
+
colrapi: "https://www.checklistbank.org/api",
|
|
33
|
+
crawlyflower: "https://www.marinespecies.org/rest/",
|
|
34
|
+
hookkaido: "https://www.ontobee.org",
|
|
35
|
+
nasturtium: "https://api.inaturalist.org/v1",
|
|
36
|
+
plazucchini: "https://api.plazi.org",
|
|
37
|
+
syconium: "https://api.openalex.org",
|
|
38
|
+
wikimelon: "https://www.wikidata.org/w/api.php"
|
|
39
|
+
}
|
|
40
|
+
urls[gem_name] || ""
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class YardDocExtractor
|
|
44
|
+
def initialize(lib_filepath, test_dir = nil)
|
|
45
|
+
@lib_filepath = lib_filepath
|
|
46
|
+
@test_dir = test_dir
|
|
47
|
+
@content = File.read(lib_filepath) if File.exist?(lib_filepath)
|
|
48
|
+
@test_content = load_test_files(test_dir)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def extract_all_methods
|
|
52
|
+
return {} unless @content
|
|
53
|
+
|
|
54
|
+
methods = {}
|
|
55
|
+
lines = @content.split("\n")
|
|
56
|
+
i = 0
|
|
57
|
+
|
|
58
|
+
while i < lines.size
|
|
59
|
+
line = lines[i]
|
|
60
|
+
|
|
61
|
+
# Find method definition
|
|
62
|
+
if line.match?(/^\s*def\s+self\.(\w+)/)
|
|
63
|
+
method_name = line.match(/def\s+self\.(\w+)/)[1]
|
|
64
|
+
|
|
65
|
+
# Look backwards for docstring
|
|
66
|
+
docstring_lines = []
|
|
67
|
+
j = i - 1
|
|
68
|
+
while j >= 0 && lines[j].match?(/^\s*#/)
|
|
69
|
+
docstring_lines.unshift(lines[j])
|
|
70
|
+
j -= 1
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
docstring_text = docstring_lines.join("\n")
|
|
74
|
+
data = parse_docstring(docstring_text)
|
|
75
|
+
|
|
76
|
+
# Extract examples from test files
|
|
77
|
+
data[:examples] = extract_examples_for_method(method_name)
|
|
78
|
+
|
|
79
|
+
methods[method_name.to_sym] = data
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
i += 1
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
methods
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def load_test_files(test_dir)
|
|
89
|
+
return "" unless test_dir && File.directory?(test_dir)
|
|
90
|
+
|
|
91
|
+
test_content = ""
|
|
92
|
+
Dir.glob("#{test_dir}/**/*_test.rb").each do |file|
|
|
93
|
+
test_content += File.read(file) + "\n"
|
|
94
|
+
end
|
|
95
|
+
test_content
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def extract_examples_for_method(method_name)
|
|
101
|
+
return [] unless @test_content && @test_content.length > 0
|
|
102
|
+
|
|
103
|
+
examples = []
|
|
104
|
+
|
|
105
|
+
# Look for method calls in test files
|
|
106
|
+
# Patterns: ModuleName.method_name(...) or Gem.method_name(...)
|
|
107
|
+
@test_content.scan(/([A-Z][a-z]*\.)?#{Regexp.escape(method_name)}\([^)]*\)/) do |match|
|
|
108
|
+
example = $&
|
|
109
|
+
examples << example unless examples.include?(example) || example.length > 100
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
examples[0...3] # Return up to 3 examples
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def parse_docstring(docstring_text)
|
|
116
|
+
lines = docstring_text.split("\n")
|
|
117
|
+
clean_lines = lines.map { |line| line.sub(/^\s*#\s?/, '').rstrip }
|
|
118
|
+
|
|
119
|
+
# Extract summary
|
|
120
|
+
summary_idx = clean_lines.index { |l| !l.empty? && !l.start_with?('@') }
|
|
121
|
+
summary = summary_idx ? clean_lines[summary_idx] : ""
|
|
122
|
+
|
|
123
|
+
# Extract @param lines
|
|
124
|
+
params = {}
|
|
125
|
+
current_param = nil
|
|
126
|
+
|
|
127
|
+
clean_lines.each do |line|
|
|
128
|
+
if line.start_with?('@param ')
|
|
129
|
+
params[current_param[:name]] = current_param[:desc] if current_param
|
|
130
|
+
|
|
131
|
+
if line =~ /@param\s+(\w+)\s+\[([^\]]+)\]\s*(.*?)$/
|
|
132
|
+
param_name = $1.to_sym
|
|
133
|
+
param_desc = $3.strip
|
|
134
|
+
current_param = { name: param_name, desc: param_desc }
|
|
135
|
+
elsif line =~ /@param\s+(\w+)\s+(.*)$/
|
|
136
|
+
param_name = $1.to_sym
|
|
137
|
+
param_desc = $2.strip
|
|
138
|
+
current_param = { name: param_name, desc: param_desc }
|
|
139
|
+
end
|
|
140
|
+
elsif line.start_with?('@') && current_param
|
|
141
|
+
params[current_param[:name]] = current_param[:desc]
|
|
142
|
+
current_param = nil
|
|
143
|
+
elsif current_param && !line.empty?
|
|
144
|
+
current_param[:desc] += " #{line}"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
params[current_param[:name]] = current_param[:desc] if current_param
|
|
149
|
+
|
|
150
|
+
{ summary: summary, params: params }
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Configuration for all gems with their test paths (from source repos).
|
|
155
|
+
# Lib paths are resolved from installed gem specs. Test paths are looked up
|
|
156
|
+
# under SFG_SRC_DIR (defaults to ~/src/github.com/speciesfilegroup).
|
|
157
|
+
require 'rubygems'
|
|
158
|
+
|
|
159
|
+
SFG_GEMS = %i[
|
|
160
|
+
bananomia bell_pepper bok_choy checkerberry colrapi crawlyflower
|
|
161
|
+
hookkaido nasturtium plazucchini syconium wikimelon
|
|
162
|
+
].freeze
|
|
163
|
+
|
|
164
|
+
SFG_SRC_DIR = ENV.fetch('SFG_SRC_DIR', File.expand_path('~/src/github.com/speciesfilegroup'))
|
|
165
|
+
|
|
166
|
+
def gem_lib_path(name)
|
|
167
|
+
Gem::Specification.find_by_name(name.to_s).full_gem_path + "/lib/#{name}.rb"
|
|
168
|
+
rescue Gem::MissingSpecError
|
|
169
|
+
nil
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
GEMS_CONFIG = SFG_GEMS.each_with_object({}) do |name, h|
|
|
173
|
+
h[name] = {
|
|
174
|
+
lib: gem_lib_path(name),
|
|
175
|
+
test: File.join(SFG_SRC_DIR, name.to_s, 'test')
|
|
176
|
+
}
|
|
177
|
+
end.freeze
|
|
178
|
+
|
|
179
|
+
# Extract documentation from all gems
|
|
180
|
+
gem_docs = {}
|
|
181
|
+
GEMS_CONFIG.each do |gem_name, paths|
|
|
182
|
+
extractor = YardDocExtractor.new(paths[:lib], paths[:test])
|
|
183
|
+
gem_docs[gem_name] = extractor.extract_all_methods
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Generate Ruby code
|
|
187
|
+
ruby_code = "# frozen_string_literal: true\n\n"
|
|
188
|
+
ruby_code += "module Salad\n"
|
|
189
|
+
ruby_code += " GEM_HELP = {\n"
|
|
190
|
+
|
|
191
|
+
gem_docs.each do |gem_name, methods|
|
|
192
|
+
ruby_code += " #{gem_name.inspect} => {\n"
|
|
193
|
+
ruby_code += " description: \"#{get_gem_description(gem_name)}\",\n"
|
|
194
|
+
ruby_code += " api: \"#{get_gem_api_url(gem_name)}\",\n"
|
|
195
|
+
ruby_code += " endpoints: {\n"
|
|
196
|
+
|
|
197
|
+
methods.each do |method_name, data|
|
|
198
|
+
ruby_code += " #{method_name.inspect} => {\n"
|
|
199
|
+
ruby_code += " description: #{data[:summary].inspect},\n"
|
|
200
|
+
|
|
201
|
+
# Add params
|
|
202
|
+
if data[:params].any?
|
|
203
|
+
ruby_code += " params: {\n"
|
|
204
|
+
data[:params].each do |param_name, param_desc|
|
|
205
|
+
clean_desc = param_desc.gsub(/\n/, ' ').strip
|
|
206
|
+
ruby_code += " #{param_name.inspect} => #{clean_desc.inspect},\n"
|
|
207
|
+
end
|
|
208
|
+
ruby_code += " },\n"
|
|
209
|
+
else
|
|
210
|
+
ruby_code += " params: {},\n"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Add examples
|
|
214
|
+
examples = data[:examples] || []
|
|
215
|
+
if examples.any?
|
|
216
|
+
ruby_code += " examples: [\n"
|
|
217
|
+
examples.each do |example|
|
|
218
|
+
ruby_code += " #{example.inspect},\n"
|
|
219
|
+
end
|
|
220
|
+
ruby_code += " ],\n"
|
|
221
|
+
else
|
|
222
|
+
ruby_code += " examples: [],\n"
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
ruby_code += " },\n"
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
ruby_code += " },\n"
|
|
229
|
+
ruby_code += " },\n"
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
ruby_code += " }.freeze\n"
|
|
233
|
+
ruby_code += "end\n"
|
|
234
|
+
|
|
235
|
+
puts ruby_code
|
|
236
|
+
|
|
237
|
+
# Print summary stats
|
|
238
|
+
STDERR.puts "\n=== GENERATION SUMMARY ===\n\n"
|
|
239
|
+
gem_docs.each do |gem_name, methods|
|
|
240
|
+
STDERR.puts "#{gem_name.to_s.ljust(15)}: #{methods.size} endpoints"
|
|
241
|
+
end
|
|
242
|
+
STDERR.puts "\nTotal endpoints: #{gem_docs.values.map(&:size).sum}"
|
data/lib/salad.rb
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'salad/version'
|
|
4
|
+
require 'salad/catalogue_of_life'
|
|
5
|
+
|
|
6
|
+
module Salad
|
|
7
|
+
GEMS = %w[
|
|
8
|
+
bananomia
|
|
9
|
+
bell_pepper
|
|
10
|
+
bok_choy
|
|
11
|
+
checkerberry
|
|
12
|
+
colrapi
|
|
13
|
+
crawlyflower
|
|
14
|
+
hookkaido
|
|
15
|
+
nasturtium
|
|
16
|
+
plazucchini
|
|
17
|
+
syconium
|
|
18
|
+
wikimelon
|
|
19
|
+
].freeze
|
|
20
|
+
|
|
21
|
+
SERVICES = {
|
|
22
|
+
bels: 'bell_pepper',
|
|
23
|
+
bhlnames: 'bok_choy',
|
|
24
|
+
bionomia: 'bananomia',
|
|
25
|
+
catalogue_of_life: 'colrapi',
|
|
26
|
+
checklistbank: 'colrapi',
|
|
27
|
+
clb: 'colrapi',
|
|
28
|
+
col: 'colrapi',
|
|
29
|
+
gnverifier: 'checkerberry',
|
|
30
|
+
inaturalist: 'nasturtium',
|
|
31
|
+
owl: 'hookkaido',
|
|
32
|
+
openalex: 'syconium',
|
|
33
|
+
plazi: 'plazucchini',
|
|
34
|
+
wikidata: 'wikimelon',
|
|
35
|
+
worms: 'crawlyflower'
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
class << self
|
|
39
|
+
def gem_module(gem_name)
|
|
40
|
+
name = gem_name.split('_').map(&:capitalize).join
|
|
41
|
+
Object.const_get(name)
|
|
42
|
+
rescue NameError
|
|
43
|
+
raise NameError, "Cannot find top-level module for gem #{gem_name.inspect} (expected #{name})"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def services
|
|
47
|
+
SERVICES
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Top-level constants Salad will offer for case-insensitive tab-completion
|
|
51
|
+
# in the REPL.
|
|
52
|
+
def completable_names
|
|
53
|
+
@completable_names ||= (['Salad'] + GEMS.map { |g| gem_module(g).to_s }).freeze
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Regex matching any non-empty prefix of length >= 3 of any completable name.
|
|
57
|
+
# Built by enumerating prefixes and joining with `|`. Each prefix is escaped
|
|
58
|
+
# so weird characters in a name can't change the regex's meaning. The 3-char
|
|
59
|
+
# minimum keeps short ambiguous input (`s`, `c`) falling through to Pry's
|
|
60
|
+
# default completion.
|
|
61
|
+
COMPLETABLE_PREFIX_MIN = 3
|
|
62
|
+
|
|
63
|
+
def completable_prefix_regex
|
|
64
|
+
@completable_prefix_regex ||= build_prefix_regex(completable_names)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Names offered as completions after `help `. Uses CamelCase module names
|
|
68
|
+
# for the bundled gems (so `help nast<TAB>` -> `help Nasturtium`) plus the
|
|
69
|
+
# lowercase service aliases (so `help inat<TAB>` -> `help inaturalist`).
|
|
70
|
+
# `Salad` itself is the literal services-listing topic.
|
|
71
|
+
def help_completable_names
|
|
72
|
+
@help_completable_names ||= (completable_names + SERVICES.keys.map(&:to_s)).uniq.freeze
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Reverse lookup: 'Nasturtium' -> 'nasturtium', 'BellPepper' -> 'bell_pepper'.
|
|
76
|
+
# Returns nil for unknown module names.
|
|
77
|
+
def gem_for_module(module_name)
|
|
78
|
+
@gem_for_module ||= GEMS.each_with_object({}) do |g, h|
|
|
79
|
+
h[gem_module(g).to_s] = g
|
|
80
|
+
end.freeze
|
|
81
|
+
@gem_for_module[module_name]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def help_completable_prefix_regex
|
|
85
|
+
@help_completable_prefix_regex ||= build_prefix_regex(help_completable_names, prefix: 'help\\s+')
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def build_prefix_regex(names, prefix: '')
|
|
89
|
+
prefixes = names.flat_map { |n| (COMPLETABLE_PREFIX_MIN..n.length).map { |i| n[0...i] } }
|
|
90
|
+
Regexp.new("\\A#{prefix}(?:#{prefixes.map { |p| Regexp.escape(p) }.join('|')})\\z", Regexp::IGNORECASE)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def help
|
|
94
|
+
puts 'Salad services — access by service name or gem name:'
|
|
95
|
+
service_width = SERVICES.keys.map { |s| s.to_s.length }.max
|
|
96
|
+
gem_width = SERVICES.values.map(&:length).max
|
|
97
|
+
SERVICES.sort.each do |service, gem_name|
|
|
98
|
+
mod = begin
|
|
99
|
+
gem_module(gem_name).to_s
|
|
100
|
+
rescue NameError
|
|
101
|
+
'(not loaded)'
|
|
102
|
+
end
|
|
103
|
+
printf " Salad.%-#{service_width}s Salad.%-#{gem_width}s -> %s\n", service, gem_name, mod
|
|
104
|
+
end
|
|
105
|
+
nil
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
COL_SCOPED_SERVICES = %i[catalogue_of_life col].freeze
|
|
110
|
+
|
|
111
|
+
SERVICES.each do |service, gem_name|
|
|
112
|
+
if COL_SCOPED_SERVICES.include?(service)
|
|
113
|
+
define_singleton_method(service) do
|
|
114
|
+
@catalogue_of_life ||= CatalogueOfLife.new
|
|
115
|
+
end
|
|
116
|
+
else
|
|
117
|
+
define_singleton_method(service) { gem_module(gem_name) }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
GEMS.each do |gem_name|
|
|
122
|
+
define_singleton_method(gem_name) { gem_module(gem_name) }
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
Salad::GEMS.each { |g| require g }
|
metadata
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: salad
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Geoff Ower
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: pry
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.15'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.15'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: bond
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.5'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.5'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rb-readline
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0.5'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0.5'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: bananomia
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.1'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.1'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: bell_pepper
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0.1'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0.1'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: bok_choy
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0.0'
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0.0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: checkerberry
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0.0'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0.0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: colrapi
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0.1'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0.1'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: crawlyflower
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0.0'
|
|
131
|
+
type: :runtime
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0.0'
|
|
138
|
+
- !ruby/object:Gem::Dependency
|
|
139
|
+
name: hookkaido
|
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - "~>"
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0.1'
|
|
145
|
+
type: :runtime
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - "~>"
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0.1'
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: nasturtium
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - "~>"
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '0.1'
|
|
159
|
+
type: :runtime
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - "~>"
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '0.1'
|
|
166
|
+
- !ruby/object:Gem::Dependency
|
|
167
|
+
name: plazucchini
|
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - "~>"
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: '0.0'
|
|
173
|
+
type: :runtime
|
|
174
|
+
prerelease: false
|
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - "~>"
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: '0.0'
|
|
180
|
+
- !ruby/object:Gem::Dependency
|
|
181
|
+
name: syconium
|
|
182
|
+
requirement: !ruby/object:Gem::Requirement
|
|
183
|
+
requirements:
|
|
184
|
+
- - "~>"
|
|
185
|
+
- !ruby/object:Gem::Version
|
|
186
|
+
version: '0.0'
|
|
187
|
+
type: :runtime
|
|
188
|
+
prerelease: false
|
|
189
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
190
|
+
requirements:
|
|
191
|
+
- - "~>"
|
|
192
|
+
- !ruby/object:Gem::Version
|
|
193
|
+
version: '0.0'
|
|
194
|
+
- !ruby/object:Gem::Dependency
|
|
195
|
+
name: wikimelon
|
|
196
|
+
requirement: !ruby/object:Gem::Requirement
|
|
197
|
+
requirements:
|
|
198
|
+
- - "~>"
|
|
199
|
+
- !ruby/object:Gem::Version
|
|
200
|
+
version: '0.0'
|
|
201
|
+
type: :runtime
|
|
202
|
+
prerelease: false
|
|
203
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
204
|
+
requirements:
|
|
205
|
+
- - "~>"
|
|
206
|
+
- !ruby/object:Gem::Version
|
|
207
|
+
version: '0.0'
|
|
208
|
+
- !ruby/object:Gem::Dependency
|
|
209
|
+
name: bundler
|
|
210
|
+
requirement: !ruby/object:Gem::Requirement
|
|
211
|
+
requirements:
|
|
212
|
+
- - "~>"
|
|
213
|
+
- !ruby/object:Gem::Version
|
|
214
|
+
version: '2.1'
|
|
215
|
+
type: :development
|
|
216
|
+
prerelease: false
|
|
217
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
218
|
+
requirements:
|
|
219
|
+
- - "~>"
|
|
220
|
+
- !ruby/object:Gem::Version
|
|
221
|
+
version: '2.1'
|
|
222
|
+
- !ruby/object:Gem::Dependency
|
|
223
|
+
name: rake
|
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
|
225
|
+
requirements:
|
|
226
|
+
- - "~>"
|
|
227
|
+
- !ruby/object:Gem::Version
|
|
228
|
+
version: '13.0'
|
|
229
|
+
type: :development
|
|
230
|
+
prerelease: false
|
|
231
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
232
|
+
requirements:
|
|
233
|
+
- - "~>"
|
|
234
|
+
- !ruby/object:Gem::Version
|
|
235
|
+
version: '13.0'
|
|
236
|
+
- !ruby/object:Gem::Dependency
|
|
237
|
+
name: test-unit
|
|
238
|
+
requirement: !ruby/object:Gem::Requirement
|
|
239
|
+
requirements:
|
|
240
|
+
- - "~>"
|
|
241
|
+
- !ruby/object:Gem::Version
|
|
242
|
+
version: '3.6'
|
|
243
|
+
type: :development
|
|
244
|
+
prerelease: false
|
|
245
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
246
|
+
requirements:
|
|
247
|
+
- - "~>"
|
|
248
|
+
- !ruby/object:Gem::Version
|
|
249
|
+
version: '3.6'
|
|
250
|
+
description: salad bundles the SpeciesFileGroup Ruby API wrappers (bananomia, bell_pepper,
|
|
251
|
+
bok_choy, checkerberry, colrapi, crawlyflower, hookkaido, nasturtium, plazucchini,
|
|
252
|
+
syconium, wikimelon) and ships a `salad` executable that launches a Pry console
|
|
253
|
+
with all of them pre-loaded and available under both their service names (Salad.inaturalist)
|
|
254
|
+
and their gem names (Salad.nasturtium).
|
|
255
|
+
email:
|
|
256
|
+
- gdower@illinois.edu
|
|
257
|
+
executables:
|
|
258
|
+
- salad
|
|
259
|
+
extensions: []
|
|
260
|
+
extra_rdoc_files: []
|
|
261
|
+
files:
|
|
262
|
+
- CHANGELOG.md
|
|
263
|
+
- LICENSE.txt
|
|
264
|
+
- README.md
|
|
265
|
+
- exe/salad
|
|
266
|
+
- lib/salad.rb
|
|
267
|
+
- lib/salad/bond_completer.rb
|
|
268
|
+
- lib/salad/catalogue_of_life.rb
|
|
269
|
+
- lib/salad/console.rb
|
|
270
|
+
- lib/salad/gem_help.rb
|
|
271
|
+
- lib/salad/generate_gem_help.rb
|
|
272
|
+
- lib/salad/version.rb
|
|
273
|
+
homepage: https://github.com/SpeciesFileGroup/salad
|
|
274
|
+
licenses:
|
|
275
|
+
- MIT
|
|
276
|
+
metadata:
|
|
277
|
+
homepage_uri: https://github.com/SpeciesFileGroup/salad
|
|
278
|
+
source_code_uri: https://github.com/SpeciesFileGroup/salad
|
|
279
|
+
changelog_uri: https://github.com/SpeciesFileGroup/salad/releases/tag/v0.0.1
|
|
280
|
+
rdoc_options: []
|
|
281
|
+
require_paths:
|
|
282
|
+
- lib
|
|
283
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
284
|
+
requirements:
|
|
285
|
+
- - ">="
|
|
286
|
+
- !ruby/object:Gem::Version
|
|
287
|
+
version: 2.7.0
|
|
288
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
289
|
+
requirements:
|
|
290
|
+
- - ">="
|
|
291
|
+
- !ruby/object:Gem::Version
|
|
292
|
+
version: '0'
|
|
293
|
+
requirements: []
|
|
294
|
+
rubygems_version: 3.6.9
|
|
295
|
+
specification_version: 4
|
|
296
|
+
summary: Unified Pry console for SpeciesFileGroup biodiversity API wrappers.
|
|
297
|
+
test_files: []
|