solargraph 0.16.0 → 0.17.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.
@@ -27,25 +27,22 @@ module Solargraph
27
27
  Server.prepare_workspace params['workspace']
28
28
  { "status" => "ok"}.to_json
29
29
  rescue Exception => e
30
- STDERR.puts e
31
- STDERR.puts e.backtrace.join("\n")
32
- { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
30
+ send_exception e
33
31
  end
34
32
  end
35
33
 
36
34
  post '/update' do
37
35
  content_type :json
38
36
  begin
37
+ workspace = find_local_workspace(params['filename'], params['workspace'])
39
38
  # @type [Solargraph::ApiMap]
40
- api_map = get_api_map(params['workspace'])
39
+ api_map = get_api_map(workspace)
41
40
  unless api_map.nil?
42
41
  api_map.update params['filename']
43
42
  end
44
43
  { "status" => "ok"}.to_json
45
44
  rescue Exception => e
46
- STDERR.puts e
47
- STDERR.puts e.backtrace.join("\n")
48
- { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
45
+ send_exception e
49
46
  end
50
47
  end
51
48
 
@@ -53,17 +50,15 @@ module Solargraph
53
50
  content_type :json
54
51
  begin
55
52
  sugg = []
56
- workspace = params['workspace']
53
+ workspace = find_local_workspace(params['filename'], params['workspace'])
57
54
  api_map = get_api_map(workspace)
58
55
  with_all = params['all'] == '1' ? true : false
59
56
  code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: api_map, cursor: [params['line'].to_i, params['column'].to_i])
60
57
  offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
61
- sugg = code_map.suggest_at(offset, with_snippets: params['with_snippets'] == '1' ? true : false, filtered: true)
58
+ sugg = code_map.suggest_at(offset, filtered: true)
62
59
  JSON.generate({ "status" => "ok", "suggestions" => sugg.map{|s| s.as_json(all: with_all)} })
63
60
  rescue Exception => e
64
- STDERR.puts e
65
- STDERR.puts e.backtrace.join("\n")
66
- { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
61
+ send_exception e
67
62
  end
68
63
  end
69
64
 
@@ -71,23 +66,21 @@ module Solargraph
71
66
  content_type :json
72
67
  begin
73
68
  sugg = []
74
- workspace = params['workspace'] || nil
69
+ workspace = find_local_workspace(params['filename'], params['workspace'])
75
70
  api_map = get_api_map(workspace)
76
71
  code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: api_map, cursor: [params['line'].to_i, params['column'].to_i])
77
72
  offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
78
73
  sugg = code_map.signatures_at(offset)
79
74
  { "status" => "ok", "suggestions" => sugg.map{|s| s.as_json(all: true)} }.to_json
80
75
  rescue Exception => e
81
- STDERR.puts e
82
- STDERR.puts e.backtrace.join("\n")
83
- { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
76
+ send_exception e
84
77
  end
85
78
  end
86
79
 
87
80
  post '/resolve' do
88
81
  content_type :json
89
82
  begin
90
- workspace = params['workspace'] || nil
83
+ workspace = find_local_workspace(params['filename'], params['workspace'])
91
84
  result = []
92
85
  api_map = get_api_map(workspace)
93
86
  unless api_map.nil?
@@ -96,26 +89,38 @@ module Solargraph
96
89
  end
97
90
  { "status" => "ok", "suggestions" => result.map{|s| s.as_json(all: true)} }.to_json
98
91
  rescue Exception => e
99
- STDERR.puts e
100
- STDERR.puts e.backtrace.join("\n")
101
- { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
92
+ send_exception e
93
+ end
94
+ end
95
+
96
+ post '/define' do
97
+ content_type :json
98
+ begin
99
+ sugg = []
100
+ workspace = find_local_workspace(params['filename'], params['workspace'])
101
+ api_map = get_api_map(workspace)
102
+ code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: @@api_hash[workspace], cursor: [params['line'].to_i, params['column'].to_i])
103
+ offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
104
+ sugg = code_map.define_symbol_at(offset)
105
+ { "status" => "ok", "suggestions" => sugg }.to_json
106
+ rescue Exception => e
107
+ send_exception e
102
108
  end
103
109
  end
104
110
 
111
+ # @deprecated Use /define instead.
105
112
  post '/hover' do
106
113
  content_type :json
107
114
  begin
108
115
  sugg = []
109
- workspace = params['workspace'] || nil
116
+ workspace = find_local_workspace(params['filename'], params['workspace'])
110
117
  api_map = get_api_map(workspace)
111
118
  code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: @@api_hash[workspace], cursor: [params['line'].to_i, params['column'].to_i])
112
119
  offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
113
120
  sugg = code_map.resolve_object_at(offset)
114
121
  { "status" => "ok", "suggestions" => sugg }.to_json
115
122
  rescue Exception => e
116
- STDERR.puts e
117
- STDERR.puts e.backtrace.join("\n")
118
- { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
123
+ send_exception e
119
124
  end
120
125
  end
121
126
 
@@ -128,6 +133,7 @@ module Solargraph
128
133
 
129
134
  get '/document' do
130
135
  workspace = params['workspace']
136
+ workspace.gsub!(/\\/, '/') unless workspace.nil?
131
137
  api_map = get_api_map(workspace) || Solargraph::ApiMap.new
132
138
  @objects = api_map.document(params['query'])
133
139
  erb :document
@@ -161,28 +167,61 @@ module Solargraph
161
167
  h.html_markup_ruby(code)
162
168
  end
163
169
 
170
+ def send_exception e
171
+ STDERR.puts e
172
+ STDERR.puts e.backtrace.join("\n")
173
+ { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
174
+ end
175
+
176
+ def find_local_workspace file, workspace
177
+ workspace.gsub!(/\\/, '/') unless workspace.nil?
178
+ unless file.nil? or workspace.nil?
179
+ file.gsub!(/\\/, '/') unless file.nil?
180
+ return nil unless file.start_with?(workspace)
181
+ dir = File.dirname(file)
182
+ while dir.start_with?(workspace)
183
+ return dir if @@api_hash.has_key?(dir)
184
+ dir = File.dirname(dir)
185
+ end
186
+ end
187
+ workspace
188
+ end
189
+
164
190
  class << self
165
191
  def prepare_workspace directory
192
+ return if directory.nil?
166
193
  Thread.new do
167
- api_map = Solargraph::ApiMap.new(directory)
168
- api_map.yard_map
169
- @@semaphore.synchronize do
170
- @@api_hash[directory] = api_map
194
+ directory.gsub!(/\\/, '/') unless directory.nil?
195
+ configs = Dir[File.join(directory, '**', '.solargraph.yml')]
196
+ resolved = []
197
+ configs.each do |cf|
198
+ dir = File.dirname(cf)
199
+ generate_api_map dir
200
+ resolved.push dir
171
201
  end
202
+ generate_api_map directory unless resolved.include?(directory)
203
+ end
204
+ end
205
+
206
+ def generate_api_map(directory)
207
+ api_map = Solargraph::ApiMap.new(directory)
208
+ api_map.yard_map
209
+ @@semaphore.synchronize do
210
+ @@api_hash[directory] = api_map
172
211
  end
173
212
  end
174
213
 
175
214
  def run!
176
215
  Thread.new do
177
216
  while true
178
- watch_workspaces
217
+ check_workspaces
179
218
  sleep 1
180
219
  end
181
220
  end
182
221
  super
183
222
  end
184
223
 
185
- def watch_workspaces
224
+ def check_workspaces
186
225
  @@semaphore.synchronize do
187
226
  changed = {}
188
227
  @@api_hash.each_pair do |w, a|
@@ -56,7 +56,7 @@ module Solargraph
56
56
  begin
57
57
  code_map = CodeMap.new(code: text, filename: filename)
58
58
  offset = code_map.get_offset(options[:line], options[:column])
59
- sugg = code_map.suggest_at(offset, with_snippets: true, filtered: true)
59
+ sugg = code_map.suggest_at(offset, filtered: true)
60
60
  result = { "status" => "ok", "suggestions" => sugg }.to_json
61
61
  STDOUT.puts result
62
62
  rescue Exception => e
@@ -11,7 +11,6 @@ module Solargraph
11
11
  METHOD = 'Method'
12
12
  MODULE = 'Module'
13
13
  PROPERTY = 'Property'
14
- SNIPPET = 'Snippet'
15
14
  VARIABLE = 'Variable'
16
15
 
17
16
  # @return [String]
@@ -65,6 +64,10 @@ module Solargraph
65
64
  @path ||= (code_object.nil? ? label : code_object.path)
66
65
  end
67
66
 
67
+ def namespace
68
+ @namespace ||= path.split(/[#\.]/)[0]
69
+ end
70
+
68
71
  # @return [String]
69
72
  def to_s
70
73
  label
@@ -114,7 +117,8 @@ module Solargraph
114
117
  #
115
118
  # @return [Boolean]
116
119
  def has_doc?
117
- !documentation.empty?
120
+ #!documentation.empty?
121
+ !docstring.nil? and !docstring.all.empty?
118
122
  end
119
123
 
120
124
  def as_json args = {}
@@ -142,7 +146,7 @@ module Solargraph
142
146
  #
143
147
  # @param pin [Solargraph::Pin::Base]
144
148
  def self.pull pin, return_type = nil
145
- Suggestion.new(pin.name, insert: pin.name.gsub(/=/, ' = '), kind: pin.kind, docstring: pin.docstring, detail: pin.namespace, arguments: pin.parameters, path: pin.path, return_type: return_type || pin.return_type, location: pin.location)
149
+ Suggestion.new(pin.name, insert: pin.name.gsub(/=$/, ' = '), kind: pin.kind, docstring: pin.docstring, detail: pin.namespace, arguments: pin.parameters, path: pin.path, return_type: return_type || pin.return_type, location: pin.location)
146
150
  end
147
151
  end
148
152
  end
@@ -1,3 +1,3 @@
1
1
  module Solargraph
2
- VERSION = '0.16.0'
2
+ VERSION = '0.17.0'
3
3
  end
@@ -8,7 +8,7 @@ module Solargraph
8
8
  module CoreDocs
9
9
  class SourceNotAvailableError < StandardError;end
10
10
 
11
- SOURCE = 'http://solargraph.org/download'
11
+ SOURCE = 'https://solargraph.org/download'
12
12
 
13
13
  class << self
14
14
  def cache_dir
@@ -1,4 +1,5 @@
1
1
  require 'yard'
2
+ require 'bundler'
2
3
 
3
4
  module Solargraph
4
5
  class YardMap
@@ -18,24 +19,17 @@ module Solargraph
18
19
 
19
20
  def initialize required: [], workspace: nil
20
21
  @workspace = workspace
21
- used = []
22
22
  # HACK: YardMap needs its own copy of this array
23
23
  @required = required.clone
24
24
  @namespace_yardocs = {}
25
- @required.each do |r|
26
- if workspace.nil? or !File.exist?(File.join workspace, 'lib', "#{r}.rb")
27
- g = r.split('/').first
28
- unless used.include?(g)
29
- used.push g
30
- gy = YARD::Registry.yardoc_file_for_gem(g)
31
- if gy.nil?
32
- STDERR.puts "Required path not found: #{r}"
33
- else
34
- yardocs.unshift gy
35
- add_gem_dependencies g
36
- end
25
+ if !workspace.nil? and File.exist?(File.join workspace, 'Gemfile')
26
+ Bundler.with_clean_env do
27
+ Bundler.environment.chdir(workspace) do
28
+ process_requires
37
29
  end
38
30
  end
31
+ else
32
+ process_requires
39
33
  end
40
34
  yardocs.push CoreDocs.yardoc_file
41
35
  yardocs.uniq!
@@ -154,11 +148,11 @@ module Solargraph
154
148
  ns = find_first_resolved_namespace(yard, namespace, scope)
155
149
  unless ns.nil?
156
150
  ns.meths(scope: :class, visibility: visibility).each { |m|
157
- n = m.to_s.split(/[\.#]/).last.gsub(/=/, ' = ')
151
+ n = m.to_s.split(/[\.#]/).last.gsub(/=$/, ' = ')
158
152
  label = "#{n}"
159
153
  args = get_method_args(m)
160
154
  kind = (m.is_attribute? ? Suggestion::FIELD : Suggestion::METHOD)
161
- meths.push Suggestion.new(label, insert: "#{n.gsub(/=/, ' = ')}", kind: kind, docstring: m.docstring, code_object: m, detail: "#{ns}", location: "#{m.file}:#{m.line}", arguments: args)
155
+ meths.push Suggestion.new(label, insert: n, kind: kind, docstring: m.docstring, code_object: m, detail: "#{ns}", location: object_location(m), arguments: args)
162
156
  }
163
157
  # Collect superclass methods
164
158
  if ns.kind_of?(YARD::CodeObjects::ClassObject) and !ns.superclass.nil?
@@ -172,7 +166,7 @@ module Solargraph
172
166
  meths.delete_if{|m| m.label == 'new'}
173
167
  label = "#{i}"
174
168
  args = get_method_args(i)
175
- meths.push Suggestion.new('new', kind: Suggestion::METHOD, docstring: i.docstring, code_object: i, detail: "#{ns}", location: "#{i.file}:#{i.line}", arguments: args)
169
+ meths.push Suggestion.new('new', kind: Suggestion::METHOD, docstring: i.docstring, code_object: i, detail: "#{ns}", location: object_location(i), arguments: args)
176
170
  end
177
171
  end
178
172
  end
@@ -197,11 +191,13 @@ module Solargraph
197
191
  unless ns.nil?
198
192
  ns.meths(scope: :instance, visibility: visibility).each { |m|
199
193
  n = m.to_s.split(/[\.#]/).last
200
- if n.to_s.match(/^[a-z]/i) and (namespace == 'Kernel' or !m.to_s.start_with?('Kernel#')) and !m.docstring.to_s.include?(':nodoc:')
194
+ # @todo Return method names like []?
195
+ #if n.to_s.match(/^[a-z]/i) and (namespace == 'Kernel' or !m.to_s.start_with?('Kernel#')) and !m.docstring.to_s.include?(':nodoc:')
196
+ if (namespace == 'Kernel' or !m.to_s.start_with?('Kernel#')) and !m.docstring.to_s.include?(':nodoc:')
201
197
  label = "#{n}"
202
198
  args = get_method_args(m)
203
199
  kind = (m.is_attribute? ? Suggestion::FIELD : Suggestion::METHOD)
204
- meths.push Suggestion.new(label, insert: "#{n.gsub(/=/, ' = ')}", kind: kind, docstring: m.docstring, code_object: m, detail: m.namespace, location: "#{m.file}:#{m.line}", arguments: args)
200
+ meths.push Suggestion.new(label, insert: "#{n.gsub(/=$/, ' = ')}", kind: kind, docstring: m.docstring, code_object: m, detail: m.namespace, location: object_location(m), arguments: args)
205
201
  end
206
202
  }
207
203
  if ns.kind_of?(YARD::CodeObjects::ClassObject) and namespace != 'Object'
@@ -361,6 +357,53 @@ module Solargraph
361
357
  end
362
358
  end
363
359
 
360
+ def process_requires
361
+ used = []
362
+ @required.each do |r|
363
+ if workspace.nil? or !File.exist?(File.join workspace, 'lib', "#{r}.rb")
364
+ unless used.include?(r)
365
+ used.push r
366
+ result = find_yardoc(r)
367
+ if result.nil?
368
+ STDERR.puts "Required path not found: #{r}"
369
+ else
370
+ yardocs.unshift result unless yardocs.include?(result)
371
+ end
372
+ end
373
+ end
374
+ end
375
+ end
376
+
377
+ def find_yardoc path
378
+ result = nil
379
+ spec = Gem::Specification.find_by_path(path)
380
+ result = YARD::Registry.yardoc_file_for_gem(spec.name) unless spec.nil?
381
+ if result.nil?
382
+ $LOAD_PATH.each do |base|
383
+ source_file = File.join(base, "#{path}.rb")
384
+ if File.exist?(source_file)
385
+ if base.start_with?(Bundler.bundle_path.to_s)
386
+ match = File.dirname(base).split('/').last.match(/^([a-z0-9\-_]*?)-([0-9]+\.[0-9]+\.[0-9]+)/i)
387
+ unless match.nil? or match[1].nil?
388
+ result = YARD::Registry.yardoc_file_for_gem(match[1])
389
+ add_gem_dependencies match[1]
390
+ break
391
+ end
392
+ end
393
+ yp = File.join(File.dirname(base), '.yardoc')
394
+ if File.exist?(yp)
395
+ result = yp
396
+ break
397
+ else
398
+ # @todo Keep trying?
399
+ end
400
+ break
401
+ end
402
+ end
403
+ end
404
+ result
405
+ end
406
+
364
407
  def add_gem_dependencies gem_name
365
408
  spec = Gem::Specification.find_by_name(gem_name)
366
409
  (spec.dependencies - spec.development_dependencies).each do |dep|
@@ -368,8 +411,7 @@ module Solargraph
368
411
  if gy.nil?
369
412
  STDERR.puts "Required path not found: #{dep.name}"
370
413
  else
371
- #STDERR.puts "Adding #{gy}"
372
- yardocs.unshift gy
414
+ yardocs.unshift gy unless yardocs.include?(gy)
373
415
  end
374
416
  end
375
417
  end
@@ -396,5 +438,14 @@ module Solargraph
396
438
  result.push @@stdlib_yardoc if result.empty? and @@stdlib_namespaces.include?(namespace)
397
439
  result
398
440
  end
441
+
442
+ # @param obj [YARD::CodeObjects::Base]
443
+ def object_location obj
444
+ # @todo Locations from YardMaps are temporarily disabled pending a
445
+ # method for resolving the source file's absolute path.
446
+ return nil
447
+ return nil if obj.file.nil? or obj.line.nil?
448
+ "#{obj.file}:#{obj.line - 1}:0"
449
+ end
399
450
  end
400
451
  end
data/lib/solargraph.rb CHANGED
@@ -8,13 +8,13 @@ module Solargraph
8
8
  autoload :CodeMap, 'solargraph/code_map'
9
9
  autoload :NodeMethods, 'solargraph/node_methods'
10
10
  autoload :Suggestion, 'solargraph/suggestion'
11
- autoload :Snippets, 'solargraph/snippets'
12
11
  autoload :Server, 'solargraph/server'
13
12
  autoload :YardMap, 'solargraph/yard_map'
14
13
  autoload :Pin, 'solargraph/pin'
15
14
  autoload :LiveMap, 'solargraph/live_map'
16
15
  autoload :ServerMethods, 'solargraph/server_methods'
17
16
  autoload :Plugin, 'solargraph/plugin'
17
+ autoload :CoreFills, 'solargraph/core_fills'
18
18
 
19
19
  YARDOC_PATH = File.join(File.realpath(File.dirname(__FILE__)), '..', 'yardoc')
20
20
  YARD_EXTENSION_FILE = File.join(File.realpath(File.dirname(__FILE__)), 'yard-solargraph.rb')
@@ -1,4 +1,6 @@
1
1
  require 'yard'
2
2
 
3
- # Define a @type tag to be used for documenting variables
3
+ # Define a @type tag for documenting variables
4
4
  YARD::Tags::Library.define_tag("Type", :type, :with_types_and_name)
5
+ # Define a @yieldself tag for documenting block contexts
6
+ YARD::Tags::Library.define_tag("Yieldself", :yieldself, :with_types)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-17 00:00:00.000000000 Z
11
+ date: 2018-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -170,6 +170,7 @@ executables:
170
170
  extensions: []
171
171
  extra_rdoc_files: []
172
172
  files:
173
+ - ".yardopts"
173
174
  - bin/solargraph
174
175
  - bin/solargraph-runtime
175
176
  - lib/solargraph.rb
@@ -179,6 +180,7 @@ files:
179
180
  - lib/solargraph/api_map/source.rb
180
181
  - lib/solargraph/api_map/source_to_yard.rb
181
182
  - lib/solargraph/code_map.rb
183
+ - lib/solargraph/core_fills.rb
182
184
  - lib/solargraph/live_map.rb
183
185
  - lib/solargraph/live_map/cache.rb
184
186
  - lib/solargraph/node_methods.rb
@@ -206,7 +208,6 @@ files:
206
208
  - lib/solargraph/server.rb
207
209
  - lib/solargraph/server_methods.rb
208
210
  - lib/solargraph/shell.rb
209
- - lib/solargraph/snippets.rb
210
211
  - lib/solargraph/suggestion.rb
211
212
  - lib/solargraph/version.rb
212
213
  - lib/solargraph/views/_method.erb
@@ -1,186 +0,0 @@
1
- require 'json'
2
-
3
- module Solargraph
4
- module Snippets
5
- def self.definitions
6
- @definitions ||= JSON.parse('{
7
- "Exception block": {
8
- "prefix": "begin",
9
- "body": [
10
- "begin",
11
- "\t$1",
12
- "rescue => exception",
13
- "\t",
14
- "end"
15
- ]
16
- },
17
- "Exception block with ensure": {
18
- "prefix": "begin ensure",
19
- "body": [
20
- "begin",
21
- "\t$1",
22
- "rescue => exception",
23
- "\t",
24
- "ensure",
25
- "\t",
26
- "end"
27
- ]
28
- },
29
- "Exception block with else": {
30
- "prefix": "begin else",
31
- "body": [
32
- "begin",
33
- "\t$1",
34
- "rescue => exception",
35
- "\t",
36
- "else",
37
- "\t",
38
- "end"
39
- ]
40
- },
41
- "Exception block with else and ensure": {
42
- "prefix": "begin else ensure",
43
- "body": [
44
- "begin",
45
- "\t$1",
46
- "rescue => exception",
47
- "\t",
48
- "else",
49
- "\t",
50
- "ensure",
51
- "\t",
52
- "end"
53
- ]
54
- },
55
- "Class definition with initialize": {
56
- "prefix": "class init",
57
- "body": [
58
- "class ${ClassName}",
59
- "\tdef initialize",
60
- "\t\t$0",
61
- "\tend",
62
- "end"
63
- ]
64
- },
65
- "Class definition": {
66
- "prefix": "class",
67
- "body": [
68
- "class ${ClassName}",
69
- "\t$0",
70
- "end"
71
- ]
72
- },
73
- "for loop": {
74
- "prefix": "for",
75
- "body": [
76
- "for ${value} in ${enumerable} do",
77
- "\t$0",
78
- "end"
79
- ]
80
- },
81
- "if": {
82
- "prefix": "if",
83
- "body": [
84
- "if ${test}",
85
- "\t$0",
86
- "end"
87
- ]
88
- },
89
- "if else": {
90
- "prefix": "if else",
91
- "body": [
92
- "if ${test}",
93
- "\t$0",
94
- "else",
95
- "\t",
96
- "end"
97
- ]
98
- },
99
- "if elsif": {
100
- "prefix": "if elsif",
101
- "body": [
102
- "if ${test}",
103
- "\t$0",
104
- "elsif ",
105
- "\t",
106
- "end"
107
- ]
108
- },
109
- "if elsif else": {
110
- "prefix": "if elsif else",
111
- "body": [
112
- "if ${test}",
113
- "\t$0",
114
- "elsif ",
115
- "\t",
116
- "else",
117
- "\t",
118
- "end"
119
- ]
120
- },
121
- "forever loop": {
122
- "prefix": "loop",
123
- "body": [
124
- "loop do",
125
- "\t$0",
126
- "end"
127
- ]
128
- },
129
- "Module definition": {
130
- "prefix": "module",
131
- "body": [
132
- "module ${ModuleName}",
133
- "\t$0",
134
- "end"
135
- ]
136
- },
137
- "unless": {
138
- "prefix": "unless",
139
- "body": [
140
- "unless ${test}",
141
- "\t$0",
142
- "end"
143
- ]
144
- },
145
- "until loop": {
146
- "prefix": "until",
147
- "body": [
148
- "until ${test}",
149
- "\t$0",
150
- "end"
151
- ]
152
- },
153
- "while loop": {
154
- "prefix": "while",
155
- "body": [
156
- "while ${test}",
157
- "\t$0",
158
- "end"
159
- ]
160
- },
161
- "method definition": {
162
- "prefix": "def",
163
- "body": [
164
- "def ${method_name}",
165
- "\t$0",
166
- "end"
167
- ],
168
- "description": "Snippet for method definitions"
169
- },
170
- "defined?": {
171
- "prefix": "defined?",
172
- "body": [
173
- "defined?"
174
- ],
175
- "description": "Something silly"
176
- }
177
- }')
178
- end
179
-
180
- def self.keywords
181
- @keywords ||= [
182
- 'begin', 'class', 'for', 'if', 'module', 'unless', 'until', 'while', 'def', 'defined?'
183
- ]
184
- end
185
- end
186
- end