irb-kit 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd95b94c3b604ba8c6c5c239475a99ab603815ba86d98587193063515b676fd2
4
- data.tar.gz: e2082fe9b9e281291c2e67ec6b54e2ea7359c50178d625cf96faa05ce225ece8
3
+ metadata.gz: b692329d2278f59f1ce6f20d56821972cd9b77ade76381f2c3f11da5630e18af
4
+ data.tar.gz: f2c933bc7b3b019b39680217e09e522df7ba3a8e5ba4e4d133c035b061bff14e
5
5
  SHA512:
6
- metadata.gz: a5bbb32382af12000c59e762774961637a00285f55355eed10d7feead6d6f015397661ec99a9ad0e29e7036a26cc938b89c3aa75ee6d96b1d2c0e6fd4c9f77bf
7
- data.tar.gz: cc2472d1fd8069b751816de1f5c62574236dc999b59c380b886b5e2e0b1b5a8911935fe2c6b2fc9e9b738e9626f6c78699ae3d16d25bae5c5ff3ea63778b5837
6
+ metadata.gz: 3b504eef2e81b90b4cabbe8a51651eb35927a861016df3b08c6f631b9619fb4905b28884bd600b52245e0a6e14020284e6b34f8bd81690602211b12717540957
7
+ data.tar.gz: 76dc0f7cc724201608a42cc831f4d2b72c91e53f37cf14f3fa0ae80e5f7124c8b607fad277bccd92b00e1dfb336d6a4f09b40399f379e79087c473954de01595
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -19,7 +19,7 @@ toc::[]
19
19
 
20
20
  == Features
21
21
 
22
- * Provides custom helpers.
22
+ * Provides custom commands and helpers.
23
23
  * Provides dynamic prompt based on environment.
24
24
 
25
25
  == Requirements
@@ -84,6 +84,7 @@ If you'd like all the bells and whistles fully enabled, add the following to you
84
84
  begin
85
85
  require "irb/kit"
86
86
 
87
+ IRB::Kit.register_commands :all
87
88
  IRB::Kit.register_helpers :all
88
89
 
89
90
  IRB.conf[:PROMPT] ||= {}
@@ -102,14 +103,44 @@ rescue LoadError => error
102
103
  end
103
104
  ----
104
105
 
105
- The above enables all helpers and configures your prompt for {ruby_link}, {hanami_link}, and {rails_link} environments.
106
+ The above enables all commands and helpers and configures your prompt for {ruby_link}, {hanami_link}, and {rails_link} environments.
106
107
 
107
108
 
108
109
  💡 Use of `:DEMO`, while functional, is meant to be replaced with the name of your organization or personal identity. So please ensure you replace both occurrences of `:DEMO` with your own unique identifier.
109
110
 
110
111
  === Commands
111
112
 
112
- At the moment, this gem does not provide any custom commands _but might in the future_. See {irb_extensions_link} documentation for further details.
113
+ Custom command are provided for you by this gem. Each is listed below as found when using `help` within an {irb_link} console:
114
+
115
+ ....
116
+ Kit
117
+ descendants Show class descendants.
118
+ ....
119
+
120
+ To enable all of these commands, use `IRB::Kit.register_commands :all`. This is the same as using:
121
+
122
+ [source,ruby]
123
+ ----
124
+ IRB::Kit.register_commands :descendants
125
+ ----
126
+
127
+ Knowing this, you can disable all commands entirely, use only the ones you care about, or enable all of them at once. The following explains each helper in greater detail.
128
+
129
+ ==== `descendants`
130
+
131
+ Use this command to show all descendants of a class. Example:
132
+
133
+ [source,ruby]
134
+ ----
135
+ descendants IO
136
+ # File
137
+
138
+ descendants Ractor::Error
139
+ # Ractor::IsolationError
140
+ # Ractor::MovedError
141
+ # Ractor::RemoteError
142
+ # Ractor::UnsafeError
143
+ ----
113
144
 
114
145
  === Helpers
115
146
 
@@ -118,8 +149,7 @@ Several custom helpers are provided for you by this gem. Each is listed below as
118
149
  ....
119
150
  Helper methods
120
151
  clip Copy input to macOS clipboard.
