rider-server 0.1.1 → 0.1.2

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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.build.yml +3 -3
  3. data/CHANGELOG.md +17 -1
  4. data/README.rdoc +39 -0
  5. data/Rakefile +5 -0
  6. data/exe/rider-server +3 -3
  7. data/lib/rider_server/config.rb +76 -0
  8. data/lib/rider_server/core_ext/array.rb +3 -1
  9. data/lib/rider_server/core_ext/class.rb +5 -0
  10. data/lib/rider_server/core_ext/env.rb +14 -0
  11. data/lib/rider_server/core_ext/hash.rb +3 -1
  12. data/lib/rider_server/core_ext/kernel.rb +5 -0
  13. data/lib/rider_server/core_ext/module.rb +18 -0
  14. data/lib/rider_server/core_ext/object.rb +7 -1
  15. data/lib/rider_server/core_ext/string.rb +3 -1
  16. data/lib/rider_server/core_ext/symbol.rb +3 -1
  17. data/lib/rider_server/exception_extension.rb +2 -0
  18. data/lib/rider_server/inspect.rb +108 -32
  19. data/lib/rider_server/logger.rb +11 -4
  20. data/lib/rider_server/operation.rb +39 -20
  21. data/lib/rider_server/{ops → operations}/clone.rb +3 -2
  22. data/lib/rider_server/{ops → operations}/close.rb +3 -2
  23. data/lib/rider_server/operations/completions.rb +146 -0
  24. data/lib/rider_server/operations/lookup.rb +102 -0
  25. data/lib/rider_server/operations/ls_sessions.rb +51 -0
  26. data/lib/rider_server/operations/toggle_catch_all_exceptions.rb +24 -0
  27. data/lib/rider_server/operations.rb +42 -68
  28. data/lib/rider_server/request.rb +61 -0
  29. data/lib/rider_server/response.rb +10 -2
  30. data/lib/rider_server/server.rb +28 -16
  31. data/lib/rider_server/services/capture_exceptions.rb +1 -1
  32. data/lib/rider_server/services/rails.rb +1 -1
  33. data/lib/rider_server/session.rb +75 -44
  34. data/lib/rider_server/session_operation.rb +17 -0
  35. data/lib/rider_server/session_operations/eval.rb +61 -0
  36. data/lib/rider_server/session_operations/inspect.rb +123 -0
  37. data/lib/rider_server/session_operations/inspect_exception.rb +46 -0
  38. data/lib/rider_server/session_operations/interrupt.rb +29 -0
  39. data/lib/rider_server/session_operations/load_path.rb +19 -0
  40. data/lib/rider_server/session_operations/ls_exceptions.rb +28 -0
  41. data/lib/rider_server/session_operations/ls_services.rb +18 -0
  42. data/lib/rider_server/session_operations/service.rb +42 -0
  43. data/lib/rider_server/session_operations/set_namespace.rb +82 -0
  44. data/lib/rider_server/session_operations/set_namespace_variable.rb +81 -0
  45. data/lib/rider_server/session_operations/stdin.rb +19 -0
  46. data/lib/rider_server/utils.rb +7 -7
  47. data/lib/rider_server/validate/array.rb +32 -0
  48. data/lib/rider_server/validate/base.rb +28 -0
  49. data/lib/rider_server/validate/boolean.rb +47 -0
  50. data/lib/rider_server/validate/hash.rb +32 -0
  51. data/lib/rider_server/validate/integer.rb +56 -0
  52. data/lib/rider_server/validate/predicates.rb +30 -0
  53. data/lib/rider_server/validate/string.rb +60 -0
  54. data/lib/rider_server/validate/symbol.rb +90 -0
  55. data/lib/rider_server/validate.rb +15 -0
  56. data/lib/rider_server/version.rb +1 -1
  57. data/lib/rider_server/workspace.rb +1 -1
  58. data/lib/rider_server.rb +3 -1
  59. metadata +54 -24
  60. data/README.md +0 -46
  61. data/lib/rider_server/ops/completions.rb +0 -145
  62. data/lib/rider_server/ops/eval.rb +0 -62
  63. data/lib/rider_server/ops/inspect.rb +0 -121
  64. data/lib/rider_server/ops/inspect_exception.rb +0 -47
  65. data/lib/rider_server/ops/interrupt.rb +0 -30
  66. data/lib/rider_server/ops/load_path.rb +0 -20
  67. data/lib/rider_server/ops/lookup.rb +0 -104
  68. data/lib/rider_server/ops/ls_exceptions.rb +0 -29
  69. data/lib/rider_server/ops/ls_services.rb +0 -19
  70. data/lib/rider_server/ops/ls_sessions.rb +0 -52
  71. data/lib/rider_server/ops/service.rb +0 -43
  72. data/lib/rider_server/ops/set_namespace.rb +0 -79
  73. data/lib/rider_server/ops/set_namespace_variable.rb +0 -80
  74. data/lib/rider_server/ops/stdin.rb +0 -20
  75. data/lib/rider_server/ops/toggle_catch_all_exceptions.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acb6833a29ab9facb82c72d8f2e012ab0dd7a44dbd1ad93dfe69f8d1bff2a765
