Skip to content

Commit

Permalink
Add EXTEND_IRB.md to introduce IRB's command and helper registration …
Browse files Browse the repository at this point in the history
…mechanism (#933)
  • Loading branch information
st0012 authored Apr 26, 2024
1 parent fa96bea commit d167ea0
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 10 deletions.
111 changes: 111 additions & 0 deletions EXTEND_IRB.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Extend IRB

From v1.13.0, IRB provides official APIs to extend its functionality. This feature allows libraries to
customize and enhance their users' IRB sessions by adding new commands and helper methods tailored for
the libraries.

## Commands

Commands are designed to complete certain tasks or display information for the user, similar to shell commands.
Therefore, they are designed to accept a variety of inputs, including those that are not valid Ruby code, such
as `my_cmd Foo#bar` or `my_cmd --flag foo`.

### Example

```rb
require "irb/command"

class Greet < IRB::Command::Base
category "Greeting"
description "Greets the user"
help_message <<~HELP
Greets the user with the given name.
Usage: greet <name>
HELP

# Any input after the command name will be passed as a single string.
# If nothing is added after the command, an empty string will be passed.
def execute(arg)
puts "Hello! #{arg}"
end
end

IRB::Command.register("greet", Greet)
```

As long as the above code is loaded before the IRB session is started, such as in a loaded library or a user's `.irbrc` file, `greet` will be accessible to the user.

```txt
irb(main):001> greet
Hello!
=> nil
irb(main):002> greet Stan
Hello! Stan
=> nil
```

And because the `Greet` command introduces a new category, `Greeting`, a new help message category will be created:

```txt
Help
help List all available commands. Use `help <command>` to get information about a specific command.
Greeting
greet Greets the user
IRB
context Displays current configuration.
...
```

If the optional `help_message` attribute is specified, `help greet` will also display it:

```txt
irb(main):001> help greet
Greets the user with the given name.
Usage: greet <name>
```

## Helper methods

Helper methods are designed to be used as Ruby methods, such as `my_helper(arg, kwarg: val).foo`.

The main use case of helper methods is to provide shortcuts for users, providing quick and easy access to
frequently used operations or components within the IRB session. For example, a helper method might simplify
the process of fetching and displaying specific configuration settings or data structures that would otherwise
require multiple steps to access.

### Example

```rb
# This only loads the minimum components required to define and register a helper method.
# It does not load the entire IRB, nor does it initialize it.
require "irb/helper_method"

class MyHelper < IRB::HelperMethod::Base
description "This is a test helper"

def execute(arg, kwarg:)
"arg: #{arg}, kwarg: #{kwarg}"
end
end

IRB::HelperMethod.register(:my_helper, MyHelper)
```

As long as the above code is loaded before the IRB session is started, such as in a loaded library or a user's `.irbrc` file, `my_helper` will be accessible to the user.

```txt
irb(main):001> my_helper("foo", kwarg: "bar").upcase
=> "ARG: FOO, KWARG: BAR"
```

The registered helper methods will also be listed in the help message's `Helper methods` section:

```txt
Helper methods
conf Returns the current context.
my_helper This is a test helper
```
12 changes: 2 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,17 +355,9 @@ https://docs.ruby-lang.org/en/master/IRB.html

## Extending IRB

IRB is currently going through some refactoring to bring in some cool improvements and make things more flexible for developers.
We know that in the past, due to a lack of public APIs and documentation, many of you have had to use IRB's private APIs
and components to extend it. We also know that changes can be a bit annoying and might mess with your current setup.
IRB `v1.13.0` and later versions allows users/libraries to extend its functionality through official APIs.

We're sorry if this causes a bit of a scramble. We're working hard to make IRB better and your input is super important to us.
If you've been using private APIs or components in your projects, we'd love to hear about your use cases. Please feel free to file a new issue. Your feedback will be a massive help in guiding us on how to design and prioritize the development of official APIs in the future.

Right now, we've got command extension APIs on the drawing board, as you can see in [#513](https://github.com/ruby/irb/issues/513).
We've also got a prototype for helper method extension APIs in the works, as shown in [#588](https://github.com/ruby/irb/issues/588).

We really appreciate your understanding and patience during this transition. We're pretty excited about the improvements these changes will bring to the IRB ecosystem and we hope you are too!
For more information, please visit [EXTEND_IRB.md](./EXTEND_IRB.md).

## Development

Expand Down

0 comments on commit d167ea0

Please sign in to comment.