121
- csource Find a constant's source location.
122
- msource Find an object method's source location.
152
+ esource Edit the source code of a constant or method in your default editor.
123
153
  paste Paste last entry from macOS clipboard.
124
154
  search Search an object's methods by pattern.
125
155
  ....
@@ -128,7 +158,7 @@ To enable all of these helpers, use `IRB::Kit.register_helpers :all`. This is th
128
158
 
129
159
  [source,ruby]
130
160
  ----
131
- IRB::Kit.register_helpers(*%i[clip csource msource paste search])
161
+ IRB::Kit.register_helpers(*%i[clip esource paste search])
132
162
  ----
133
163
 
134
164
  Knowing this, you can disable all helpers entirely, use only the ones you care about, or enable all of them at once. The following explains each helper in greater detail.
@@ -155,31 +185,26 @@ clip Object.new
155
185
 
156
186
  This helper accepts any number of arguments. Each is delimited by a new line for pasting into another application.
157
187
 
158
- ==== `csource`
188
+ ==== `esource`
159
189
 
160
- Use this helper, short for _constant source_, to find the source location of a constant. Example:
190
+ Use this helper, short for _edit source_, to print and edit the source of a constant or method in your default editor. This assumes your have the `EDITOR` environment variable set and configured to use your favorite editor. If not, you'll get an error requiring your to update your environment accordingly. Here are a few usage examples:
161
191
 
162
192
  [source,ruby]
163
193
  ----
164
- csource :RUBY_DESCRIPTION # "$HOME/.cache/frum/versions/3.3.2/bin/ruby:0"
165
- csource "RUBY_DESCRIPTION" # "$HOME/.cache/frum/versions/3.3.2/bin/ruby:0"
166
- ----
167
-
168
- You can use a symbol or a string when looking up the source location of a constant. The output is formatted so you can use pass:[<kbd>CONTROL</kbd>] + `<click>` to immediately view the source at the exact line number in consoles like {iterm_link}.
194
+ esource IRB, :start
195
+ # Editing: irb-1.13.2/lib/irb.rb:893...
169
196
 
170
- ==== `msource`
197
+ esource IRB, "start"
198
+ # Editing: irb-1.13.2/lib/irb.rb:893...
171
199
 
172
- Use this helper, short for _method source_, to find the source location of a method. Example:
200
+ esource "IRB::IRBRC_EXT"
201
+ # Editing: irb-1.13.2/lib/irb/init.rb:407...
173
202
 
174
- [source,ruby]
203
+ esource :RUBY_DESCRIPTION
204
+ # ERROR (invalid path): ruby.
175
205
  ----
176
- msource IRB, :start # "$HOME/.cache/frum/versions/3.3.2/lib/ruby/3.3.0/irb.rb:893"
177
- msource IRB, "start" # "$HOME/.cache/frum/versions/3.3.2/lib/ruby/3.3.0/irb.rb:893"
178
- ----
179
-
180
- The first argument is the object you want to message while the second argument is the object's method you want to find the source code location for. You can also use a symbol or string for the method.
181
206
 
182
- The output is formatted so you can use pass:[<kbd>CONTROL</kbd>] + `<click>` to immediately view the source at the exact line number in consoles like {iterm_link}.
207
+ The first argument is the constant or object you want to search for or target. The second argument is the object's method you want to find the source code location for. You can also use a symbol or string for the method.
183
208
 
184
209
  ==== `paste`
185
210
 
@@ -200,22 +225,18 @@ Use this helper to search for methods on an object. Example:
200
225
  [source,ruby]
201
226
  ----
202
227
  search Module, "protected"
203
- # [
204
- # protected_instance_methods(*args) #<Class:Module> (Class)
205
- # protected_method_defined?(*arg1) #<Class:Module> (Module)
206
- # protected_methods(*args) #<Class:Module> (Object)
207
- # ]
228
+ # protected_instance_methods
229
+ # protected_method_defined?
230
+ # protected_methods
208
231
 
209
232
  search Module, /_defined/