4
- data.tar.gz: 62834c0a615baa860e1e7650f14353180b874cf877833cc94b6f9804edd32efa
3
+ metadata.gz: 42460de42badb3c5e588c8f606d395f91b8c91f419f119983e18d9ee7833b6c6
4
+ data.tar.gz: 3a1b5c4b92bb2bfe630a01736aa75dfa7eb23cd058686faaa748589d62f95e96
5
5
  SHA512:
6
- metadata.gz: bec9b6906b7e47954bdf9a85fcb3a47ca89d86f63f68023b90d0c8ac83028f6aa7681ad0a4042934cd4a663a0f86f344d8ee11374816efe5616d5eaeaa2a8b75
7
- data.tar.gz: a0d1b287bfeeaf68bbd82c9d72d7bb9405a9873286993e6171cd5f754c545c56cdcde1f186e8c9edb755a1e883a627ce6b33eeea2b21a047220ced97e3e973e5
6
+ metadata.gz: f42e2bb3d67f2922b0fe7a06c027b17a5737361521aa73f41a9b2376d53217f2f81f54066b82ba168ec3f5046dc8b2b238d0c7e2d6d0d8f8db5a6ac1bd279654
7
+ data.tar.gz: 5518b9ca7125186c9c248606b219819b271aa35514518ee90384614c8ccb9e7f0d8e1d1bc22014129d11dda586d849fd31854a7b8309083a0c3f8ac35e4e0acc
data/.build.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  image: debian/stable
2
2
  sources:
3
- - https://git.sr.ht/~rsl/rider
3
+ - https://git.sr.ht/~rsl/rider-server
4
4
  packages:
5
5
  - bundler
6
6
  - curl
@@ -10,11 +10,11 @@ packages:
10
10
  - zlib1g-dev
11
11
  tasks:
12
12
  - lint: |
13
- cd rider
13
+ cd rider-server
14
14
  bundle install --path="../.gems"
15
15
  bundle exec rake standard
16
16
  - test: |
17
- cd rider
17
+ cd rider-server
18
18
  bundle install --path="../.gems"
19
19
  bundle exec rake test
20
20
  triggers:
data/CHANGELOG.md CHANGED
@@ -1,4 +1,20 @@
1
- ## [Unreleased]
1
+ ## [0.1.2] - 2024-08-14
2
+
3
+ - update to latest bencode and remove ruby version limitation
4
+ - request argument validation
5
+ - add a global configuration object and a mechanism to load
6
+ configuration at startup.
7
+ - support setting the caputured exception buffer size.
8
+ - allow setting of the log level
9
+ - enable setting of the current namespace to an element of an array
10
+ - add a separate inspect mechanism for the singleton class
11
+ - fill in missing parameter details in ruby. This is a port of the
12
+ elisp code, and simplifies the Emacs implementation.
13
+ - ENV object printing, previously the env object would print the
14
+ entire env value which is of an unknown size.
15
+ - printing of constant names along with values in inspect view.
16
+ Module constants have a name as a value, but this isn't true for
17
+ other constants.
2
18
 
3
19
  ## [0.1.1] - 2024-07-31
4
20
 
data/README.rdoc ADDED
@@ -0,0 +1,39 @@
1
+ = RIDER -- RIDER Interactive Development Environment for Ruby
2
+
3
+ RIDER Server is the server component of the RIDER development
4
+ environment.
5
+
6
+ == Installation
7
+
8
+ Install the gem and add to the application's Gemfile by executing:
9
+
10
+ $ bundle add rider-server
11
+
12
+ If bundler is not being used to manage dependencies, install the gem by executing:
13
+
14
+ $ gem install rider-server
15
+
16
+ == Usage
17
+
18
+ TODO: Write usage instructions here
19
+
20
+ == Development
21
+
22
+ After checking out the repo, run <tt>bin/setup</tt> to install
23
+ dependencies. Then, run <tt>rake test</tt> to run the tests. You can also run
24
+ <tt>bin/console</tt> for an interactive prompt that will allow you to
25
+ experiment.
26
+
27
+ To install this gem onto your local machine, run <tt>bundle exec rake
28
+ install</tt>.
29
+
30
+ To release a new version run <tt>rake bump:patch</tt> and then run <tt>bundle
31
+ exec rake release</tt>, which will create a git tag for the version, push
32
+ git commits and the created tag, and push the <tt>.gem</tt> file to
33
+ http://rubygems.org.
34
+
35
+ == Contributing
36
+
37
+ Bug reports http://todo.sr.ht/~rsl/rider
38
+
39
+ Support or discussion http://lists.sr.ht/~rsl/rider-devel
data/Rakefile CHANGED
@@ -3,9 +3,14 @@
3
3
  require "bundler/gem_tasks"
4
4
  require "minitest/test_task"
5
5
  require "bump/tasks"
6
+ require "rdoc/task"
6
7
 
7
8
  Bump.tag_by_default = true
8
9
  Minitest::TestTask.create
10
+ RDoc::Task.new do |rdoc|
11
+ rdoc.main = "README.rdoc"
12
+ rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb")
13
+ end
9
14
 
10
15
  require "standard/rake"
11
16
 
data/exe/rider-server CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
7
7
 
8
- require "rider_server/server"
9
-
10
- server = RiderServer::Server.new
8
+ require "rider_server"
9
+ config = RiderServer::Config.new
10
+ server = RiderServer::Server.new(config)
11
11
  server.run
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # config.rb -- A config class for global config
5
+ #
6
+ # Author: Russell Sim
7
+ # Copyright (c) 2024 Russell Sim
8
+ # SPDX-License-Identifier: MIT
9
+
10
+ require "rider_server/validate"
11
+
12
+ module RiderServer
13
+ class Config
14
+ DEFAULTS = {
15
+ host: "localhost",
16
+ port: 7888,
17
+
18
+ # Whether to capture RIDER exceptions and send them to the
19
+ # client.
20
+ capture_exceptions: false,
21
+
22
+ # The number of exceptions to keep in the history.
23
+ exception_history_size: 10,
24
+
25
+ # The log level
26
+ log_level: :INFO
27
+ }
28
+
29
+ def self.configure(&block)
30
+ instance = new
31
+ instance.instance_eval(&block)
32
+ instance
33
+ end
34
+
35
+ # Define a configuration option, +option_name+ is a symbol
36
+ # representing the name of the configuration option, and
37
+ # +validator+ is a Validate object that will be used to validate
38
+ # the value of the option.
39
+ def self.def_option(option_name, validator)
40
+ define_method :"#{option_name}" do |value = nil|
41
+ if value
42
+ @options[option_name] = validator.validate(value)
43
+ else
44
+ unless @options.key?(option_name)
45
+ raise ArgumentError, "Option #{option_name} not set"
46
+ end
47
+
48
+ @options[option_name]
49
+ end
50
+ end
51
+ end
52
+
53
+ def_option :host, Validate.string.not_empty
54
+ def_option :port, Validate.integer.greater_than(0)
55
+ def_option :capture_exceptions, Validate.bool
56
+ def_option :exception_history_size, Validate.integer.greater_than(0)
57
+
58
+ def_option :log_level, Validate.symbol.upcase.one_of(:DEBUG, :INFO, :WARN, :ERROR, :FATAL)
59
+
60
+ attr_reader :options
61
+
62
+ def initialize(config_file: "rider.rb")
63
+ @options = DEFAULTS.dup
64
+
65
+ if File.file?(config_file)
66
+ config.load_from(config_file)
67
+ end
68
+ end
69
+
70
+ # Load configuration from file +path+. The contents of the file
71
+ # will be evaluated within the context of this class instance.
72
+ def load_from(path)
73
+ instance_eval(File.read(path), path, 1)
74
+ end
75
+ end
76
+ end
@@ -8,7 +8,9 @@
8
8
  # SPDX-License-Identifier: MIT