210
- # [
211
- # class_variable_defined?(arg1) #<Class:Module> (Module)
212
- # const_defined?(*arg1) #<Class:Module> (Module)
213
- # instance_variable_defined?(arg1) #<Class:Module> (Kernel)
214
- # method_defined?(*arg1) #<Class:Module> (Module)
215
- # private_method_defined?(*arg1) #<Class:Module> (Module)
216
- # protected_method_defined?(*arg1) #<Class:Module> (Module)
217
- # public_method_defined?(*arg1) #<Class:Module> (Module)
218
- # ]
233
+ # const_defined?
234
+ # class_variable_defined?
235
+ # method_defined?
236
+ # public_method_defined?
237
+ # private_method_defined?
238
+ # protected_method_defined?
239
+ # instance_variable_defined?
219
240
  ----
220
241
 
221
242
  This helper takes two arguments. The first is the object you want to search on and the second argument is the string or regular expression of the methods to search for.
data/irb-kit.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "irb-kit"
5
- spec.version = "0.2.0"
5
+ spec.version = "0.3.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/irb-kit"
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Commands
6
+ # Answers descendants of a class.
7
+ class Descendants < IRB::Command::Base
8
+ MONIKER = :descendants
9
+
10
+ category "Kit"
11
+
12
+ description "Show class descendants."
13
+
14
+ help_message <<~BODY
15
+ Usage: descendants <class>
16
+
17
+ Examples:
18
+
19
+ descendants Object
20
+ descendants IO
21
+ descendants Ractor::Error
22
+ BODY
23
+
24
+ def initialize context, handler: Handlers::Descender.new
25
+ super context
26
+ @handler = handler
27
+ end
28
+
29
+ def execute(name) = handler.call(name)
30
+
31
+ private
32
+
33
+ attr_reader :handler
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Handlers
6
+ # Provides default functionality for all handlers.
7
+ class Abstract
8
+ def initialize io: STDOUT
9
+ @io = io
10
+ end
11
+
12
+ def call
13
+ fail NoMethodError,
14
+ "`#{self.class}##{__method__} #{method(__method__).parameters}` must be implemented."
15
+ end
16
+
17
+ protected
18
+
19
+ attr_reader :io
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Handlers
6
+ # Handles copying content to the macOS clipboard.
7
+ class Clipper < Abstract
8
+ def initialize(processor: IO, **)
9
+ @processor = processor
10
+ super(**)
11
+ end
12
+
13
+ def call(*lines)
14
+ processor.popen("pbcopy", "w") { |clipboard| clipboard.write lines.join("\n") }
15
+ io.puts "Copied to clipboard."
16
+ rescue Errno::ENOENT
17
+ io.puts "ERROR: Unable to copy since `pbcopy` is only supported on macOS."
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :processor
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Handlers
6
+ # Handles editing of constant source code.
7
+ class ConstantEditor < Abstract
8
+ def initialize(editor: Editor.new, **)
9
+ @editor = editor
10
+ super(**)
11
+ end
12
+
13
+ def call name
14
+ editor.call(*Object.const_source_location(name))
15
+ rescue NameError
16
+ io.puts "ERROR (invalid constant): #{name.inspect}."
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :editor
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Handlers
6
+ # Handles finding the descendants of a class.
7
+ class Descender < Abstract
8
+ def initialize(collector: ObjectSpace, **)
9
+ @collector = collector
10
+ super(**)
11
+ end
12
+
13
+ def call name
14
+ collect(name).then { |all| all.empty? ? "No descendants found." : all.join("\n") }
15
+ .then { |result| io.puts result }
16
+ rescue NameError
17
+ io.puts "ERROR: #{name.inspect} doesn't exist."
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :collector
23
+
24
+ def collect name
25
+ superclass = Object.const_get name
26
+
27
+ collector.each_object(Class)
28
+ .select { |subclass| subclass < superclass }
29
+ .tap { |descendants| descendants.delete superclass }
30
+ .map(&:to_s)
31
+ .sort
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Handlers
6
+ # Handles editing of source code.
7
+ class Editor < Abstract
8
+ def initialize(environment: ENV, kernel: Kernel, **)
9
+ @environment = environment
10
+ @kernel = kernel
11
+ super(**)
12
+ end
13
+
14
+ def call path, line = nil
15
+ path_and_line = [path, line].join ":"
16
+
17
+ if path && Pathname(path).exist?
18
+ io.puts "Editing: #{path_and_line}..."
19
+ kernel.system %(#{environment.fetch "EDITOR"} #{path_and_line})
20
+ else
21
+ io.puts "ERROR (invalid path): #{path}."
22
+ end
23
+ rescue KeyError then io.puts "ERROR: The `EDITOR` environment variable must be defined."
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :environment, :kernel
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Handlers
6
+ # Handles editing of method source code.
7
+ class MethodEditor < Abstract
8
+ def initialize(editor: Editor.new, **)
9
+ @editor = editor
10
+ super(**)
11
+ end
12
+
13
+ def call object, name
14
+ editor.call(*object.method(name).source_location)
15
+ rescue NameError
16
+ io.puts "ERROR: Undefined method `#{name.inspect}` for `#{object.inspect}`."
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :editor
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Handlers
6
+ # Handles pasting content from the macOS clipboard.
7
+ class Paster < Abstract
8
+ def initialize(processor: IO, **)
9
+ @processor = processor
10
+ super(**)
11
+ end
12
+
13
+ def call
14
+ processor.popen "pbpaste", "r", &:read
15
+ rescue Errno::ENOENT
16
+ io.puts "ERROR: Unable to paste since `pbpaste` is only supported on macOS."
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :processor
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Kit
5
+ module Handlers
6
+ # Handles searching an object's methods by pattern.
7
+ class Searcher < Abstract
8
+ def initialize(matcher: Regexp, **)
9
+ @matcher = matcher
10
+ super(**)
11
+ end
12
+
13
+ def call object, pattern
14
+ object.methods
15
+ .grep(matcher.new(pattern))
16
+ .join("\n")
17
+ .then { |result| result.empty? ? io.puts("No matches found.") : io.puts(result) }
18
+ rescue TypeError
19
+ io.puts "ERROR: Use only a string or regular expression for the pattern."
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :matcher
25
+ end
26
+ end
27
+ end
28
+ end
@@ -9,20 +9,16 @@ module IRB
9
9
 
10
10
  description "Copy input to macOS clipboard."
11
11
 
12
- def initialize io = IO
12
+ def initialize handler: Handlers::Clipper.new
13
13
  super()
14
- @io = io
14
+ @handler = handler
15
15
  end
16
16
 
17
- def execute(*lines)
18
- io.popen("pbcopy", "w") { |clipboard| clipboard.write lines.join("\n") }
19
- rescue Errno::ENOENT
20
- "ERROR: Unable to copy since `pbcopy` is only supported on macOS."
21
- end
17
+ def execute(*) = handler.call(*)
22
18
 
23
19
  private
24
20
 
25
- attr_reader :io
21
+ attr_reader :handler
26
22
  end
27
23
  end
28
24
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+
5
+ module IRB
6
+ module Kit
7
+ module Helpers
8
+ # Edits the source code of a constant or method.
9
+ class EditSource < IRB::HelperMethod::Base
10
+ MONIKER = :esource
11
+
12
+ description "Edit the source code of a constant or method in your default editor."
13
+
14
+ def initialize constant_handler: Handlers::ConstantEditor.new,
15
+ method_handler: Handlers::MethodEditor.new
16
+ super()
17
+ @constant_handler = constant_handler
18
+ @method_handler = method_handler
19
+ end
20
+
21
+ def execute(*arguments)
22
+ case arguments
23
+ in [name] then puts constant_handler.call(name)
24
+ in [object, name] then puts method_handler.call(object, name)
25
+ else puts "ERROR: Invalid constant or method for arguments: #{arguments.inspect}."
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :constant_handler, :method_handler
32
+ end
33
+ end
34
+ end
35
+ end
@@ -9,20 +9,16 @@ module IRB
9
9
 
10
10
  description "Paste last entry from macOS clipboard."
11
11
 
12
- def initialize io = IO
12
+ def initialize handler: Handlers::Paster.new
13
13
  super()
14
- @io = io
14
+ @handler = handler
15
15
  end
16
16
 
17
- def execute
18
- io.popen "pbpaste", "r", &:read
19
- rescue Errno::ENOENT
20
- "ERROR: Unable to paste since `pbpaste` is only supported on macOS."
21
- end
17
+ def execute = handler.call
22
18
 
23
19
  private
24
20
 
25
- attr_reader :io
21
+ attr_reader :handler
26
22
  end
27
23
  end
28
24
  end
@@ -9,20 +9,16 @@ module IRB
9
9
 
10
10
  description "Search an object's methods by pattern."
11
11
 
12
- def initialize regex = Regexp
12
+ def initialize handler: Handlers::Searcher.new
13
13
  super()
14
- @regex = regex
14
+ @handler = handler
15
15
  end
16
16
 
17
- def execute object, pattern
18
- object.methods.grep regex.new(pattern)
19
- rescue TypeError
20
- "ERROR: Use only a string or regular expression for the pattern."
21
- end
17
+ def execute(*) = handler.call(*)
22
18
 
23
19
  private
24
20
 
25
- attr_reader :regex
21
+ attr_reader :handler
26
22
  end
27
23
  end
28
24
  end
data/lib/irb/kit.rb CHANGED
@@ -17,6 +17,8 @@ module IRB
17
17
  @loader ||= registry.loaders.find { |loader| loader.tag == "irb-kit" }
18
18
  end
19
19
 
20
+ def self.register_commands(*) = Loader.new(IRB::Command, :Commands).call(*)
21
+
20
22
  def self.register_helpers(*) = Loader.new(IRB::HelperMethod, :Helpers).call(*)
21
23
 
22
24
  def self.prompt = @prompt ||= Prompter.new.call
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: irb-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,7 +35,7 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2024-05-31 00:00:00.000000000 Z
38
+ date: 2024-06-23 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: irb
@@ -78,9 +78,17 @@ files:
78
78
  - README.adoc
79
79
  - irb-kit.gemspec
80
80
  - lib/irb/kit.rb
81
+ - lib/irb/kit/commands/descendants.rb
82
+ - lib/irb/kit/handlers/abstract.rb
83
+ - lib/irb/kit/handlers/clipper.rb
84
+ - lib/irb/kit/handlers/constant_editor.rb
85
+ - lib/irb/kit/handlers/descender.rb
86
+ - lib/irb/kit/handlers/editor.rb
87
+ - lib/irb/kit/handlers/method_editor.rb
88
+ - lib/irb/kit/handlers/paster.rb
89
+ - lib/irb/kit/handlers/searcher.rb
81
90
  - lib/irb/kit/helpers/clip.rb
82
- - lib/irb/kit/helpers/constant_source.rb
83
- - lib/irb/kit/helpers/method_source.rb
91
+ - lib/irb/kit/helpers/edit_source.rb
84
92
  - lib/irb/kit/helpers/paste.rb
85
93
  - lib/irb/kit/helpers/search.rb
86
94
  - lib/irb/kit/loader.rb
@@ -111,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
119
  - !ruby/object:Gem::Version
112
120
  version: '0'
113
121
  requirements: []
114
- rubygems_version: 3.5.11
122
+ rubygems_version: 3.5.14
115
123
  signing_key:
116
124
  specification_version: 4
117
125
  summary: Extends IRB by providing additional productivity enhancements.
metadata.gz.sig CHANGED
Binary file
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module IRB
4
- module Kit
5
- module Helpers
6
- # Finds constant's source location.
7
- class ConstantSource < IRB::HelperMethod::Base
8
- MONIKER = :csource
9
-
10
- description "Find a constant's source location."
11
-
12
- def initialize object = Object, delimiter: ":"
13
- super()
14
- @object = object
15
- @delimiter = delimiter
16
- end
17
-
18
- def execute name
19
- object.const_source_location(name).then { |details| details.join delimiter if details }
20
- rescue NameError
21
- "ERROR: Invalid constant (#{name.inspect})."
22
- end
23
-
24
- private
25
-
26
- attr_reader :object, :delimiter
27
- end
28
- end
29
- end
30
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module IRB
4
- module Kit
5
- module Helpers
6
- # Find an object method's source location.
7
- class MethodSource < IRB::HelperMethod::Base
8
- MONIKER = :msource
9
-
10
- description "Find an object method's source location."
11
-
12
- def initialize delimiter: ":"
13
- super()
14
- @delimiter = delimiter
15
- end
16
-
17
- def execute object, name
18
- object.method(name).source_location.then { |details| details.join delimiter if details }
19
- rescue NameError => error
20
- "ERROR: #{error.message}"
21
- end
22
-
23
- private
24
-
25
- attr_reader :delimiter
26
- end
27
- end
28
- end
29
- end