9
9
 
10
10
  class Array
11
- def rider_inspect
11
+ # Return a +string+ representation of the object in a consistent
12
+ # manner that will not be excessivly long.
13
+ def rider_display
12
14
  max_length = 50
13
15
  sample = +""
14
16
 
@@ -0,0 +1,5 @@
1
+ class Class
2
+ def rider_descendants
3
+ ObjectSpace.each_object(::Class).select { |klass| klass < self }
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # env.rb -- ENV extensions
5
+ #
6
+ # Author: Russell Sim
7
+ # Copyright (c) 2024 Russell Sim
8
+ # SPDX-License-Identifier: MIT
9
+
10
+ # Return a +string+ representation of the object in a consistent
11
+ # manner that will not be excessivly long.
12
+ def ENV.rider_display
13
+ "#<ENV #{keys[..3].join(", ")}, ...>"
14
+ end
@@ -8,7 +8,9 @@
8
8
  # SPDX-License-Identifier: MIT
9
9
 
10
10
  class Hash
11
- def rider_inspect
11
+ # Return a +string+ representation of the object in a consistent
12
+ # manner that will not be excessivly long.
13
+ def rider_display
12
14
  "#<#{self.class}: #{length} items}>"
13
15
  end
14
16
  end
@@ -0,0 +1,5 @@
1
+ module Kernel
2
+ def rider_methods
3
+ Kernel.instance_method(:methods).bind_call(self)
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # module.rb -- Module extensions
5
+ #
6
+ # Author: Russell Sim
7
+ # Copyright (c) 2024 Russell Sim
8
+ # SPDX-License-Identifier: MIT
9
+
10
+ class Module
11
+ def rider_inspect
12
+ Module.instance_method(:inspect).bind_call(self)
13
+ end
14
+
15
+ def rider_instance_methods
16
+ Module.instance_method(:instance_methods).bind_call(self)
17
+ end
18
+ end
@@ -8,11 +8,17 @@
8
8
  # SPDX-License-Identifier: MIT
9
9
 
10
10
  class Object
11
- def rider_inspect
11
+ # Return a +string+ representation of the object in a consistent
12
+ # manner that will not be excessivly long.
13
+ def rider_display
12
14
  if defined?(inspect) && method(:inspect).owner != Object && method(:inspect).owner != Kernel
13
15
  inspect
14
16
  else
15
17
  "#<#{self.class} #{object_id}>"
16
18
  end
17
19
  end
20
+
21
+ def rider_inspect
22
+ Object.instance_method(:inspect).bind_call(self)
23
+ end
18
24
  end
@@ -8,7 +8,9 @@
8
8
  # SPDX-License-Identifier: MIT
9
9
 
10
10
  class String
11
- def rider_inspect
11
+ # Return a +string+ representation of the object in a consistent
12
+ # manner that will not be excessivly long.
13
+ def rider_display
12
14
  if length <= 50
13
15
  "#<String #{inspect}>"
14
16
  else
@@ -8,7 +8,9 @@
8
8
  # SPDX-License-Identifier: MIT
9
9
 
10
10
  class Symbol
11
- def rider_inspect
11
+ # Return a +string+ representation of the object in a consistent
12
+ # manner that will not be excessivly long.
13
+ def rider_display
12
14
  ":#{self}"
13
15
  end
14
16
  end
@@ -28,6 +28,8 @@ module RiderServer
28
28
  end
29
29
 
30
30
  unless ::Exception.included_modules.include?(RiderServer::ExceptionExtension)
31
+ # Extend the +exception+ class so that RIDER can capture the
32
+ # backtraces for inspection.
31
33
  class ::Exception
32
34
  prepend RiderServer::ExceptionExtension
33
35
  end
@@ -22,52 +22,128 @@ module RiderServer
22
22
  eval(code, TOPLEVEL_BINDING, file, line) # rubocop:disable Security/Eval
23
23
  end
24
24
 
25
- def self.class(obj)
25
+ def self.safely_location(src)
26
+ loc = safely_eval(src, __FILE__, __LINE__)
27
+ if loc.length == 2 && loc[0].is_a?(String) && loc[1].is_a?(Integer)
28
+ loc
29
+ else
30
+ []
31
+ end
32
+ end
33
+
34
+ def self.inspect_class(obj)
26
35
  klass = obj.class
27
36
  {
28
37
  "name" => klass.to_s,
29
- "value" => Utils.rider_inspect(safely_eval("Object.const_get('#{klass}')", __FILE__, __LINE__)),
38
+ "value" => Utils.rider_display(safely_eval("Object.const_get('#{klass}')", __FILE__, __LINE__)),
30
39
  "inspect-location" => "toplevel_const_get:#{klass.inspect}",
31
40
  "source-location" => safely_eval("Object.const_source_location('#{klass}')", __FILE__, __LINE__) || []
32
41
  }
33
42
  end
34
43
 
35
- def self.ancestors(obj)
44
+ def self.inspect_singleton_class(obj)
45
+ klass = obj.singleton_class
46
+ {
47
+ "name" => klass.to_s,
48
+ "value" => Utils.rider_display(klass),
49
+ "inspect-location" => "singleton_class",
50
+ "source-location" => []
51
+ }
52
+ rescue => e # integers have no singleton
53
+ {
54
+ "name" => e.to_s,
55
+ "value" => Utils.rider_display(e)
56
+ }
57
+ end
58
+
59
+ def self.inspect_ancestors(obj)
36
60
  if obj.respond_to?(:ancestors)
37
61
  obj.ancestors.map do |item|
38
- {
39
- "name" => item.to_s,
40
- "value" => Utils.rider_inspect(item),
41
- "inspect-location" => "ancestor_find:#{item}",
42
- "source-location" => safely_eval("Object.const_source_location('#{item}')", __FILE__, __LINE__) || []
43
- }
62
+ if item.instance_of? ::Module
63
+ {
64
+ "name" => item.to_s,
65
+ "value" => Utils.rider_display(item),
66
+ "inspect-location" => "ancestor_find:#{item}",
67
+ "source-location" => safely_location("Object.const_source_location('#{item}')")
68
+ }
69
+ else
70
+ {
71
+ "name" => item.to_s,
72
+ "value" => Utils.rider_display(item),
73
+ "inspect-location" => "ancestor_find:#{item}",
74
+ "source-location" => []
75
+ }
76
+ end
44
77
  end
45
78
  else
46
79
  []
47
80
  end
48
81
  end
49
82
 
50
- def self.constants(obj)
83
+ def self.inspect_constants(obj)
51
84
  if obj.respond_to?(:constants)
52
- constants = safely_eval("#{obj.inspect}.constants", __FILE__, __LINE__)
85
+ constants = safely_eval("#{obj.rider_inspect}.constants", __FILE__, __LINE__)
53
86
  return [] if constants.nil? # Eigen classes have no constants
54
87
  constants.map do |item|
55
- {
56
- "name" => item.to_s,
57
- "value" => Utils.rider_inspect(safely_eval("#{obj.inspect}.const_get('#{item}')", __FILE__, __LINE__)),
58
- "inspect-location" => "const_get:#{obj.inspect}::#{item}",
59
- "source-location" => safely_eval("#{obj.inspect}.const_source_location('#{item}')", __FILE__, __LINE__) || []
60
- }
61
- end.sort_by { |hash| hash["name"] }
88
+ [
89
+ {
90
+ "name" => item.to_s
91
+ },
92
+ {
93
+ "name" => item.to_s,
94
+ "value" => Utils.rider_display(safely_eval("#{obj.rider_inspect}.const_get('#{item}')", __FILE__, __LINE__)),
95
+ "inspect-location" => "const_get:#{obj.rider_inspect}::#{item}",
96
+ "source-location" => safely_location("#{obj.rider_inspect}.const_source_location('#{item}')")
97
+ }
98
+ ]
99
+ end.sort_by { |hash| hash[0]["name"] }
62
100
  else
63
101
  []
64
102
  end
65
103
  end
66
104
 
105
+ def self.inspect_parameters(parameters)
106
+ alpha = Enumerator.new do |y|
107
+ ("a".."z").each { |char| y << char }
108
+ end
109
+
110
+ parameters.map do |params|
111
+ arg, name = params
112
+ if arg == :rest
113
+ "*#{name || "args"}"
114
+ elsif arg == :keyrest
115
+ if name.nil? || name == "**"
116
+ "**kwargs"
117
+ else
118
+ name
119
+ end
120
+ elsif arg == :req
121
+ name || alpha.next
122
+ elsif arg == :keyreq
123
+ "#{name || alpha.next}: ..."
124
+ elsif arg == :key
125
+ "#{name || alpha.next}:"
126
+ elsif arg == :opt
127
+ "#{name || alpha.next}=..."
128
+ elsif arg == :block
129
+ "&block"
130
+ else
131
+ raise "Unknown prameter format #{arg}"
132
+ end.to_s
133
+ end
134
+ end
135
+
67
136
  def self.describe_method(method)
137
+ loc = method.source_location
138
+ method_location = if !loc.nil? && loc.length == 2 && loc[0].is_a?(String) && loc[1].is_a?(Integer)
139
+ loc
140
+ else
141
+ []
142
+ end
143
+
68
144
  {
69
145
  "name" => method.name.to_s,
70
- "value" => Utils.rider_inspect(method),
146
+ "value" => Utils.rider_display(method),
71
147
  "visibility" => if method.private?
72
148
  ":private"
73
149
  elsif method.protected?
@@ -77,15 +153,15 @@ module RiderServer
77
153
  else
78
154
  ":unknown"
79
155
  end,
80
- "owner" => method.owner.inspect,
81
- "source-location" => method.source_location || [],
82
- "parameters" => method.parameters.map { |subarray| subarray.map(&:to_s) }
156
+ "owner" => method.owner.rider_inspect,
157
+ "source-location" => method_location,
158
+ "parameters" => inspect_parameters(method.parameters)
83
159
  }
84
160
  end
85
161
 
86
- def self.methods(obj)
87
- if obj.respond_to?(:methods)
88
- obj.methods.map do |name|
162
+ def self.inspect_methods(obj)
163
+ if obj.respond_to?(:rider_methods)
164
+ obj.rider_methods.map do |name|
89
165
  describe_method(obj.method(name))
90
166
  end
91
167
  else
@@ -93,9 +169,9 @@ module RiderServer
93
169
  end
94
170
  end
95
171
 
96
- def self.instance_methods(obj)
97
- if obj.respond_to?(:instance_methods)
98
- obj.instance_methods.map do |item|
172
+ def self.inspect_instance_methods(obj)
173
+ if obj.respond_to?(:rider_instance_methods)
174
+ obj.rider_instance_methods.map do |item|
99
175
  describe_method(obj.instance_method(item))
100
176
  end
101
177
  else
@@ -103,7 +179,7 @@ module RiderServer
103
179
  end
104
180
  end
105
181
 
106
- def self.instance_variables(obj)
182
+ def self.inspect_instance_variables(obj)
107
183
  if obj.respond_to?(:instance_variables)
108
184
  obj.instance_variables.map do |item|
109
185
  [
@@ -112,7 +188,7 @@ module RiderServer
112
188
  },
113
189
  {
114
190
  "name" => obj.instance_variable_get(item).to_s,
115
- "value" => Utils.rider_inspect(obj.instance_variable_get(item)),
191
+ "value" => Utils.rider_display(obj.instance_variable_get(item)),
116
192
  "inspect-location" => "instance_variable_get:#{item}"
117
193
  }
118
194
  ]
@@ -122,7 +198,7 @@ module RiderServer
122
198
  end
123
199
  end
124
200
 
125
- def self.class_variables(obj)
201
+ def self.inspect_class_variables(obj)
126
202
  if obj.respond_to?(:class_variables)
127
203
  obj.class_variables.map do |item|
128
204
  [
@@ -131,7 +207,7 @@ module RiderServer
131
207
  },
132
208
  {
133
209
  "name" => obj.class_variable_get(item).to_s,
134
- "value" => Utils.rider_inspect(obj.class_variable_get(item)),
210
+ "value" => Utils.rider_display(obj.class_variable_get(item)),
135
211
  "inspect-location" => "class_variable_get:#{item}"
136
212
  }
137
213
  ]
@@ -2,12 +2,19 @@ require "logger"
2
2
 
3
3
  module RiderServer
4
4
  module Logger
5
- def log
6
- @logger ||= begin
7
- log_level = (ENV["LOG_LEVEL"] || "INFO").upcase.to_sym
5
+ class << self
6
+ def configure_logger(logdev: ::STDERR, level: ENV["LOG_LEVEL"] || "INFO") # rubocop:disable Style/GlobalStdStream
7
+ log_level = level.upcase.to_sym
8
+ @@logger = ::Logger.new(logdev, level: log_level)
9
+ end
8
10
 
9
- ::Logger.new(STDERR, level: log_level) # rubocop:disable Style/GlobalStdStream
11
+ def log
12
+ @@logger ||= configure_logger
10
13
  end
11
14
  end
15
+
16
+ def log
17
+ Logger.log
18
+ end
12
19
  end
13
20
  end
@@ -13,38 +13,57 @@ module RiderServer
13
13
  class Operation
14
14
  include RiderServer::Logger
15
15
 
16
- attr_reader :documentation, :arguments, :controller
17
- def self.operation_name
18
- name.split("::").last.gsub(/(.)([A-Z])/, '\1_\2').downcase
16
+ # Operations registry
17
+ @operations = {}
18
+ class << self
19
+ attr_reader :operations
19
20
  end
20
21
 
21
- def self.documentation(desc)
22
- @documentation = desc
22
+ def self.handles?(request)
23
+ @operations.key? request.op
23
24
  end
24
25
 
25
- def self.argument(name, type, description, required: false)
26
- @arguments ||= []
26
+ def self.handle(context, request)
27
+ operation = @operations[request.op]
28
+ operation.validate_request!(request)
29
+ operation.handle(context, request)
30
+ end
27
31
 
28
- raise ArgumentError, "Invalid argument type #{type}" \
29
- unless [:string, :integer, :array].include?(type)
32
+ def self.define(&block)
33
+ instance = new
34
+ instance.instance_eval(&block)
35
+ raise ArgumentError, "Operation #{self} must have a name" if instance.name.empty?
36
+ raise ArgumentError, "Operation #{self} must have a documentation string" if instance.documentation.empty?
37
+ raise ArgumentError, "Operation #{self} must have at least one argument" if instance.arguments.empty?
38
+ @operations[instance.name] = instance
39
+ instance
40
+ end
30
41
 
31
- @arguments << {name: name, type: type, required: required, description: description}
42
+ attr_reader :arguments
43
+
44
+ def documentation(value = nil)
45
+ @documentation = value if value
46
+ @documentation
32
47
  end
33
48
 
34
- def initialize(controller)
35
- @controller = controller
36
- @documentation = self.class.instance_variable_get(:@documentation) || ""
37
- @arguments = self.class.instance_variable_get(:@arguments) || []
38
- raise ArgumentError, "Operation must have a documentation string" if @documentation.empty?
39
- raise ArgumentError, "Operation must have at least one argument" if @arguments.empty?
49
+ def name(value = nil)
50
+ @name = value if value
51
+ @name
40
52
  end
41
53
 
42
- def create_response(operation)
43
- Utils.create_response(operation)
54
+ def initialize
55
+ @name = ""
56
+ @arguments = []
57
+ @documentation = ""
44
58
  end
45
59
 
46
- def send_response(response)
47
- controller.send_response(response)
60
+ def argument(name, type, description, required: false)
61
+ @arguments ||= []
62
+
63
+ raise ArgumentError, "Invalid argument type #{type}" \
64
+ unless [:string, :integer, :array].include?(type)
65
+
66
+ @arguments << {name: name, type: type, required: required, description: description}
48
67
  end
49
68
 
50
69
  def validate_request!(request)
@@ -3,14 +3,15 @@ require "rider_server/response"
3
3
 
4
4
  module RiderServer
5
5
  module Ops
6
- class Clone < Operation
6
+ Operation.define do
7
+ name "clone"
7
8
  documentation "Clone a session"
8
9
 
9
10
  argument :id, :string, "The request id", required: true
10
11
  argument :session, :string, "The session to clone"
11
12
 
12
13
  # Handle the clone operation, session will be nil
13
- def handle(session, operation)
14
+ def handle(controller, operation)
14
15
  response = Response.new(operation)
15
16
 
16
17
  # Clone a specific session if specified