Full Code of godfat/rib for AI

master 54d1f88d9c85 cached
71 files
132.8 KB
40.1k tokens
291 symbols
1 requests
Download .txt
Repository: godfat/rib
Branch: master
Commit: 54d1f88d9c85
Files: 71
Total size: 132.8 KB

Directory structure:
gitextract_3eo0hgho/

├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── CHANGES.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── TODO.md
├── asciicast.json
├── bin/
│   ├── rib
│   ├── rib-all
│   ├── rib-auto
│   ├── rib-min
│   ├── rib-rack
│   └── rib-rails
├── lib/
│   ├── rib/
│   │   ├── all.rb
│   │   ├── api.rb
│   │   ├── app/
│   │   │   ├── auto.rb
│   │   │   ├── rack.rb
│   │   │   └── rails.rb
│   │   ├── config.rb
│   │   ├── core/
│   │   │   ├── completion.rb
│   │   │   ├── history.rb
│   │   │   ├── last_value.rb
│   │   │   ├── multiline.rb
│   │   │   ├── readline.rb
│   │   │   ├── squeeze_history.rb
│   │   │   └── strip_backtrace.rb
│   │   ├── core.rb
│   │   ├── debug.rb
│   │   ├── extra/
│   │   │   ├── autoindent.rb
│   │   │   ├── byebug.rb
│   │   │   ├── hirb.rb
│   │   │   ├── paging.rb
│   │   │   └── spring.rb
│   │   ├── more/
│   │   │   ├── anchor.rb
│   │   │   ├── beep.rb
│   │   │   ├── bottomup_backtrace.rb
│   │   │   ├── caller.rb
│   │   │   ├── color.rb
│   │   │   ├── edit.rb
│   │   │   ├── multiline_history.rb
│   │   │   └── multiline_history_file.rb
│   │   ├── more.rb
│   │   ├── plugin.rb
│   │   ├── runner.rb
│   │   ├── shell.rb
│   │   ├── test/
│   │   │   ├── history.rb
│   │   │   └── multiline.rb
│   │   ├── test.rb
│   │   └── version.rb
│   └── rib.rb
├── rib.gemspec
└── test/
    ├── core/
    │   ├── test_completion.rb
    │   ├── test_history.rb
    │   ├── test_last_value.rb
    │   ├── test_multiline.rb
    │   ├── test_readline.rb
    │   ├── test_squeeze_history.rb
    │   └── test_strip_backtrace.rb
    ├── extra/
    │   └── test_autoindent.rb
    ├── more/
    │   ├── test_anchor.rb
    │   ├── test_beep.rb
    │   ├── test_caller.rb
    │   ├── test_color.rb
    │   └── test_multiline_history.rb
    ├── test_api.rb
    ├── test_plugin.rb
    ├── test_runner.rb
    └── test_shell.rb

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
/pkg/
/coverage/


================================================
FILE: .gitlab-ci.yml
================================================

stages:
  - test

.test:
  stage: test
  image: ruby:${RUBY_VERSION}-bullseye
  variables:
    GIT_DEPTH: "1"
    GIT_SUBMODULE_STRATEGY: recursive
    GIT_SUBMODULE_PATHS: task
    RUBYOPT: --enable-frozen-string-literal
  before_script:
    - bundle install --retry=3
    - unset CI # Coverage doesn't work well with frozen literal
  script:
    - ruby -vr bundler/setup -S rake test

ruby:3.2:
  extends:
    - .test
  variables:
    RUBY_VERSION: '3.2'

ruby:3.3:
  extends:
    - .test
  variables:
    RUBY_VERSION: '3.3'

ruby:3.4:
  extends:
    - .test
  variables:
    RUBY_VERSION: '3.4'

jruby:latest:
  extends:
    - .test
  image: jruby:latest


================================================
FILE: .gitmodules
================================================
[submodule "task"]
	path = task
	url = https://github.com/godfat/gemgem.git


================================================
FILE: CHANGES.md
================================================
# CHANGES

## Rib 1.6.2 -- 2026-01-20

### Bugs fixed

* [core/strip_backtrace] Now it works with backtrace quotes change from
  `` ` `` to `'`

## Rib 1.6.2 -- 2026-01-19

### Bugs fixed

* [core/multiline] Now it works with prism parser
* [more/color] Now it works with backtrace quotes change from `` ` `` to `'`

## Rib 1.6.1 -- 2022-12-30

### Bugs fixed

* Fixed `rib rack` for constant resolution.

### Enhancement

* [more/color] Instead of using `$1` and `$2`, use `Regexp.last_match`.
  It should be the same for MRI, but seems to be working better for JRuby.
  Perhaps `$1` and `$2` is not thread local on JRuby?

## Rib 1.6.0 -- 2018-06-20

* [core/multiline] Support for JRuby 9.2.0.0 is fixed
* [more/beep] It would now beep every single time when any evaluation took
  longer than the threshold.
* [more/color] Fix whenever the input is just `next` or `break`
* [more/bottomup_backtrace] This would no longer format backtrace twice
* [more/caller] It would now properly use the enabled plugins
* [extra/autoindent] It would now indent with `ensure` for `begin` and `def`.
  Thanks @MITSUBOSHI https://github.com/godfat/rib/pull/21 and
  @alpaca-tc https://github.com/godfat/rib/pull/17
* [extra/autoindent] It would now indent with `for`.
  Thanks @MITSUBOSHI https://github.com/godfat/rib/pull/18
* [extra/autoindent] It would now indent with `()` and `[]`.
  Thanks @MITSUBOSHI https://github.com/godfat/rib/pull/20 and
  https://github.com/godfat/rib/pull/19
* [extra/byebug] This is now work-in-progress.

## Rib 1.5.4 -- 2017-10-23

* Removed unnecessary method definition for `puts`

## Rib 1.5.3 -- 2017-08-05

* Now we set trap only when the shell starts, and restore the old trap
  after the shell stops. This should fix some problems using anchor inside
  RSpec or Unicorn. They would no longer interfere with them.
* [core/multiline] Now we support backslash. See:
  [Using backslash line continuation character results in syntax error](https://github.com/godfat/rib/issues/15)

## Rib 1.5.2 -- 2017-05-01

* We now `require 'rib/version'` from the beginning, avoid loading error
  under bundler.
* Introduced `API#started_at` which is `config[:started_at]` for accessing
  when Rib started.
* Introduced `API#inspect_result` which would inspect the result. The default
  behaviour would just inspect the result, but if the result is not a string,
  emit a warning. https://github.com/godfat/rib/issues/14
* Now all warnings would be printed after the result was printed. This would
  make it easier to spot warnings.
* [more/color] It would now paint warnings.
* [more/anchor] Introduced `Rib.stop_anchors` to stop all nested anchors.
  https://github.com/godfat/rib/issues/13
* Fixed Rib app detection for newer RubyGems

### Breaking changes

* Extending `Rib::Plugin` would no longer automatically also include `Rib`.
  For compatibility concern, a `const_missing` is now defined in `Rib::Plugin`
  so that using `Shell` would still refer to `Rib::Shell` for you, considering
  that this might be a common pattern:

      extend Rib::Plugin
      Shell.use(self)

  Note that this would be removed in the future, so please take this chance to
  change it to:

      extend Rib::Plugin
      Rib::Shell.use(self)

## Rib 1.5.1 -- 2017-03-09

* [more/beep] This plugin would beep via `print "\a"` when the application
  was loaded and it's been too long. Configure the time via
  `Rib.config[:beep_threshold]`, default is 5 seconds.

## Rib 1.5.0 -- 2017-02-27

* Removed Ramaze direct support. Use Rack instead.
* Introduced API#format_backtrace
* Introduced API#puts
* [more/anchor] Fixed multiline support when anchoring on an object
* [more/caller] Added for showing formatted call stack
* [core/underscore] This is changed to `core/last_value`, and the API is
  changed to `Rib.last_value` and `Rib.last_exception`. Surely this is less
  intrusive and more compatible for things like `Rib.anchor 42` because
  now literal integers are frozen and we cannot define methods on them.
  Also, using `Rib.last_value` is surely more descriptive. Of course,
  being able to type `_` is so much easier, but you could just add a plugin
  which defines `def _; Rib.last_value; end` and keep using `_` for your
  own taste!

## Rib 1.4.0 -- 2016-11-11

* Search Rib home by directories rather than config/history file.
* Respect prefix option for detecting Rib home.
* Update help message for `-n`, which won't load any config.
* Change `Rib.config[:config]` to `Rib.config_path`.
* [app/rails] Fix loading boot file when using prefix option.
* [app/auto] Fix two variable shadowing warnings.

## Rib 1.3.1 -- 2016-11-03

* [core/strip_backtrace], [more/color] No longer show `./` for current path.
  This would be more friendly to some editors like Sublime.

## Rib 1.3.0 -- 2016-06-28

* Now `rib` would accept `-p` or `--prefix` to allow setting where we want to
  load the application. This is useful when we don't want to `cd` into a
  directory and `rib auto` or `rib rails` from there.

## Rib 1.2.91 -- 2016-01-06

* [core/multiline] Fixed a case for JRuby 9.0.4.0.
* [extra/paging] Disable paging if `tput` is not found.
* [extra/spring] Require `rib/extra/spring` in your `~/.spring` to enable
  Rails Spring support. #11 (thanks @swrobel)

## Rib 1.2.9 -- 2015-09-23

* [extra/paging] Disable paging if your terminal is nil. (e.g. on Heroku)

## Rib 1.2.8 -- 2015-09-23

* [extra/paging] Disable paging if your terminal is dumb. (e.g. on Heroku)

## Rib 1.2.7 -- 2015-01-28

* [more/bottomup_backtrace] A new plugin which prints the backtrace bottom-up.
  Ref: <http://yellerapp.com/posts/2015-01-22-upside-down-stacktraces.html>

## Rib 1.2.6 -- 2014-11-07

* [extra/autoindent] Now `module_function` would indent correctly.
* [extra/autoindent] Now `else` in `case` would indent correctly.
* [extra/autoindent] Fixed printing end clause twice. (performance fix)
* [extra/multiline] Fixed in some cases it's not recognized as multiline
  in Rubinius (rbx).

## Rib 1.2.5 -- 2014-03-13

* Fixed binding. Sorry my bad.

## Rib 1.2.4 -- 2014-03-13

* Fixed a regression introduced in 1.2.0. Now `rib all -e 'p 123'` should
  work properly. Previously -e is ignored after rib apps.
* Fixed a long standing Windows issue, where `rib all` did not work because
  there's no `which` on Windows. Now we fall back to `where`.
* Warn on removing main method on `TOPLEVEL_BINDING`. Not sure if this
  would happen, but at least we could have a warning.

## Rib 1.2.3 -- 2014-02-08

* [extra/paging] Properly disable paging if less or ENV['PAGER'] is not
  available.

## Rib 1.2.2 -- 2014-01-23

* From now on, we support project specific config file located on
  "./.rib/config.rb". Note that if there's a project specific config file,
  your home config would not be loaded at all. The history file would also
  be put into "./.rib/history.rb". You might want to ignore it from your
  repository to avoid leaking confidential information.

* [extra/paging] Now we strip ANSI sequences before calculating if we need
  a pager. This should make it much more accurate.

## Rib 1.2.1 -- 2014-01-18

* Fixed a bug where it cannot properly elegantly handle errors when loading
  the config file.

* [extra/paging] This plugin would try to use $PAGER and by default less to
  paginate for output which cannot fit in a screen.

* [more/edit] Now by default it would pick vim if $EDITOR is not set.

## Rib 1.2.0 -- 2014-01-17

* We no longer really eval on TOPLEVEL_BINDING, but a private binding
  derived from TOPLEVEL_BINDING. This is due to RubyGems bin stub would
  actually pollute TOPLEVEL_BINDING, leaving `str` and `version` as
  local variables. I would like to avoid them, thus introducing this change.
  Please let me know if this breaks anything, thanks!

* [core/multiline] Fixed a multiline detection for Rubinius.

## Rib 1.1.6 -- 2013-08-14

* [more/color] Fixed inspecting recursive array and hash.

## Rib 1.1.5 -- 2013-07-11

* Fixed `rib -h` with commands don't have a description.
* Added a description for `rib rack`

## Rib 1.1.4 -- 2013-07-11

* Further fixed a bug for displaying a BasicObject. Rib should never crash.
* Added `rib-rack` executable which could load the app in config.ru,
  accessible from calling `app` in the console. Also works for `rib-auto`

## Rib 1.1.3 -- 2013-05-08

* Fixed a bug where if user input doesn't respond to `==` would crash rib.

## Rib 1.1.2 -- 2013-04-02

* [core/multiline] Ruby 2.0 compatibility.

## Rib 1.1.1 -- 2013-01-25

* Fixed some multiline issue with Rubinius and JRuby.
* Properly indent for multiline prompt.
* Removed ripl compatibility layer.
* Only retry 5 times upon failures. This prevents from infinite retries.
* Don't retry on quiting.
* Added a half-baked debugger support. Try it with:
  `require 'rib/extra/debugger'; Rib.debug`

## Rib 1.1.0 -- 2012-07-18

* Support for Ruby 1.8 is dropped.
* Now `Rib::Plugin` should be extended to the module, instead of included.
  This fits more naturally with Ruby, but not really compatible with Ruby 1.8?
* [more/anchor] Fixed a bug where you run rib in top level while anchor in
  the other source, exit from the inner shell would break from the original
  call. Now you can safely exit from the inner shell and keep doing the
  original work.

## Rib 1.0.5 -- 2012-05-15

* [app/rails] Fixed SystemStackError issue. It's because ConsoleMethods
  should not pollute the Object, redefining `app` method.

## Rib 1.0.4 -- 2012-03-20

* [core/multiline] Fixed a corner case:

  ``` ruby
      1/1.to_i +
      1
  ```

* [rib] Do not crash because of a loop error. Try to relaunch the shell.

## Rib 1.0.3 -- 2012-01-21

### Bugs fixes

* [rib-rails] Fixed sandbox mode.
* [rib-rails] Bring back `reload!`, `new_session`, and `app` for Rails 3.2.0

## Rib 1.0.2 -- 2011-12-24

### Bugs fixes

* [more/multiline_history] Make sure values are initialized even if
  before_loop is called later. This helps us enable plugins on the fly.

## Rib 1.0.1 -- 2011-12-15

### Incompatible changes

* [rib] Keyword `quit` to exit rib is removed, preferring `exit`.

### Bugs fixes

* [rib] Now you exit rib with ` exit`. Thanks @ayamomiji
* [rib] Fixed -e, --eval binding. It should be TOPLEVEL_BINDING

### Enhancement

* [core/history, more/color, more/multiline_history_file, extra/autoindent]
  Make sure values are initialized even if before_loop is called later.
  This helps us enable plugins on the fly.

* [extra/autoindent] Now it depends on history plugin as well. This is not
  really needed, but would help to reduce plugins ordering issue.

## Rib 1.0.0 -- 2011-11-05

### Bugs fixes

* [more/color] Fixed a bug for displaying `1/0`. Fixed #4, thanks @bootleq

## Rib 0.9.9 -- 2011-10-26

### Bugs fixes

* [more/color] Fixed Windows coloring support.
* [more/color] Properly reset ANSI sequence.

### Enhancement

* [commands] Extract commands description under `__END__` in the commands.
  Please read [rib-rest-core][] as an example.
* [rib] Always show original errors if anything is wrong.

[rib-rest-core]: https://github.com/cardinalblue/rest-core/blob/rest-core-0.7.0/bin/rib-rest-core#L21-22

## Rib 0.9.5 -- 2011-09-03

* [rib-rails] Fixed Rails3 (sandbox) and Rails2 (env) console. Thanks bootleq
* [rib-min] Fixed not being really minimum
* [rib] Now you can run it with `rib -wdIlib`, isn't it convenient?
  It's equivalent to `rib -w -d -I lib` or `rib -w -d -I=lib`

## Rib 0.9.4 -- 2011-09-01

* [rib-rails] So now we replicated what Rails did for its console, both for
  Rails 2 and Rails 3. You can now fully use `rib rails` or `rib auto` as
  `rails console` or `./script/console` in respect to Rails 2 or 3. For
  example, it works for:

      rib auto production
      rib rails production
      rib auto test --debugger # remember to add ruby-debug(19)? to Gemfile
      rib auto test --sandbox
      rib rails test --debugger --sandbox

  It should also make Rails 3 print SQL log to stdout. Thanks tka.

## Rib 0.9.3 -- 2011-08-28

* [rib] Calling `Rib.shell` would no longer automatically `require 'rib/core'`
  anymore. This is too messy. We should only do this in `bin/rib`. See:
  commit #7a97441afeecae80f5493f4e8a4a6ba3044e2c33

      require 'rib/more/anchor'
      Rib.anchor 123

  Should no longer crashed... Thanks Andrew.

## Rib 0.9.2 -- 2011-08-25

* [extra/autoindent] It has been greatly improved. A lot more accurate.
* [extra/autoindent] Fixed a bug when you're typing too fast upon rib
                     launching, it might eat your input. Thanks bootleq.

## Rib 0.9.1 -- 2011-08-19

* [extra/autoindent] Autoindent plugin help you indent multiline editing.
  Note: This plugin is depending on [readline_buffer][], thus GNU Readline.

* [ripl] After `require 'rib/ripl'`, ripl plugins should be usable for rib.

* [rib] Introduce `ENV['RIB_HOME']` to set where to store config and history.
  By default, it's `~/.rib` now, but it would first search for existing
  config or history, which would first try to see `~/.rib/config.rb`, and
  then `~/.rib/history.rb`. If Rib can find anything there, then `RIB_HOME`
  would be set to `~/.rib`, the same goes to `~/.config/rib`.
  In short, by default `RIB_HOME` is `~/.rib`, but the old `~/.config/rib`
  still works.

[readline_buffer]: https://github.com/godfat/readline_buffer

## Rib 0.9.0 -- 2011-08-14

* First serious release!
* So much enhancement over ripl-rc!


================================================
FILE: Gemfile
================================================

source 'https://rubygems.org'

gemspec

gem 'rake'
gem 'pork'
gem 'muack'

gem 'bond'
gem 'hirb'

gem 'simplecov', :require => false if ENV['COV']
gem 'coveralls', :require => false if ENV['CI']

platforms :ruby do
  gem 'readline_buffer'
end


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# Rib [![Pipeline status](https://gitlab.com/godfat/rib/badges/master/pipeline.svg)](https://gitlab.com/godfat/rib/-/pipelines)

by Lin Jen-Shin ([godfat](https://godfat.org))

## LINKS:

* [github](https://github.com/godfat/rib)
* [rubygems](https://rubygems.org/gems/rib)
* [rdoc](https://rubydoc.info/github/godfat/rib)
* [issues](https://github.com/godfat/rib/issues) (feel free to ask for support)

## DESCRIPTION:

Ruby-Interactive-ruBy -- Yet another interactive Ruby shell

Rib is based on the design of [ripl][] and the work of [ripl-rc][], some of
the features are also inspired by [pry][]. The aim of Rib is to be fully
featured and yet very easy to opt-out or opt-in other features. It shall
be simple, lightweight and modular so that everyone could customize Rib.

[ripl]: https://github.com/cldwalker/ripl
[ripl-rc]: https://github.com/godfat/ripl-rc
[pry]: https://github.com/pry/pry

## REQUIREMENTS:

* Tested with MRI (official CRuby) and JRuby.
* All gem dependencies are optional, but it's highly recommended to use
  Rib with [bond][] for tab completion.

[bond]: https://github.com/cldwalker/bond

## INSTALLATION:

    gem install rib

## SYNOPSIS:

![Screenshot](https://github.com/godfat/rib/raw/master/screenshot.png)

### As an interactive shell

As IRB (reads `~/.rib/config.rb` writes `~/.rib/history.rb`)

    rib

As Rails console

    rib rails

You could also run in production and pass arguments normally as you'd do in
`rails console` or `./script/console`

    rib rails production --sandbox --debugger

Note: You might need to add ruby-debug or ruby-debug19 to your Gemfile if
you're passing --debugger and using bundler together.

For [Rails Spring](https://github.com/rails/spring) support, put this line
in your `~/.spring.rb`:

    require 'rib/extra/spring'

As Rack console

    rib rack

As a console for whichever the app in the current path
it should be (for now, it's either Rails or Rack)

    rib auto

If you're trying to use `rib auto` for a Rails app, you could also pass
arguments as if you were using `rib rails`. `rib auto` is merely passing
arguments.

    rib auto production --sandbox --debugger

As a fully featured interactive Ruby shell (as ripl-rc)

    rib all

As a fully featured app console (yes, some commands could be used together)

    rib all auto # or `rib auto all`, the order doesn't really matter

#### Customization

You can customize Rib's behaviour by setting a config file located at
`$RIB_HOME/config.rb`, or `./.rib/config.rb`, or `~/.rib/config.rb`, or
`~/.config/rib/config.rb`, searched by respected order. The default
would be `~/.rib/config.rb`. Since it's merely a Ruby script which would
be loaded into memory before launching Rib shell session, You can put any
customization or monkey patch there. Personally, I use all plugins provided
by Rib.

My Personal [~/.config/rib/config](https://github.com/godfat/dev-tool/blob/master/.config/rib/config.rb)

As you can see, putting `require 'rib/all'` into config file is exactly the
same as running `rib all` without a config file. What `rib all` would do is
merely require the file, and that file is also merely requiring all plugins,
but without **extra plugins**, which you should enable them one by one. This
is because most extra plugins are depending on other gems, or hard to work
with other plugins, or having strong personal tastes, so you won't want to
enable them all. Suppose you only want to use the core plugins and color
plugin, you'll put this into your config file:

``` ruby
require 'rib/core'
require 'rib/more/color'
```

You can also write your plugins there. Here's another example:

``` ruby
require 'rib/core'
require 'pp'
Rib.config[:prompt] = '$ '

module RibPP
  Rib::Shell.send(:include, self)

  def format_result result
    result_prompt + result.pretty_inspect
  end
end
```

So that we override the original format_result to pretty_inspect the result.
You can also build your own gem and then simply require it in your config
file. To see a list of overridable API, please read [api.rb][]

[api.rb]: https://github.com/godfat/rib/blob/master/lib/rib/api.rb

#### Disable enabled plugins

While it's convenient to just `require 'rib/all'`, you might not want to use
all the plugins. No worries, you don't have to list everything in order to
not use something. For example, you might not get used to `bottomup_backtrace`
and don't want to use it. You could put this in your config:

``` ruby
require 'rib/all'

Rib::BottomupBacktrace.disable
```

This could disable `bottomup_backtrace` so you get regular top-down backtrace
with all other plugins. This is particularly useful whenever there's a bug
in one of the plugins, and you might need to disable some plugins in order to
debug. You could always enable it again with:

``` ruby
Rib::BottomupBacktrace.enable
```

You could do this any time, in the config, or in the shell session. No need to
restart anything, because it takes effect immediately.

#### Rib home and history file

Rib home is used to store a config file and a history file, which is
searched in this order:

* $RIB_HOME
* ./.rib
* ~/.rib
* ~/.config/rib

Rib would stop searching whenever the directory is found. If none could be
found, the default would be:

* ~/.rib

So the default history file would be located at `~/.rib/history.rb`.

#### Project config and history

Since `./.rib` would be searched before `~/.rib`, you could create project
level config at the project directory, and the history would also be
separated from each other, located at the respected `./.rib/history.rb`.

To do this, you don't really have to create a project config. Creating an
empty directory for Rib home at the project directory would also work.

#### Project directory and command line options

You could set the project directory by using `-p, --prefix` command line
option. So consider this:

    cd ~/project
    rib auto

Would work the same as:

    cd /tmp
    rib -p ~/project auto

And the project config and history would be located at `~/project/.rib`.

To check for more command line options, run `rib -h`:

```
Usage: rib [ruby OPTIONS] [rib OPTIONS] [rib COMMANDS]
ruby options:
  -e, --eval LINE        Evaluate a LINE of code
  -d, --debug            Set debugging flags (set $DEBUG to true)
  -w, --warn             Turn warnings on (set $-w and $VERBOSE to true)
  -I, --include PATH     Specify $LOAD_PATH (may be used more than once)
  -r, --require LIBRARY  Require the library, before executing your script
rib options:
  -c, --config FILE      Load config from FILE
  -p, --prefix PATH      Prefix to locate the app. Default to .
  -n, --no-config        Suppress loading ~/.config/rib/config.rb
  -h, --help             Print this message
  -v, --version          Print the version
rib commands:
  all                    Load all recommended plugins
  auto                   Run as Rails or Rack console (auto-detect)
  min                    Run the minimum essence
  rack                   Run as Rack console
  rails                  Run as Rails console
```

#### Basic configuration

Rib.config                 | Functionality
-------------------------- | -------------------------------------------------
ENV['RIB_HOME']            | Specify where Rib should store config and history
Rib.config[:name]          | The name of this shell
Rib.config[:result_prompt] | Default is "=>"
Rib.config[:prompt]        | Default is ">>"
Rib.config[:binding]       | Context, default: TOPLEVEL_BINDING
Rib.config[:exit]          | Commands to exit, default [nil] # control+d

#### Plugin specific configuration

Rib.config                     | Functionality
------------------------------ | ---------------------------------------------
Rib.config[:completion]        | Completion: Bond config
Rib.config[:history_file]      | Default is "~/.rib/history.rb"
Rib.config[:history_size]      | Default is 500
Rib.config[:color]             | A hash of Class => :color mapping
Rib.config[:autoindent_spaces] | How to indent? Default is two spaces: '  '
Rib.config[:beep_threshold]    | When it should beep? Default is 5 seconds

#### List of core plugins

``` ruby
require 'rib/core' # You get all of the followings:
```

* `require 'rib/core/completion'`

  Completion from [bond][].

* `require 'rib/core/history'`

  Remember history in a history file.

* `require 'rib/core/strip_backtrace'`

  Strip backtrace before Rib.

* `require 'rib/core/readline'`

  Readline support.

* `require 'rib/core/multiline'`

  You can interpret multiple lines.

* `require 'rib/core/squeeze_history'`

  Remove duplicated input from history.

* `require 'rib/core/last_value'`

  Save the last result in `Rib.last_value` and the last exception in
  `Rib.last_exception`.

#### List of more plugins

``` ruby
require 'rib/more' # You get all of the followings:
```

* `require 'rib/more/multiline_history_file'`

  Not only readline could have multiline history, but also the history file.

* `require 'rib/more/bottomup_backtrace'`

  Show backtrace bottom-up instead of the regular top-down.

* `require 'rib/more/color'`

  Class based colorizing.

* `require 'rib/more/multiline_history'`

  Make readline aware of multiline history.

* `require 'rib/more/beep'`

  Print "\a" when the application was loaded and it's been too long.
  Configure the threshold via `Rib.config[:beep_threshold]`.

* `require 'rib/more/anchor'`

  See _As a debugging/interacting tool_.

* `require 'rib/more/caller'`

  See _Current call stack (backtrace, caller)_.

* `require 'rib/more/edit'`

  See _In place editing_.

### List of extra plugins

There's no `require 'rib/extra'` for extra plugins because they might not
be doing what you would expect or want, or having an external dependency,
or having conflicted semantics.

* `require 'rib/extra/autoindent'` This plugin is depending on:

  1. [readline_buffer][]
  2. readline plugin
  3. multiline plugin

  Which would autoindent your input.

* `require 'rib/extra/hirb'` This plugin is depending on:

  1. [hirb][]

  Which would print the result with hirb.

* `require 'rib/extra/paging'` This plugin is depending on `less` and `tput`.

  Which would pass the result to `less` (or `$PAGER` if set) if
  the result string is longer than the screen.

* `require 'rib/extra/spring'` in your `~/.spring.rb`
  for [Rails Spring](https://github.com/rails/spring) support.

[readline_buffer]: https://github.com/godfat/readline_buffer
[hirb]: https://github.com/cldwalker/hirb

### As a debugging/interacting tool

Rib could be used as a kind of debugging tool which you can set break point
in the source program.

``` ruby
require 'rib/config' # This would load your Rib config
require 'rib/more/anchor'
                     # If you enabled anchor in config, then needed not
Rib.anchor binding   # This would give you an interactive shell
                     # when your program has been executed here.
Rib.anchor 123       # You can also anchor on an object.
```

But this might be called in a loop, you might only want to
enter the shell under certain circumstance, then you'll do:

``` ruby
require 'rib/debug'

Rib.enable_anchor do
  # Only `Rib.anchor` called in the block would launch a shell
end

Rib.anchor binding # No effect (no-op) outside the block
```

Anchor could also be nested. The level would be shown on the prompt,
starting from 1.

### Current call stack (backtrace, caller)

Often time we would want to see current call stack whenever we're using
`Rib.anchor`. We could do that by simply using `caller` but it's barely
readable because it's just returning an array without any format and
it also contains backtrace from Rib itself. You could use pretty
formatting with Rib:

``` ruby
require 'rib/more/caller'

Rib.caller
```

It would use the same format for exception backtrace to show current
call stack for you. Colors, bottom up order, etc, if you're also using
the corresponding plugins.

Sometimes there are also too many stack frames which we don't care about.
In this case, we could pass arguments to `Rib.caller` in order to filter
against them. You could either pass:

* A `String` represents the name of the gem you don't care
* A `Regexp` which would be used to match against paths/methods you don't care

Examples:

``` ruby
require 'rib/more/caller'

Rib.caller 'activesupport', /rspec/
```

To remove backtrace from gem _activesupport_ and paths or methods containing
rspec as part of the name, like things for _rspec_ or _rspec-core_ and so on.
Note that if a method name also contains rspec then it would also be filtered.
Just keep that in mind when using regular expression.

Or if you don't care about any gems, only want to see application related
calls, then try to match against `%r{/gems/}` because gems are often stored
in a path containing `/gems/`:

```
Rib.caller %r{/gem/}
```

Happy debugging.

### In place editing

Whenever you called:

``` ruby
require 'rib/more/edit'

Rib.edit
```

Rib would open an editor according to `$EDITOR` (`ENV['EDITOR']`) for you.
By default it would pick vim if no `$EDITOR` was set. After save and leave
the editor, Rib would evaluate what you had input. This also works inside
an anchor. To use it, require either rib/more/edit or rib/more or rib/all.

### As a shell framework

The essence is:

``` ruby
require 'rib'
```

All others are optional. The core plugins are lying in `rib/core/*.rb`, and
more plugins are lying in `rib/more/*.rb`. You can read `rib/app/rack.rb`
and `bin/rib-rack` as a Rib App reference implementation, because it's very
simple, simpler than rib-rails.

## Other plugins and apps

* [rest-more][] `rib rest-core` Run as interactive rest-core client
* [rib-heroku][] `rib heroku` Run console on Heroku Cedar with your config

[rest-more]: https://github.com/cardinalblue/rest-more
[rib-heroku]: https://github.com/godfat/rib-heroku

## CONTRIBUTORS:

* Andrew Liu (@eggegg)
* ayaya (@ayamomiji)
* Lin Jen-Shin (@godfat)
* Mr. Big Cat (@miaout17)
* @alpaca-tc
* @bootleq
* @lulalala
* @MITSUBOSH
* @tka

## LICENSE:

Apache License 2.0 (Apache-2.0)

Copyright (c) 2011-2026, Lin Jen-Shin (godfat)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

<https://www.apache.org/licenses/LICENSE-2.0>

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


================================================
FILE: Rakefile
================================================

begin
  require "#{__dir__}/task/gemgem"
rescue LoadError
  sh 'git submodule update --init --recursive'
  exec Gem.ruby, '-S', $PROGRAM_NAME, *ARGV
end

Gemgem.init(__dir__) do |s|
  require 'rib/version'
  s.name    = 'rib'
  s.version = Rib::VERSION
  %w[screenshot.png asciicast.json].each do |file|
    s.files.delete(file)
  end
end


================================================
FILE: TODO.md
================================================
# TODO

* cleanup the tests. it's so messy right now

* Runner tests
* Documentation
* Implement exception_spy

<https://github.com/godfat/rib/commit/7a97441afeecae80f5493f4e8a4a6ba3044e2c33>

So here we have a problem. Some plugins are expecting to override
some other plugins. The order can't really be arbitrary.....
Actually, users won't care about order either. We just want to
enable/disable plugins, not really composability.

So it really should be a bucket of plugins. At least for built-in plugins,
so that we would be aware of the order. Users shouldn't pay attention
on the order of built-in plugins.


================================================
FILE: asciicast.json
================================================
{
  "version": 1,
  "width": 80,
  "height": 24,
  "duration": 31.5,
  "command": null,
  "title": "rib",
  "env": {
    "TERM": "xterm-256color",
    "SHELL": "/usr/local/bin/fish"
  },
  "stdout": [
    [
      0.05,
      ">> "
    ],
    [
      0.05,
      "{"
    ],
    [
      0.05,
      "a"
    ],
    [
      0.05,
      ":"
    ],
    [
      0.05,
      "0"
    ],
    [
      0.05,
      ","
    ],
    [
      0.05,
      "'"
    ],
    [
      0.05,
      "b"
    ],
    [
      0.05,
      "'"
    ],
    [
      0.05,
      "="
    ],
    [
      0.05,
      ">"
    ],
    [
      0.05,
      "["
    ],
    [
      0.05,
      "O"
    ],
    [
      0.05,
      "b"
    ],
    [
      0.05,
      "j"
    ],
    [
      0.05,
      "e"
    ],
    [
      0.05,
      "c"
    ],
    [
      0.05,
      "t"
    ],
    [
      0.05,
      "]"
    ],
    [
      0.05,
      ","
    ],
    [
      0.05,
      "n"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "l"
    ],
    [
      0.05,
      "="
    ],
    [
      0.05,
      ">"
    ],
    [
      0.05,
      "t"
    ],
    [
      0.05,
      "r"
    ],
    [
      0.05,
      "u"
    ],
    [
      0.05,
      "e"
    ],
    [
      0.05,
      "}"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "=> \u001b[34m{\u001b[0m\u001b[36m:a\u001b[0m\u001b[34m=>\u001b[0m\u001b[31m0\u001b[0m\u001b[34m, \u001b[0m\u001b[32m\"b\"\u001b[0m\u001b[34m=>\u001b[0m\u001b[34m[\u001b[0m\u001b[33mObject\u001b[0m\u001b[34m]\u001b[0m\u001b[34m, \u001b[0m\u001b[35mnil\u001b[0m\u001b[34m=>\u001b[0m\u001b[35mtrue\u001b[0m\u001b[34m}\u001b[0m\r\n"
    ],
    [
      0.05,
      ">> "
    ],
    [
      1.5,
      "R"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "b"
    ],
    [
      0.05,
      "."
    ],
    [
      0.05,
      "a"
    ],
    [
      0.05,
      "n"
    ],
    [
      0.05,
      "c"
    ],
    [
      0.05,
      "h"
    ],
    [
      0.05,
      "o"
    ],
    [
      0.05,
      "r"
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "'"
    ],
    [
      0.05,
      "r"
    ],
    [
      0.05,
      "o"
    ],
    [
      0.05,
      "c"
    ],
    [
      0.05,
      "k"
    ],
    [
      0.05,
      "'"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1)>> "
    ],
    [
      1.5,
      "u"
    ],
    [
      0.05,
      "p"
    ],
    [
      0.05,
      "c"
    ],
    [
      0.05,
      "a"
    ],
    [
      0.05,
      "s"
    ],
    [
      0.05,
      "e"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "=> \u001b[32m\"ROCK\"\u001b[0m\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1)>> "
    ],
    [
      1.5,
      "R"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "b"
    ],
    [
      0.05,
      "."
    ],
    [
      0.05,
      "a"
    ],
    [
      0.05,
      "n"
    ],
    [
      0.05,
      "c"
    ],
    [
      0.05,
      "h"
    ],
    [
      0.05,
      "o"
    ],
    [
      0.05,
      "r"
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "s"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "z"
    ],
    [
      0.05,
      "e"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[31m4\u001b[0m(2)>> "
    ],
    [
      1.5,
      "s"
    ],
    [
      0.05,
      "e"
    ],
    [
      0.05,
      "l"
    ],
    [
      0.05,
      "f"
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "+"
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "1"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "=> \u001b[31m5\u001b[0m\r\n"
    ],
    [
      0.05,
      "\u001b[31m4\u001b[0m(2)>> "
    ],
    [
      1.5,
      "R"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "b"
    ],
    [
      0.05,
      "."
    ],
    [
      0.05,
      "a"
    ],
    [
      0.05,
      "n"
    ],
    [
      0.05,
      "c"
    ],
    [
      0.05,
      "h"
    ],
    [
      0.05,
      "o"
    ],
    [
      0.05,
      "r"
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "s"
    ],
    [
      0.05,
      "e"
    ],
    [
      0.05,
      "l"
    ],
    [
      0.05,
      "f"
    ],
    [
      0.05,
      "."
    ],
    [
      0.05,
      "c"
    ],
    [
      0.05,
      "l"
    ],
    [
      0.05,
      "a"
    ],
    [
      0.05,
      "s"
    ],
    [
      0.05,
      "s"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[33mInteger\u001b[0m(3)>> "
    ],
    [
      1.5,
      "e"
    ],
    [
      0.05,
      "x"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "t"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[31m4\u001b[0m(2)>> "
    ],
    [
      1.5,
      "e"
    ],
    [
      0.05,
      "x"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "t"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1)>> "
    ],
    [
      1.5,
      "d"
    ],
    [
      0.05,
      "e"
    ],
    [
      0.05,
      "f"
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "g"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1) | "
    ],
    [
      0.05,
      "  "
    ],
    [
      0.5,
      "a"
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "="
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "1"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1) | "
    ],
    [
      0.05,
      "  "
    ],
    [
      0.5,
      "R"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "b"
    ],
    [
      0.05,
      "."
    ],
    [
      0.05,
      "a"
    ],
    [
      0.05,
      "n"
    ],
    [
      0.05,
      "c"
    ],
    [
      0.05,
      "h"
    ],
    [
      0.05,
      "o"
    ],
    [
      0.05,
      "r"
    ],
    [
      0.05,
      " "
    ],
    [
      0.05,
      "b"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "n"
    ],
    [
      0.05,
      "d"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "n"
    ],
    [
      0.05,
      "g"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1) | "
    ],
    [
      0.05,
      "  "
    ],
    [
      0.5,
      "e"
    ],
    [
      0.05,
      "n"
    ],
    [
      0.05,
      "d"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[1A\u001b[K\u001b[32m\"rock\"\u001b[0m(1) | end\r\n"
    ],
    [
      0.05,
      "=> \u001b[36m:g\u001b[0m\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1)>> "
    ],
    [
      1.5,
      "a"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "  \u001b[33m\u001b[33m\u001b[33m(rib)\u001b[0m\u001b[0m\u001b[0m:\u001b[31m2\u001b[0m:in \u001b[32m\u001b[32m\u001b[32m`main'\u001b[0m\u001b[0m\u001b[0m\r\n"
    ],
    [
      0.05,
      "\u001b[35mNameError: undefined local variable or method `a' for \"rock\":String\u001b[0m\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1)>> "
    ],
    [
      1.5,
      "g"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[33m\"rock\"\u001b[0m(2)>> "
    ],
    [
      1.5,
      "a"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "=> \u001b[31m1\u001b[0m\r\n"
    ],
    [
      0.05,
      "\u001b[33m\"rock\"\u001b[0m(2)>> "
    ],
    [
      1.5,
      "e"
    ],
    [
      0.05,
      "x"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "t"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      "\u001b[32m\"rock\"\u001b[0m(1)>> "
    ],
    [
      1.5,
      "e"
    ],
    [
      0.05,
      "x"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "t"
    ],
    [
      0.05,
      "\r\n"
    ],
    [
      0.05,
      ">> "
    ],
    [
      1.5,
      "e"
    ],
    [
      0.05,
      "x"
    ],
    [
      0.05,
      "i"
    ],
    [
      0.05,
      "t"
    ],
    [
      0.05,
      "\r\n"
    ]
  ]
}


================================================
FILE: bin/rib
================================================
#!/usr/bin/env ruby

require 'rib/runner'
Rib.config[:mimic_irb] = true
Rib::Runner.run(ARGV)


================================================
FILE: bin/rib-all
================================================
#!/usr/bin/env ruby

require 'rib/runner'
require 'rib/all'
Rib::Runner.run(ARGV)


================================================
FILE: bin/rib-auto
================================================
#!/usr/bin/env ruby

require 'rib/runner'
# create the shell before app to prvent your bundler (if any) kicks in
Rib.shell
# we need to require anything before loading the app,
# and both `rib auto` (true) and `rib-auto` (nil) should work
require 'rib/core' if Rib.config.delete(:mimic_irb) != false
require 'rib/app/auto'
# load the app
Rib::Auto.load
Rib::Runner.run(ARGV)


================================================
FILE: bin/rib-min
================================================
#!/usr/bin/env ruby

require 'rib/runner'
Rib.config[:mimic_irb] = false
Rib::Runner.run(ARGV)


================================================
FILE: bin/rib-rack
================================================
#!/usr/bin/env ruby

require 'rib/runner'
# create the shell before app to prvent your bundler (if any) kicks in
Rib.shell
# we need to require anything before loading the app,
# and both `rib auto` (true) and `rib-auto` (nil) should work
require 'rib/core' if Rib.config.delete(:mimic_irb) != false
require 'rib/app/rack'
# load the app
Rib::Rack.load
Rib::Runner.run(ARGV)


================================================
FILE: bin/rib-rails
================================================
#!/usr/bin/env ruby

require 'rib/runner'
# create the shell before app to prvent your bundler (if any) kicks in
Rib.shell
# we need to require anything before loading the app,
# and both `rib auto` (true) and `rib-auto` (nil) should work
require 'rib/core' if Rib.config.delete(:mimic_irb) != false
require 'rib/app/rails'
# load the app
Rib::Rails.load
Rib::Runner.run(ARGV)


================================================
FILE: lib/rib/all.rb
================================================
# frozen_string_literal: true

require 'rib/core'
require 'rib/more'


================================================
FILE: lib/rib/api.rb
================================================
# frozen_string_literal: true

module Rib; module API
  # Called before shell starts looping
  def before_loop
    self
  end

  # Called after shell finishes looping
  def after_loop
    self
  end

  # Handle interrupt (control-c)
  def handle_interrupt; puts                ; end
  # The prompt string of this shell
  def prompt       ; config[:prompt]        ; end
  # The result prompt string of this shell
  def result_prompt; config[:result_prompt] ; end
  # The name of this shell
  def name         ; config[:name]          ; end
  # The binding for evaluation
  def eval_binding ; config[:binding]       ; end
  # The line number for next evaluation
  def line         ; config[:line]          ; end
  # When the application loaded
  def started_at   ; config[:started_at]    ; end

  # Main loop
  def in_loop
    input = catch(:rib_exit){ loop_once while running? }
    puts if input == nil && running?
  end

  # Loop iteration: REPL
  def loop_once
    input, result, err = get_input, nil, nil
    throw(:rib_exit, input) if config[:exit].include?(input)

    result, err = eval_input(input)

    if err
      print_eval_error(err)
    elsif input.strip != '' && !equal_rib_skip(result)
      print_result(result)
    else
      # print nothing for blank input or Rib::Skip
    end

    flush_warnings

    [result, err]
  rescue Interrupt
    handle_interrupt
  end

  # Get user input. This is most likely overrided in Readline plugin
  def get_input
    print(prompt)
    if input = $stdin.gets
      input.chomp
    else
      nil
    end
  end

  # Evaluate the input using #loop_eval and handle it
  def eval_input input
    [loop_eval(input), nil]
  rescue SystemExit
    throw(:rib_exit, input)
  rescue Exception => e
    [nil, e]
  ensure
    config[:line] += 1
  end

  # Evaluate user input with #eval_binding, name and line
  def loop_eval input
    if eval_binding.kind_of?(Binding)
      eval_binding.eval(input, "(#{name})", line)
    else
      eval_binding.instance_eval(input, "(#{name})", line)
    end
  end

  def puts str=''
    super
  end

  # Print result using #format_result
  def print_result result
    puts(format_result(result))
  rescue StandardError, SyntaxError => e
    warn("Error while printing result:\n  #{format_error(e)}")
  end

  # Print evaluated error using #format_error
  def print_eval_error err
    puts(format_error(err))
  rescue StandardError, SyntaxError => e
    warn("Error while printing error:\n  #{format_error(e)}")
  end

  def warn message
    warnings << message
  end

  # Format result using #result_prompt
  def format_result result
    "#{result_prompt}#{inspect_result(result)}"
  end

  def inspect_result result
    string = result.inspect
    warn("#{result.class}#inspect is not returning a string") unless
      string.kind_of?(String)
    string
  end

  # Format error raised in #loop_eval with #get_error
  def format_error err
    message, backtrace = get_error(err)
    "#{message}\n    #{backtrace.join("\n    ")}"
  end
  module_function :format_error

  # Get error message and backtrace from a particular error
  def get_error err
    ["#{err.class}: #{err.message}", format_backtrace(err.backtrace)]
  end
  module_function :get_error

  def format_backtrace backtrace
    backtrace
  end

  private
  def equal_rib_skip result
    result == Rib::Skip
  rescue
    # do nothing, it cannot respond to == correctly, it can't be Rib::Skip
  end

  def flush_warnings
    Rib.warn(warnings.shift) until warnings.empty?
  end
end; end


================================================
FILE: lib/rib/app/auto.rb
================================================
# frozen_string_literal: true

module Rib; module Auto
  module_function
  def load
    app, name = %w[rails rack].find{ |n|
      require "rib/app/#{n}"
      a = Rib.const_get(n.capitalize)
      break a, n if a.public_send("#{n}?")
    }

    if app
      Rib.say("Found #{name.capitalize}, loading it...")
      begin
        app.load
      rescue LoadError => e
        Rib.warn("Error: #{e}", "Is this a #{app} app?")
      end
    else
      Rib.warn("No app found")
    end
  end
end; end


================================================
FILE: lib/rib/app/rack.rb
================================================
# frozen_string_literal: true

module Rib; module Rack
  singleton_class.module_eval{ attr_accessor :app }

  module_function
  def load
    load_rack
  rescue LoadError => e
    Rib.abort("Error: #{e}", "Is this a Rack app?")
  end

  def load_rack
    require 'rack'
    Rib.abort("Error: Cannot find config.ru") unless rack?
    app, _ = ::Rack::Builder.parse_file(configru_path)
    self.app = app
    Rib.shell.eval_binding.eval('def app; Rib::Rack.app; end')
    Rib.say("Access your app via :app method")
  end

  def rack?
    File.exist?(configru_path)
  end

  def configru_path
    "#{Rib.config[:prefix]}/config.ru"
  end
end; end


================================================
FILE: lib/rib/app/rails.rb
================================================
# frozen_string_literal: true

module Rib; module Rails
  module_function
  def load
    load_rails
  rescue LoadError => e
    Rib.abort("Error: #{e}", "Is this a Rails app?")
  end

  def load_rails
    require path_for('boot')

    if File.exist?(path_for('application.rb'))
      Rib::Rails.load_rails3
    else
      Rib::Rails.load_rails2
    end
  end

  def load_rails2
    optparse_env
    Rib.silence{
      # rails 2 is so badly written
      require 'stringio'
       stderr = $stderr
      $stderr = StringIO.new
      Object.const_set('RAILS_ENV', ENV['RAILS_ENV'] || 'development')
      $stderr = stderr
    }

    # copied from commands/console
    [path_for('environment'),
     'console_app',
     'console_with_helpers'].each{ |f| require f }

    optparse_rails
  end

  def load_rails3
    optparse_env

    # copied from rails/commands
    require path_for('application')
    ::Rails.application.require_environment!

    optparse_rails
  end

  # copied from rails/commands/console
  def optparse_env
    # Has to set the RAILS_ENV before config/application is required
    if ARGV.first && !ARGV.first.index("-") && env = ARGV.shift # has to shift the env ARGV so IRB doesn't freak
      ENV['RAILS_ENV'] = %w(production development test).detect {|e| e =~ /^#{env}/} || env
    end
  end

  # copied from rails/commands/console
  def optparse_rails
    require 'optparse'
    options = {}

    OptionParser.new do |opt|
      opt.banner = "Usage: rib rails [environment] [options]"
      opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
      opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
      opt.parse!(ARGV)
    end

      # rails 3
    if ::Rails.respond_to?(:application) && (app = ::Rails.application)
      # rails 3.1
      if app.respond_to?(:sandbox)
        app.sandbox = options[:sandbox]
        app.load_console
      # rails 3.0
      else
        app.load_console(options[:sandbox])
      end
    else
      # rails 2
      require 'console_sandbox' if options[:sandbox]
    end

    if options[:debugger]
      begin
        require 'ruby-debug'
        puts "=> Debugger enabled"
      rescue Exception
        puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
        exit
      end
    end

    if options[:sandbox]
      puts "Loading #{::Rails.env} environment in sandbox (Rails #{::Rails.version})"
      puts "Any modifications you make will be rolled back on exit"
    else
      puts "Loading #{::Rails.env} environment (Rails #{::Rails.version})"
    end

    # rails 3.2
    if ::Rails.const_defined?(:ConsoleMethods)
      Rib.shell.eval_binding.eval('extend ::Rails::ConsoleMethods')
    end
  end

  def rails?
    File.exist?(path_for('boot.rb')) &&
      File.exist?(path_for('environment.rb'))
  end

  def path_for file
    File.expand_path("#{Rib.config[:prefix]}/config/#{file}")
  end
end; end


================================================
FILE: lib/rib/config.rb
================================================
# frozen_string_literal: true

require 'rib'
Rib.require_config


================================================
FILE: lib/rib/core/completion.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module Completion
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def before_loop
    return super if Completion.disabled?
    config[:completion]                ||= {}
    config[:completion][:gems]         ||= []
    config[:completion][:eval_binding] ||= method(:eval_binding).to_proc
    Rib.silence{Bond.start(config[:completion]) unless Bond.started?}
    super
  end
end; end

begin
  Rib.silence{require 'bond'}
rescue LoadError => e
  Rib.warn("Error: #{e}"                                    ,
           "Please install bond to use completion plugin:\n",
           "    gem install bond\n"                         ,
           "Or add bond to Gemfile if that's the case"      )
  Rib::Completion.disable
end


================================================
FILE: lib/rib/core/history.rb
================================================
# frozen_string_literal: true

require 'rib'
require 'fileutils'

module Rib; module History
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def before_loop
    return super if History.disabled?
    history_file
    history_size
    FileUtils.mkdir_p(File.dirname(history_file_path))
    read_history
    Rib.say("History read from: #{history_file_path}") if $VERBOSE
    super
  end

  def after_loop
    return super if History.disabled?
    write_history
    Rib.say("History wrote to: #{history_file_path}") if $VERBOSE
    super
  end

  def get_input
    return super if History.disabled?
    (history << super).last
  end

  # --------------- Plugin API ---------------

  # The history data
  def history; config[:history] ||= []; end

  # Read config[:history_file] into #history, handled in history_file plugin
  def read_history
    return super if History.disabled?
    File.exist?(history_file_path) && history.empty? &&
      File.readlines(history_file_path).each{ |e| history << e.chomp }
  end

  # Write #history into config[:history_file], handled in history_file plugin
  def write_history
    return super if History.disabled?
    history_text = "#{history.to_a.last(history_size).join("\n")}\n"
    File.write(history_file_path, history_text)
  end



  private
  def history_file
    config[:history_file]      ||= File.join(Rib.home, 'history.rb')
  end

  def history_file_path
    config[:history_file_path] ||= File.expand_path(history_file)
  end

  def history_size
    config[:history_size] ||= 500
  end
end; end


================================================
FILE: lib/rib/core/last_value.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module LastValue
  extend Plugin
  Shell.use(self)

  attr_reader :last_value, :last_exception

  def print_result result
    return super if LastValue.disabled?
    @last_value = result
    super
  end

  def print_eval_error err
    return super if LastValue.disabled?
    @last_exception = err
    super
  end



  module Imp
    def last_value
      Rib.shell.last_value
    end

    def last_exception
      Rib.shell.last_exception
    end
  end

  Rib.extend(Imp)
end; end


================================================
FILE: lib/rib/core/multiline.rb
================================================
# frozen_string_literal: true

require 'rib'

# from https://github.com/janlelis/ripl-multi_line
module Rib; module Multiline
  extend Plugin
  Shell.use(self)

  engine = if Object.const_defined?(:RUBY_ENGINE)
             RUBY_ENGINE
           else
             'ruby'
           end

  # test those:
  # ruby -e '"'
  # ruby -e '{'
  # ruby -e '['
  # ruby -e '('
  # ruby -e '/'
  # ruby -e 'class C'
  # ruby -e 'def f'
  # ruby -e 'begin'
  # ruby -e 'case 1'
  # ruby -e 'eval "1+1.to_i +"'
  # ruby -e 'eval "1+1.to_i -"'
  # ruby -e 'eval "1+1.to_i *"'
  # ruby -e 'eval "1+1.to_i /"'
  # ruby -e 'eval "1+1.to_i &"'
  # ruby -e 'eval "1+1.to_i |"'
  # ruby -e 'eval "1+1.to_i ^"'
  BINARY_OP = %w[tUPLUS tUMINUS tSTAR tREGEXP_BEG tAMPER]
  RUBY20_IO = %w[unary+ unary-  *     tREGEXP_BEG &].
              map(&Regexp.method(:escape))
  ERROR_REGEXP = case engine
    when 'ruby' ; Regexp.new(
                    [ # string or regexp
                      "unterminated \\w+ meets end of file",
                      # mri and rubinius
                      "unexpected (#{BINARY_OP.join('|')}), expecting \\$end",
                      "syntax error, unexpected \\$end"    ,
                      # prism
                      "expected an? `.+?` to close the",
                      "expected a matching `\\)`",
                      # ruby 2.0 and prism
                      "unexpected end-of-input",
                      # ruby 2.0
                      "syntax error, unexpected (#{RUBY20_IO.join('|')}),"
                                                                  ].join('|'))
    when 'rbx'  ; Regexp.new(
                    [ # string or regexp
                      "unterminated \\w+ meets end of file",
                      # mri and rubinius
                      "syntax error, unexpected \\$end"    ,
                      # rubinius
                      "expecting keyword_end"              ,
                      "expecting keyword_then"             ,
                      "expecting keyword_when"             ,
                      "expecting keyword_do_cond"          ,
                      "expecting \\$end"                   ,
                      "expecting '.+'( or '.+')*"          ,
                      "missing '.+' for '.+' started on line \\d+"].join('|'))
    when 'jruby'; Regexp.new(
                    [ # string or regexp
                      "unterminated \\w+ meets end of file",
                      # jruby
                      "syntax error, unexpected end\\-of\\-file",
                      # jruby 9.0.4.0
                      "formal argument must be local variable",
                      # jruby 9.2.0.0
                      "syntax error, unexpected (#{RUBY20_IO.join('|')})",
                      "syntax error, unexpected '\\W'"
                                                                  ].join('|'))
    end

  # --------------- Rib API ---------------

  def loop_once
    return super if Multiline.disabled?
    result = nil
    catch(:rib_multiline) do
      result = super
      multiline_buffer.clear
    end
    result
  end

  def loop_eval input
    return super if Multiline.disabled?
    multiline_buffer << input
    if input =~ /\\\z/
      throw :rib_multiline
    else
      super(multiline_buffer.join("\n"))
    end
  end

  def print_eval_error err
    return super if Multiline.disabled?
    if multiline?(err)
      throw :rib_multiline
    else
      super
    end
  end

  def prompt
    return super if Multiline.disabled?
    if multiline_buffer.empty?
      super
    else
      mprompt = multiline_prompt[0, config[:prompt].size]
      "#{' '*(config[:prompt].size-mprompt.size)}#{mprompt}"
    end
  end

  def handle_interrupt
    return super if Multiline.disabled?
    if multiline_buffer.empty?
      super
    else
      print "[removed this line: #{multiline_buffer.pop}]"
      super
      throw :rib_multiline
    end
  end

  # --------------- Plugin API ---------------

  def multiline? err
    err.is_a?(SyntaxError) && err.message =~ ERROR_REGEXP
  end

  def multiline_prompt
    config[:multiline_prompt] ||= '| '
  end


  private
  def multiline_buffer
    @multiline_buffer ||= []
  end
end; end


================================================
FILE: lib/rib/core/readline.rb
================================================
# frozen_string_literal: true

require 'rib'
require 'readline'

module Rib; module Readline
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def before_loop
    return super if Readline.disabled?
    config[:history] = ::Readline::HISTORY
    super
  end

  def get_input
    return super if Readline.disabled?
    ::Readline.readline(prompt, true)
  end
end

unless ::Readline::HISTORY.respond_to?(:last)
  def (::Readline::HISTORY).last
    self[-1]
  end
end; end


================================================
FILE: lib/rib/core/squeeze_history.rb
================================================
# frozen_string_literal: true

require 'rib/core/history' # dependency

module Rib; module SqueezeHistory
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  # squeeze history in memory too
  def loop_once
    return super if SqueezeHistory.disabled?
    begin
      input, last_input = history[-1], history[-2]
    rescue IndexError # EditLine is really broken, to_a is needed for it
      array = history.to_a
      input, last_input = array[-1], array[-2]
    end
    history.pop if input.to_s.strip == '' ||
                  (history.size > 1 && input == last_input)
    super
  end

  # --------------- Plugin API ---------------

  # write squeezed history
  def write_history
    return super if SqueezeHistory.disabled?
    config[:history] = squeezed_history
    super
  end



  private
  def squeezed_history
    history.to_a.inject([]){ |result, item|
      if result.last == item || item.strip == ''
        result
      else
        result << item
      end
    }
  end
end; end


================================================
FILE: lib/rib/core/strip_backtrace.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module StripBacktrace
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def format_error err
    return super if StripBacktrace.disabled?
    message, backtrace = get_error(err)
    "#{message}\n  #{backtrace.join("\n  ")}"
  end

  def get_error err
    return super if StripBacktrace.disabled?
    ["#{err.class}: #{err.message}", format_backtrace(err.backtrace)]
  end

  module_function
  def format_backtrace backtrace
    return super if StripBacktrace.disabled?
    strip_home_backtrace(
      strip_cwd_backtrace(
        strip_rib_backtrace(super(backtrace))))
  end

  def strip_home_backtrace backtrace
    backtrace.map(&method(:replace_path_prefix).curry[ENV['HOME'], '~/'])
  end

  def strip_cwd_backtrace backtrace
    backtrace.map(&method(:replace_path_prefix).curry[Dir.pwd, ''])
  end

  def strip_rib_backtrace backtrace
    backtrace[
      0..backtrace.rindex{ |l| l =~ /\(#{name}\):\d+:in (?:`|').+?'/ } || -1]
  end

  def replace_path_prefix prefix, substitute, path
    path.sub(/\A#{Regexp.escape(prefix)}\//, substitute)
  end
end; end


================================================
FILE: lib/rib/core.rb
================================================
# frozen_string_literal: true

# before session starts
require 'rib/core/completion'

# upon session ends
require 'rib/core/history'

# upon formatting output
require 'rib/core/strip_backtrace'

# upon input
require 'rib/core/readline'
require 'rib/core/multiline'
require 'rib/core/squeeze_history'

# special tools
require 'rib/core/last_value'


================================================
FILE: lib/rib/debug.rb
================================================
# frozen_string_literal: true

require 'rib/config'
require 'rib/more/anchor'
Rib::Anchor.disable
Rib::Debugger.disable if Rib.const_defined?(:Debugger)


================================================
FILE: lib/rib/extra/autoindent.rb
================================================
# frozen_string_literal: true

require 'rib/core/history'   # otherwise the order might be wrong
require 'rib/core/readline'  # dependency
require 'rib/core/multiline' # dependency

module Rib; module Autoindent
  extend Plugin
  Shell.use(self)

  # begin block could be simpler, because it should also trigger
  # SyntaxError, otherwise indention would be wiped out.
  # but end block should be exactly match, because we don't have
  # SyntaxError information, also triggering SyntaxError doesn't
  # mean it's not an end block, thinking about nested multiline!
  BLOCK_REGEXP = {
    # rescue Expression? (=> VariableName)?
    # consider cases:
    # rescue
    # rescue=>e
    # rescue => e
    # rescue =>e
    # rescue E=>e
    # rescue E
    # rescue E => e
    # rescue E=> e
    # rescue E =>e
    # ensure
    /^begin$/ =>
      /^(end)\b|^else$|^rescue *((\w+)? *(=> *\w+)?)?$|^ensure$/,
    /^def\b/  =>
      /^(end)\b|^else$|^rescue *((\w+)? *(=> *\w+)?)?$|^ensure$/,
    # elsif Expression
    # consider cases:
    # elsif(true)
    # elsif true
    # elsif true == true
    # elsif (a = true) && false
    /^if\b/            => /^(end)\b|^else$|^elsif\b/,
    /^unless\b/        => /^(end)\b|^else$|^elsif\b/,
    /^case\b/          => /^(end)\b|^else$|when\b/  ,
    /^class\b/         => /^(end)\b/                ,
    /^module\b/        => /^(end)\b/                ,
    /^while\b/         => /^(end)\b/                ,
    /^for\b/           => /^(end)\b/                ,
    /^until\b/         => /^(end)\b/                ,
    # consider cases:
    # 'do
    # ' do
    # "' do
    # /do
    # '{
    # %q{
    # %q| do
    # hey, two lines are even harder!
    # "
    # begin
    /do( *\|.*\|)?$/ => /^(end)\b/                ,
    /\{( *\|.*\|)?$/ => /^(\})\B/                 ,
    /\($/            => /^(\))\B/                 ,
    /\[$/            => /^(\])\B/                 ,
    # those are too hard to deal with, so we use syntax error to double check
    # what about this then?
    # v = if true
    #     else
    #     end
  }

  # --------------- Rib API ---------------

  def before_loop
    return super if Autoindent.disabled?
    autoindent_spaces
    super
  end

  def get_input
    return super if Autoindent.disabled?
    # this is only a fix in case we don't autoindent correctly
    # if we're autoindenting 100% correct, then this is a useless check
    autoindent_stack.clear if multiline_buffer.empty?

    # this should be called after ::Readline.readline, but it's blocking,
    # and i don't know if there's any hook to do this, so here we use thread
    Thread.new do
      sleep(0.01)
      ::Readline.line_buffer = current_autoindent if
        ::Readline.line_buffer && ::Readline.line_buffer.empty?
    end

    super
  end

  def eval_input raw_input
    return super if Autoindent.disabled?
    input  = raw_input.strip
    indent = detect_autoindent(input)
    result, err = super
    handle_autoindent(input, indent, err)
    [result, err]
  end

  # --------------- Plugin API ---------------

  def detect_autoindent input
    _, backmark = BLOCK_REGEXP.find{ |key,  _| input =~ key }
    if backmark # e.g. begin
      [:right, backmark]
    elsif input =~ autoindent_stack.last
      if $1     # e.g. end, }, etc
        [:left_end]
      else      # e.g. elsif, rescue, etc
        [:left_tmp]
      end
    else
      [:stay]
    end
  end

  def handle_autoindent input, indent, err
    case indent.first
    when :right    # we need to go deeper
      if multiline?(err)
        if err.message =~ /unterminated \w+ meets end of file/
          # skip if we're in the middle of a string or regexp
        else
          # indent.last is the way (input regexp matches) to go back
          autoindent_stack << indent.last
        end
      end

    when :left_end # we need to go back
      # could happen in either multiline or not
      handle_last_line(input)
      autoindent_stack.pop

    when :left_tmp # temporarily go back
      handle_last_line(input) if multiline?(err)
    end
  end

  def handle_last_line input,
                       indent=current_autoindent(autoindent_stack.size-1)
    new_input = "#{indent}#{input}"
    puts("\e[1A\e[K#{prompt}#{new_input}")
    new_input
  end



  private
  def current_autoindent size=autoindent_stack.size
    autoindent_spaces * size
  end

  def autoindent_spaces
    config[:autoindent_spaces] ||= '  '
  end

  def autoindent_stack
    @autoindent_stack ||= []
  end
end; end

begin
  require 'readline_buffer'
rescue LoadError => e
  Rib.warn("Error: #{e}"                                               ,
           "Please install readline_buffer to use autoindent plugin:\n",
           "    gem install readline_buffer\n"                         ,
           "Or add readline_buffer to Gemfile if that's the case"      )
  Rib::Autoindent.disable
end


================================================
FILE: lib/rib/extra/byebug.rb
================================================
# frozen_string_literal: true

require 'rib/more/anchor'
require 'byebug/core'

# This is based on lib/byebug/processors/pry_processor.rb

module Rib; module Byebug
  extend Plugin
  Shell.use(self)

  def before_loop
    return super if Rib::Byebug.disabled?

    super
    # ::Byebug::RibProcessor.start
  end

  module Imp
    def byebug
      return if Rib::Byebug.disabled?

      ::Byebug::RibProcessor.start
    end

    def location
      Rib.shell.config[:byebug].location
    end

    def step times=1
      throw :rib_byebug, [:step, times]
    end

    def next lines=1
      throw :rib_byebug, [:next, lines]
    end

    def finish
      throw :rib_byebug, [:finish]
    end
  end

  Rib.extend(Imp)
end; end

module Byebug
  class RibProcessor < CommandProcessor
    def self.start
      Byebug.start
      Setting[:autolist] = false
      Context.processor = self
      steps = caller.index{ |path| !path.start_with?(__FILE__) }
      Byebug.current_context.step_out(steps + 2, true)
    end

    def at_line
      resume_rib
    end

    def at_return(_return_value)
      resume_rib
    end

    def at_end
      resume_rib
    end

    def at_breakpoint(breakpoint)
      raise NotImplementedError
    end

    def location
      context.location
    end

    private

    def print_location
      shell = Rib.shell
      shell.puts(shell.format_backtrace([location]).first)
    end

    def resume_rib
      return if Rib.shell.running?

      byebug_binding = frame._binding

      print_location

      action, *args = catch(:rib_byebug) do
        allowing_other_threads do
          Rib.anchor byebug_binding, :byebug => self
        end
      end

      perform(action, args)
    end

    def perform action, args
      case action
      when :step
        context.step_into(*args, frame.pos)
      when :next
        context.step_over(*args, frame.pos)
      when :finish
        context.step_out(1)
      end
    end
  end
end


================================================
FILE: lib/rib/extra/hirb.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module Hirb
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def format_result result
    return super if Hirb.disabled?
    ::Hirb::View.view_or_page_output(result) || super
  end
end

begin
  Rib.silence{
    require 'hirb'
    ::Hirb.enable
  }
rescue LoadError => e
  Rib.warn("Error: #{e}"                              ,
           "Please install hirb to use hirb plugin:\n",
           "    gem install hirb\n"                   ,
           "Or add hirb to Gemfile if that's the case")
  Rib::Hirb.disable
end; end


================================================
FILE: lib/rib/extra/paging.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module Paging
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  # Print if the it fits one screen, paging it through a pager otherwise.
  def puts str=''
    return super if Paging.disabled?
    if one_screen?(str)
      super
    else
      page_result(str)
    end
  end

  # `less -F` can't cat the output, so we need to detect by ourselves.
  # `less -X` would mess up the buffers, so it's not desired, either.
  def one_screen? str
    cols, lines = `tput cols`.to_i, `tput lines`.to_i
    (str.count("\n") + 2) <= lines && # count last line and prompt
      str.gsub(/\e\[[^m]*m/, '').size <= cols * lines
  end

  def page_result str
    less = IO.popen(pager, 'w')
    less.write(str)
    less.close_write
  rescue Errno::EPIPE
    # less quit without consuming all the input
  end

  def pager
    ENV['PAGER'] || 'less -R'
  end
end; end

pager = ENV['PAGER'] || 'less'

if `which #{pager}`.empty?
  Rib.warn("#{pager} is not available, disabling Rib::Paging")
  Rib::Paging.disable
elsif `which tput`.empty?
  Rib.warn("tput is not available, disabling Rib::Paging")
  Rib::Paging.disable
elsif ENV['TERM'] == 'dumb' || ENV['TERM'].nil?
  Rib.warn("Your terminal is dumb, disabling Rib::Paging")
  Rib::Paging.disable
end


================================================
FILE: lib/rib/extra/spring.rb
================================================
# frozen_string_literal: true

module Spring
  module Commands
    class Rib
      def call
        load `which rib`.chomp
      end
    end

    Spring.register_command 'rib', Rib.new
  end
end


================================================
FILE: lib/rib/more/anchor.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module Anchor
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def prompt
    return super if Rib::Anchor.disabled?
    return super unless anchor?

    level = "(#{Rib.shells.size - 1})"
    if Rib.const_defined?(:Color) &&
       kind_of?(Rib::Color)       &&
       Rib::Color.enabled?

      "#{format_color(eval_binding, prompt_anchor)}#{level}#{super}"
    else
      "#{prompt_anchor}#{level}#{super}"
    end
  end

  def anchor?
    !!config[:prompt_anchor]
  end



  private
  def prompt_anchor
    @prompt_anchor ||=
    if eval_binding.kind_of?(Binding)
      eval_binding.eval('self', __FILE__, __LINE__)
    else
      eval_binding
    end.inspect[0..9]
  end

  module Imp
    # Enter an interactive Rib shell based on a particular context.
    #
    # @api public
    # @param obj_or_binding [Object, Binding] The context of the shell.
    # @param opts [Hash] The config hash passed to the newly created shell.
    #   See {Rib::Shell#initialize} for all possible options.
    # @return [Rib::Skip] This is the mark telling Rib do not print anything.
    #   It's only used internally in Rib.
    # @see Rib::Shell#initialize
    # @example
    #   Rib.anchor binding
    #   Rib.anchor 123
    def anchor obj_or_binding, opts={}
      return if Rib::Anchor.disabled?

      if Rib.shell.running?
        Rib.shells << Rib::Shell.new(
          Rib.shell.config.merge( :binding       => obj_or_binding,
                                  :prompt_anchor => true         ).
                           merge(opts))
      else
          Rib.shell.config.merge!(:binding       => obj_or_binding,
                                  :prompt_anchor => true         ).
                           merge!(opts)
      end

      Rib.shell.loop
      Rib::Skip

    ensure
      Rib.shells.pop
    end

    def stop_anchors
      Rib.shells.select(&:anchor?).each(&:stop)
      Rib::Skip
    end
  end

  Rib.extend(Imp)
end; end


================================================
FILE: lib/rib/more/beep.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module Beep
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def loop_once
    return super if Beep.disabled?
    beep if started_at && (Time.now - started_at) > beep_threshold
    config[:started_at] = Time.now
    super
  end

  private
  def beep
    print "\a"
  end

  def beep_threshold
    config[:beep_threshold] ||= 5
  end
end; end


================================================
FILE: lib/rib/more/bottomup_backtrace.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module BottomupBacktrace
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def format_error err
    return super if BottomupBacktrace.disabled?
    message, backtrace = get_error(err)
    "  #{backtrace.join("\n  ")}\n#{message}"
  end

  def format_backtrace backtrace
    super(backtrace).reverse
  end
end; end


================================================
FILE: lib/rib/more/caller.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module Caller
  extend Plugin
  Shell.use(self)

  module Imp
    def caller *filters
      return if Rib::Caller.disabled?

      display_backtrace(super().drop(1), *filters)
    end

    def display_backtrace raw_backtrace, *filters
      backtrace = Rib.shell.format_backtrace(raw_backtrace)

      lib = %r{\brib-#{Rib::VERSION}/lib/rib/}
      if backtrace.first =~ lib
        backtrace.shift while backtrace.first =~ lib
      elsif backtrace.last =~ lib
        backtrace.pop while backtrace.last =~ lib
      end

      result = filters.map do |f|
        case f
        when Regexp
          f
        when String
          %r{\bgems/#{Regexp.escape(f)}\-[\d\.]+/lib/}
        end
      end.inject(backtrace, &:grep_v)

      Rib.shell.puts result.map{ |l| "  #{l}" }.join("\n")

      Rib::Skip
    end
  end

  Rib.extend(Imp)
end; end


================================================
FILE: lib/rib/more/color.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module Color
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def before_loop
    colors
    super
  end

  def format_result result
    return super if Color.disabled?
    "#{result_prompt}#{format_color(result)}"
  end

  def get_error err
    return super if Color.disabled?
    message, backtrace = super
    [format_color(err, message), backtrace]
  end

  def warn message
    return super if Color.disabled?
    super(red{message})
  end

  # --------------- Plugin API ---------------

  def colors
    config[:color] ||= {
      Numeric    => :red    ,
      String     => :green  ,
      Symbol     => :cyan   ,
      Array      => :blue   ,
      Hash       => :blue   ,
      NilClass   => :magenta,
      TrueClass  => :magenta,
      FalseClass => :magenta,
      Exception  => :magenta,
      Object     => :yellow }
  end

  def format_color result, display=inspect_result(result)
    case result
      when String ; send(colors[String ]){ display }
      when Numeric; send(colors[Numeric]){ display }
      when Symbol ; send(colors[Symbol ]){ display }

      when Array  ; send(colors[Array  ]){ '['     }   +
                      result.map{ |e   | if e.object_id == result.object_id
                                           send(colors[Array]){'[...]'}
                                         else
                                           format_color(e); end }.
               join(send(colors[Array  ]){ ', '    })  +
                    send(colors[Array  ]){ ']'     }

      when Hash   ; send(colors[Hash   ]){ '{'     }   +
                      result.map{ |k, v| format_color(k) +
                    send(colors[Hash   ]){ '=>'    }   +
                                         if v.object_id == result.object_id
                                           send(colors[Hash]){'{...}'}
                                         else
                                           format_color(v); end }.
               join(send(colors[Hash   ]){ ', '    }) +
                    send(colors[Hash   ]){ '}'     }

      else        ; if color = find_color(colors, result)
                    send(color){ display }
                    else
                    send(colors[Object]){ display }
                    end
    end
  end

  def format_backtrace backtrace
    colorize_backtrace(super(backtrace))
  end



  module_function
  def colorize_backtrace backtrace
    backtrace.map{ |b|
      path, msgs = b.split(':', 2)
      dir, sep, file = path.rpartition('/')
      msgs ||= (line - 1).to_s # msgs would be nil when input is next/break
      msg = msgs.sub(/(\d+)(:?)/) do
        m = Regexp.last_match
        "#{red{m[1]}}#{m[2]}"
      end.sub(/(?:`|').+?'/){green{Regexp.last_match[0]}}

      "#{dir+sep}#{yellow{file}}:#{msg}"
    }
  end

  def find_color colors, value
    (colors.sort{ |(k1, _), (k2, _)|
      # Class <=> Class
      if    k1 < k2 then -1
      elsif k1 > k2 then  1
      else                0
      end}.find{ |(klass, _)| value.kind_of?(klass) } || []).last
  end

  def color rgb
    "\e[#{rgb}m" + if block_given? then "#{yield}#{reset}" else '' end
  end

  def   black &block; color(30, &block); end
  def     red &block; color(31, &block); end
  def   green &block; color(32, &block); end
  def  yellow &block; color(33, &block); end
  def    blue &block; color(34, &block); end
  def magenta &block; color(35, &block); end
  def    cyan &block; color(36, &block); end
  def   white &block; color(37, &block); end
  def   reset &block; color( 0, &block); end
end; end

begin
  require 'win32console' if defined?(Gem) && Gem.win_platform?
rescue LoadError => e
  Rib.warn("Error: #{e}"                                                  ,
           "Please install win32console to use color plugin on Windows:\n",
           "    gem install win32console\n"                               ,
           "Or add win32console to Gemfile if that's the case"            )
  Rib::Color.disable
end


================================================
FILE: lib/rib/more/edit.rb
================================================
# frozen_string_literal: true

require 'rib'
require 'tempfile'

module Rib; module Edit
  extend Plugin
  Shell.use(self)

  module Imp
    def edit
      return if Rib::Edit.disabled?
      file = Tempfile.new(['rib.edit', '.rb'])
      file.puts(Rib.vars[:edit])
      file.close

      shell = Rib.shell
      system("#{shell.editor} #{file.path}")

      if shell.running?
        shell.send(:multiline_buffer).pop
      else
        shell.before_loop
      end

      shell.loop_eval(Rib.vars[:edit] = File.read(file.path))

    ensure
      file.close
      file.unlink
    end
  end

  def editor
    ENV['EDITOR'] || 'vim'
  end

  Rib.extend(Imp)
end; end


================================================
FILE: lib/rib/more/multiline_history.rb
================================================
# frozen_string_literal: true

require 'rib/core/history'   # dependency
require 'rib/core/multiline' # dependency

module Rib; module MultilineHistory
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def before_loop
    @multiline_trash = 0
    super
  end

  def loop_eval input
    return super if MultilineHistory.disabled?
    super
  ensure
    # SyntaxError might mean we're multiline editing
    handle_multiline unless multiline?($!)
  end

  def handle_interrupt
    return super if MultilineHistory.disabled?
    if multiline_buffer.size > 1
      multiline_trash
      @multiline_trash += 1
    end
    super
  end



  private
  def handle_multiline
    if multiline_buffer.size > 1
      # so multiline editing is considering done here
      # TODO: there's no history.pop(size)
      (multiline_buffer.size + multiline_trash).times{ history.pop }
      history << "\n" + multiline_buffer.join("\n")
    end
  end

  def multiline_trash
    @multiline_trash ||= 0
  end
end; end


================================================
FILE: lib/rib/more/multiline_history_file.rb
================================================
# frozen_string_literal: true

require 'rib/more/multiline_history'

module Rib; module MultilineHistoryFile
  extend Plugin
  Shell.use(self)

  # --------------- Rib API ---------------

  def before_loop
    return super if MultilineHistoryFile.disabled?
    multiline_history_file_token
    super
  end

  # --------------- Plugin API ---------------

  def read_history
    return super if MultilineHistoryFile.disabled?
    buffer = []
    File.exist?(history_file_path) && history.empty? &&
      IO.readlines(history_file_path).each{ |line|
        if line.end_with?(
             "#{config[:multiline_history_file_token]}\n")
          buffer << line[0...
                         -multiline_history_file_token.size-1] + "\n"
        else
          history << (buffer.join + line).chomp
          buffer = []
        end
      }
  end

  def write_history
    return super if MultilineHistoryFile.disabled?
    # TODO: hisotroy.map is MRI 1.9+
    config[:history] = history.to_a.map{ |line|
      line.gsub("\n", "#{config[:multiline_history_file_token]}\n")
    }
    super
  end



  private
  def multiline_history_file_token
    config[:multiline_history_file_token] ||= ' '
  end
end; end


================================================
FILE: lib/rib/more.rb
================================================
# frozen_string_literal: true

# upon session ends
require 'rib/more/multiline_history_file'

# upon formatting output
require 'rib/more/bottomup_backtrace'
require 'rib/more/color'

# upon input
require 'rib/more/multiline_history'

# special tools
require 'rib/more/anchor'
require 'rib/more/caller'
require 'rib/more/edit'

# upon application loads
require 'rib/more/beep'


================================================
FILE: lib/rib/plugin.rb
================================================
# frozen_string_literal: true

module Rib; module Plugin
  attr_accessor :disabled

  def enable
    self.disabled = false
    if block_given? then yield else enabled? end
  ensure
    self.disabled = true if block_given?
  end

  def disable
    self.disabled = true
    if block_given? then yield else enabled? end
  ensure
    self.disabled = false if block_given?
  end

  def enabled?
    !disabled
  end

  def disabled?
    !!disabled
  end

  # Backward compatibility
  def const_missing mod
    if Rib.const_defined?(mod)
      Rib.warn("Using #{mod} is deprecated, please change to Rib::#{mod}",
               "This compatibility layer would be removed in Rib 1.6+",
               "Called: #{caller.first}")
      Rib.const_get(mod)
    else
      super
    end
  end

  def self.extended mod
    return unless mod.name

    snake_name = mod.name.sub(/(\w+::)+?(\w+)$/, '\2').
      gsub(/([A-Z][a-z]*)/, '\\1_').downcase[0..-2]

    code = (%w[enable disable].map{ |meth|
      <<-RUBY
        def #{meth}_#{snake_name} &block
          #{mod.name}.#{meth}(&block)
        end
      RUBY
    } + %w[enabled? disabled?].map{ |meth|
      <<-RUBY
        def #{snake_name}_#{meth} &block
          #{mod.name}.#{meth}(&block)
        end
      RUBY
    }).join("\n")

    Rib.singleton_class.module_eval(code, __FILE__, __LINE__)
  end
end; end


================================================
FILE: lib/rib/runner.rb
================================================
# frozen_string_literal: true

require 'rib'

module Rib; module Runner
  module_function
  def options
    @options ||=
    [['ruby options:'    , ''                                      ],
     ['-e, --eval LINE'                                             ,
      'Evaluate a LINE of code'                                    ],

     ['-d, --debug'                                                 ,
      'Set debugging flags (set $DEBUG to true)'                   ],

     ['-w, --warn'                                                  ,
       'Turn warnings on (set $-w and $VERBOSE to true)'           ],

     ['-I, --include PATH'                                          ,
       'Specify $LOAD_PATH (may be used more than once)'           ],

     ['-r, --require LIBRARY'                                       ,
       'Require the library, before executing your script'         ],

     ['rib options:'     , ''                                      ],
     ['-c, --config FILE', 'Load config from FILE'                 ],
     ['-p, --prefix PATH', 'Prefix to locate the app. Default to .'],
     ['-n, --no-config'  , 'Suppress loading any config'           ],
     ['-h, --help'       , 'Print this message'                    ],
     ['-v, --version'    , 'Print the version'                     ]] +

    [['rib commands:'    , '']] + commands
  end

  def commands
     @commands ||=
      command_paths.map{ |path|
        name = File.basename(path)[/^rib\-(.+)$/, 1]
        [name, command_descriptions[name]      ||
               command_descriptions_find(path) || ' '] }
  end

  def command_paths
    @command_paths ||=
    Gem.path.map{ |path|
      Dir["#{path}/bin/*"].map{ |f|
        (File.executable?(f) && File.basename(f) =~ /^rib\-.+$/ && f) ||
         nil    # a trick to make false to be nil and then
      }.compact # this compact could eliminate them
    }.flatten
  end

  def command_descriptions
    @command_descriptions ||=
    {'all'    => 'Load all recommended plugins'              ,
     'min'    => 'Run the minimum essence'                   ,
     'auto'   => 'Run as Rails or Rack console (auto-detect)',
     'rails'  => 'Run as Rails console'                      ,
     'rack'   => 'Run as Rack console'                       }
  end

  # Extract the text below __END__ in the bin file as the description
  def command_descriptions_find path
    # FIXME: Can we do better? This is not reliable
    File.read(path) =~ /Gem\.activate_bin_path\(['"](.+)['"], ['"](.+)['"],/
    (File.read(Gem.bin_path($1, $2))[/\n__END__\n(.+)$/m, 1] || '').strip
  end

  def run argv=ARGV
    (@running_commands ||= []) << Rib.config[:name]
    unused = parse(argv)
    # we only want to run the loop if we're running the rib command,
    # otherwise, it must be a rib app, which we only want to parse
    # the arguments and proceed (this is recursive!)
    if @running_commands.pop == 'rib'
      Rib.warn("Unused arguments: #{unused.inspect}") unless unused.empty?
      require 'rib/core' if Rib.config.delete(:mimic_irb)
      loop
    end
  end

  def loop retry_times=5
    Rib.shell.loop
  rescue => e
    if retry_times <= 0
      Rib.warn("Error: #{e}. Too many retries, give up.")
    elsif Rib.shells.last.running?
      Rib.warn("Error: #{e}. Relaunching a new shell... ##{retry_times}")
      Rib.warn("Backtrace: #{e.backtrace}") if $VERBOSE
      Rib.shells.pop
      Rib.shells << Rib::Shell.new(Rib.config)
      retry_times -= 1
      retry
    else
      Rib.warn("Error: #{e}. Closing.")
      Rib.warn("Backtrace: #{e.backtrace}") if $VERBOSE
    end
  end

  def parse argv
    unused = []
    until argv.empty?
      case arg = argv.shift
      when /^-e=?(.+)?/, /^--eval=?(.+)?/
        Rib.shell.eval_binding.eval(
          $1 || argv.shift || '', __FILE__, __LINE__)

      when /^-d/, '--debug'
        $DEBUG = true
        parse_next(argv, arg)

      when /^-w/, '--warn'
        $-w, $VERBOSE = true, true
        parse_next(argv, arg)

      when /^-I=?(.+)?/, /^--include=?(.+)?/
        paths = ($1 || argv.shift).split(':')
        $LOAD_PATH.unshift(*paths)

      when /^-r=?(.+)?/, /^--require=?(.+)?/
        require($1 || argv.shift)

      when /^-c=?(.+)?/, /^--config=?(.+)?/
        Rib.config_path = $1 || argv.shift

      when /^-p=?(.+)?/, /^--prefix=?(.+)?/
        Rib.config[:prefix] = $1 || argv.shift

      when /^-n/, '--no-config'
        Rib.config_path = Rib::Skip
        parse_next(argv, arg)

      when /^-h/, '--help'
        puts(help)
        exit

      when /^-v/, '--version'
        require 'rib/version'
        puts(Rib::VERSION)
        exit

      when /^[^-]/
        load_command(arg)

      else
        unused << arg
      end
    end
    unused
  end

  def parse_next argv, arg
    argv.unshift("-#{arg[2..-1]}") if arg.size > 2
  end

  def help
    optt = options.transpose
    maxn = optt.first.map(&:size).max
    maxd = optt.last .map(&:size).max
    "Usage: #{Rib.config[:name]}"                    \
    " [ruby OPTIONS] [rib OPTIONS] [rib COMMANDS]\n" +
    options.map{ |(name, desc)|
      if name.end_with?(':')
        name
      else
        sprintf("  %-*s  %-*s", maxn, name, maxd, desc)
      end
    }.join("\n")
  end

  def load_command command
    bin  = "rib-#{command}"
    path = which_bin(bin)
    if path == ''
      Rib.warn(
        "Can't find #{bin} in $PATH. Please make sure it is installed,",
        "or is there any typo? You can try this to install it:\n"      ,
        "    gem install #{bin}")
    else
      Rib.config[:name] = bin
      load(path)
    end
  end

  def which_bin bin # handle windows here
    `which #{bin}`.strip
  rescue Errno::ENOENT # probably a windows platform, try where
    `where #{bin}`.lines.first.strip
  end
end; end


================================================
FILE: lib/rib/shell.rb
================================================
# frozen_string_literal: true

require 'rib/plugin'
require 'rib/api'

module Rib; class Shell
  include API

  def self.use mod
    include mod
  end

  attr_reader :config

  # Create a new shell.
  #
  # @api public
  # @param config [Hash] The config of the shell.
  # @option config [String] :config ('~/.rib/config.rb')
  #   The path to Rib config file.
  # @option config [String] :name ('rib')
  #   The name of the shell. Used for Rib application.
  # @option config [String] :result_prompt ('=> ')
  # @option config [String] :prompt ('>> ')
  # @option config [Binding, Object] :binding (new_private_binding)
  #   The context of the shell. Could be an Object.
  # @option config [Array<String>] :exit ([nil])
  #   The keywords to exit the shell. `nil` means EOF (ctrl+d).
  # @option config [Fixnum] :line (1) The beginning of line number.
  # @option config [String] :history_file ('~/.rib/config/history.rb')
  #   (Only if {Rib::History} plugin is used) The path to history file.
  # @option config [Fixnum] :history_size (500)
  #   (Only if {Rib::History} plugin is used) Maximum numbers of history.
  # @option config [Hash<Class, Symbol>] :color (...)
  #   (Only if {Rib::Color} plugin is used) Data type colors mapping.
  # @option config [String] :autoindent_spaces ('  ')
  #   (Only if {Rib::Autoindent} plugin is used) The indented string.
  def initialize(config={})
    config[:binding] ||= new_private_binding
    self.config = {:result_prompt => '=> ',
                   :prompt        => '>> ',
                   :exit          => [nil],
                   :line          => 1    }.merge(config)
    stop
  end

  # Loops shell until user exits
  def loop
    before_loop
    set_trap
    start
    in_loop
    stop
    self
  rescue Exception => e
    Rib.warn("Error while running loop:\n  #{format_error(e)}")
    raise
  ensure
    release_trap
    after_loop
  end

  def start
    @running = true
  end

  def stop
    @running = false
  end

  def running?
    !!@running
  end

  def warnings
    @warnings ||= []
  end

  protected
  attr_writer :config

  def set_trap
    @trap_proc = trap('INT'){ raise Interrupt }
  end

  def release_trap
    trap('INT', &@trap_proc) if @trap_proc.kind_of?(Proc)
  end

  private
  # Avoid namespace pollution from rubygems bin stub.
  # To be specific, version and str.
  def new_private_binding
    TOPLEVEL_BINDING.eval <<-RUBY
      singleton_class.module_eval do
        Rib.warn("Removing existing main...") if method_defined?(:main)
        def main; binding; end # any way to define <main> method?
      end
      ret = main
      singleton_class.send(:remove_method, 'main') # never pollute anything
      ret
    RUBY
  end
end; end


================================================
FILE: lib/rib/test/history.rb
================================================
# frozen_string_literal: true

require 'tempfile'

copy :setup_history do
  before do
    if readline?
      ::Readline::HISTORY.clear
      stub_readline
    end

    shell(:history_file => history_file)
  end

  after do
    tempfile.unlink if @tempfile
  end

  def tempfile
    @tempfile ||= Tempfile.new('rib')
  end

  def history_file
    tempfile.path
  end
end


================================================
FILE: lib/rib/test/multiline.rb
================================================
# frozen_string_literal: true

copy :setup_multiline do
  def setup_input str
    if readline?
      stub_readline(:mock)
    else
      mock($stdin).gets{ str.chomp }
    end
  end

  def input str
    setup_input(str)
    mock(shell).throw(:rib_multiline)
  end

  def input_done str, err=nil
    setup_input(str)
    if err
      mock(shell).print_eval_error(is_a(err)){}
    else
      mock(shell).print_result(is_a(Object)){}
    end
    shell.loop_once
    ok
  end

  def check str, err=nil
    yield if block_given?

    lines = str.split("\n")
    lines[0...-1].each{ |line|
      input(line)
      shell.loop_once
    }
    input_done(lines.last, err)
  end

  before do
    stub_output
  end
end

copy :multiline do
  would 'work with no prompt' do
    shell.config[:prompt] = ''
    check <<~RUBY
      def f
        0
      end
    RUBY
  end

  would 'def f' do
    check <<~RUBY
      def f
        1
      end
    RUBY
  end

  would 'class C' do
    check <<~RUBY
      class C
      end
    RUBY
  end

  would 'begin' do
    check <<~RUBY
      begin
      end
    RUBY
  end

  would 'begin with RuntimeError' do
    check <<~RUBY, RuntimeError
      begin
        raise 'multiline raised an error'
      end
    RUBY
  end

  would 'do end' do
    check <<~RUBY
      [].each do
      end
    RUBY
  end

  would 'block brace' do
    check <<~RUBY
      [].each{
      }
    RUBY
  end

  would 'hash' do
    check <<~RUBY
      {
      }
    RUBY
  end

  would 'hash value' do
    check <<~RUBY
      {1 =>
       2}
    RUBY
  end

  would 'array' do
    check <<~RUBY
      [
      ]
    RUBY
  end

  would 'group' do
    check <<~RUBY
      (
      )
    RUBY
  end

  would 'string double quote' do
    check <<~RUBY
      "
      "
    RUBY
  end

  would 'string single quote' do
    check <<~RUBY
      '
      '
    RUBY
  end

  would 'be hash treated as a block SyntaxError' do
    code = <<~RUBY
      puts { :x => 10 }.class
    RUBY

    if RUBY_VERSION >= '3.0.0'
      check code do
        stub(shell.config[:binding_object]).puts{}
      end
    else
      check code, SyntaxError
    end
  end

  would 'SyntaxError' do
    check <<~RUBY, SyntaxError
      s-y n
    RUBY
  end

  would 'binary operator +' do
    check <<~RUBY
      1/1.to_i +
      1
    RUBY
  end

  would 'binary operator -' do
    check <<~RUBY
      1*1.to_i -
      1
    RUBY
  end

  would 'binary operator *' do
    check <<~RUBY
      1-1.to_i *
      1
    RUBY
  end

  would 'binary operator /' do
    code = <<~RUBY
      1+1.to_i /
      1
    RUBY

    if RUBY_VERSION >= '3.0.0'
      check code.lines.first, SyntaxError
    else
      check code
    end
  end

  would 'binary operator |' do
    check <<~RUBY
      1+1.to_i |
      1
    RUBY
  end

  would 'binary operator &' do
    check <<~RUBY
      1+1.to_i &
      1
    RUBY
  end

  would 'binary operator ^' do
    check <<~RUBY
      1+1.to_i ^
      1
    RUBY
  end

  would 'backslash at the end' do
    check <<~RUBY
      'nice ' \\
      'shell'
    RUBY
  end
end


================================================
FILE: lib/rib/test.rb
================================================
# frozen_string_literal: true

require 'pork/auto'
require 'muack'

Pork::Suite.include(Muack::API)

require 'rib'

copy :rib do
  before do
    Rib.disable_plugins
  end

  after do
    Muack.verify
  end

  def shell opts={}
    @shell ||= new_shell(opts)
  end

  def new_shell opts={}
    binding_object = Object.new
    result = Rib::Shell.new(
      {:binding => binding_object.instance_eval{binding},
       :binding_object => binding_object}.
      merge(opts))
    yield(result) if block_given?
    result.before_loop
  end

  def stub_output
    stub(shell).print(is_a(String)){}
    stub(shell).puts(is_a(String)){}
    stub(shell).puts{}
  end

  def readline?
    Rib.constants.map(&:to_s).include?('Readline') &&
      Rib::Readline.enabled?
  end

  def stub_readline meth=:stub
    send(meth, ::Readline).readline(is_a(String), true) do
      (::Readline::HISTORY << str.chomp).last
    end
  end

  singleton_class.module_eval do
    def test_for *plugins, &block
      require 'rib/all' # exhaustive tests
      rest = Rib.plugins - plugins

      before do
        Rib.enable_plugins(plugins)
        Rib.disable_plugins(rest)
      end

      describe "enabling #{plugins}" do
        block.call

        case ENV['TEST_LEVEL']
        when '0'
        when '1'
          test_level1(rest, block)
        when '2'
          test_level2(rest, block)
        when '3'
          test_level3(rest, block)
        else # test_level3 is too slow because of rr (i guess)
          test_level2(rest, block)
        end
      end
    end

    def test_level1 rest, block
      rest.each{ |target|
        target.enable

        describe "also enabling #{target}" do
          block.call
        end

        target.disable
      }
    end

    def test_level2 rest, block
      rest.combination(2).each{ |targets|
        Rib.enable_plugins(targets)

        describe "also enabling #{targets.join(', ')}" do
          block.call
        end

        Rib.disable_plugins(targets)
      }
    end

    def test_level3 rest, block
      if rest.empty?
        block.call
      else
        rest[0].enable

        describe "also enabling #{rest[0]}" do
          test_level3(rest[1..-1], block)
        end

        rest[0].disable

        describe "disabling #{rest[0]}" do
          test_level3(rest[1..-1], block)
        end
      end
    end
  end
end

def main
  'rib'
end

Rib::Blackhole = Object.new
b = Rib::Blackhole.singleton_class
b.instance_methods(true).each{ |m|
  b.send(:undef_method, m) unless
    [:object_id, :__send__, :__id__].include?(m) }


================================================
FILE: lib/rib/version.rb
================================================
# frozen_string_literal: true

module Rib
  VERSION = '1.6.3'
end


================================================
FILE: lib/rib.rb
================================================
# frozen_string_literal: true

require 'rib/shell'
require 'rib/version'

module Rib
  Skip = Object.new

  module_function
  # All default Rib configs, would be passed to Shell.new in Rib.shell,
  # but calling Shell.new directly won't bring this in.
  #
  # @api public
  def config
    @config ||= {:name => 'rib', :prefix => '.', :started_at => Time.now}
  end

  # All shells in the memory
  def shells
    @shells ||= []
  end

  # All shared variables for all shells
  def vars
    @vars   ||= {}
  end

  # Rib.home is where Rib storing things. By default, it goes to '~/.rib',
  # or somewhere containing a 'config.rb' or 'history.rb' in the order of
  # './.rib' (project specific config), or '~/.rib' (home config), or
  # '~/.config/rib' (home config, residing in ~/.config)
  #
  # @api public
  def home
    ENV['RIB_HOME'] ||= File.expand_path(
      ["#{config[:prefix]}/.rib", '~/.rib', '~/.config/rib'].find{ |path|
        File.exist?(File.expand_path(path))
      } || '~/.rib'
    )
  end

  # Convenient shell accessor, which would just give you current last shell
  # or create one and load the config file. If you need a clean shell which
  # does not load config file, use Shell.new instead.
  #
  # @api public
  def shell
    shells.last || begin
      require_config if config_path && config_path != Skip
      (shells << Shell.new(config)).last
    end
  end

  # All plugins which have been loaded into the memory regardless
  # it's enabled or not.
  #
  # @api public
  def plugins
    Shell.ancestors.drop(1).select{ |a| a.singleton_class < Plugin }
  end

  # Convenient way to disable all plugins in the memory.
  # This could also take a list of plugins and disable them.
  #
  # @api public
  # @param plugs [Array] (Rib.plugins) Plugins which would be disabled.
  def disable_plugins plugs=plugins
    plugs.each(&:disable)
  end

  # Convenient way to enable all plugins in the memory.
  # This could also take a list of plugins and enable them.
  #
  # @api public
  # @param plugs [Array] (Rib.plugins) Plugins which would be enabled.
  def enable_plugins plugs=plugins
    plugs.each(&:enable)
  end

  # Load (actually require) the config file if it exists.
  # This might emit warnings if there's some error while loading it.
  #
  # @api public
  def require_config
    result = require(config_path) if File.exist?(config_path)
    Rib.say("Config loaded from: #{config_path}") if $VERBOSE && result
    result
  rescue StandardError, LoadError, SyntaxError => e
    Rib.warn("Error loading #{config_path}\n" \
             "  #{Rib::API.format_error(e)}")
  end

  # The config path where Rib tries to load upon Rib.shell.
  # It is depending on where Rib.home was discovered if
  # no specific config path was specified via -c or --config command
  #
  # @api public
  def config_path
    @config_path ||= File.join(home, 'config.rb')
  end

  def config_path= new_path
    @config_path = new_path
  end

  # Say (print to $stdout, with colors in the future, maybe)
  # something by the name of Rib.
  #
  # @api public
  # @param words [Array[String]] Words you want to say.
  def say *words
    $stdout.puts(Rib.prepare(words))
  end

  # Warn (print to $stderr, with colors in the future, maybe)
  # something by the name of Rib.
  #
  # @api public
  # @param words [Array[String]] Words you want to warn.
  def warn *words
    $stderr.puts(Rib.prepare(words))
  end

  # Warn (print to $stderr, with colors in the future, maybe)
  # something by the name of Rib and then exit(1).
  #
  # @api public
  # @param words [Array[String]] Words you want to warn before aborting.
  def abort *words
    warn(words)
    exit(1)
  end

  def silence
    w, v = $-w, $VERBOSE
    $-w, $VERBOSE = false, false
    yield
  ensure
    $-w, $VERBOSE = w, v
  end

  private
  def self.prepare words
    name = config[:name]
    "#{name}: #{words.join("\n#{' '*(name.size+2)}")}"
  end
end


================================================
FILE: rib.gemspec
================================================
# -*- encoding: utf-8 -*-
# stub: rib 1.6.3 ruby lib

Gem::Specification.new do |s|
  s.name = "rib".freeze
  s.version = "1.6.3".freeze

  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
  s.require_paths = ["lib".freeze]
  s.authors = ["Lin Jen-Shin (godfat)".freeze]
  s.date = "2026-01-20"
  s.description = "Ruby-Interactive-ruBy -- Yet another interactive Ruby shell\n\nRib is based on the design of [ripl][] and the work of [ripl-rc][], some of\nthe features are also inspired by [pry][]. The aim of Rib is to be fully\nfeatured and yet very easy to opt-out or opt-in other features. It shall\nbe simple, lightweight and modular so that everyone could customize Rib.\n\n[ripl]: https://github.com/cldwalker/ripl\n[ripl-rc]: https://github.com/godfat/ripl-rc\n[pry]: https://github.com/pry/pry".freeze
  s.email = ["godfat (XD) godfat.org".freeze]
  s.executables = [
  "rib".freeze,
  "rib-all".freeze,
  "rib-auto".freeze,
  "rib-min".freeze,
  "rib-rack".freeze,
  "rib-rails".freeze]
  s.files = [
  ".gitignore".freeze,
  ".gitlab-ci.yml".freeze,
  ".gitmodules".freeze,
  "CHANGES.md".freeze,
  "Gemfile".freeze,
  "LICENSE".freeze,
  "README.md".freeze,
  "Rakefile".freeze,
  "TODO.md".freeze,
  "bin/rib".freeze,
  "bin/rib-all".freeze,
  "bin/rib-auto".freeze,
  "bin/rib-min".freeze,
  "bin/rib-rack".freeze,
  "bin/rib-rails".freeze,
  "lib/rib.rb".freeze,
  "lib/rib/all.rb".freeze,
  "lib/rib/api.rb".freeze,
  "lib/rib/app/auto.rb".freeze,
  "lib/rib/app/rack.rb".freeze,
  "lib/rib/app/rails.rb".freeze,
  "lib/rib/config.rb".freeze,
  "lib/rib/core.rb".freeze,
  "lib/rib/core/completion.rb".freeze,
  "lib/rib/core/history.rb".freeze,
  "lib/rib/core/last_value.rb".freeze,
  "lib/rib/core/multiline.rb".freeze,
  "lib/rib/core/readline.rb".freeze,
  "lib/rib/core/squeeze_history.rb".freeze,
  "lib/rib/core/strip_backtrace.rb".freeze,
  "lib/rib/debug.rb".freeze,
  "lib/rib/extra/autoindent.rb".freeze,
  "lib/rib/extra/byebug.rb".freeze,
  "lib/rib/extra/hirb.rb".freeze,
  "lib/rib/extra/paging.rb".freeze,
  "lib/rib/extra/spring.rb".freeze,
  "lib/rib/more.rb".freeze,
  "lib/rib/more/anchor.rb".freeze,
  "lib/rib/more/beep.rb".freeze,
  "lib/rib/more/bottomup_backtrace.rb".freeze,
  "lib/rib/more/caller.rb".freeze,
  "lib/rib/more/color.rb".freeze,
  "lib/rib/more/edit.rb".freeze,
  "lib/rib/more/multiline_history.rb".freeze,
  "lib/rib/more/multiline_history_file.rb".freeze,
  "lib/rib/plugin.rb".freeze,
  "lib/rib/runner.rb".freeze,
  "lib/rib/shell.rb".freeze,
  "lib/rib/test.rb".freeze,
  "lib/rib/test/history.rb".freeze,
  "lib/rib/test/multiline.rb".freeze,
  "lib/rib/version.rb".freeze,
  "rib.gemspec".freeze,
  "task/README.md".freeze,
  "task/gemgem.rb".freeze,
  "test/core/test_completion.rb".freeze,
  "test/core/test_history.rb".freeze,
  "test/core/test_last_value.rb".freeze,
  "test/core/test_multiline.rb".freeze,
  "test/core/test_readline.rb".freeze,
  "test/core/test_squeeze_history.rb".freeze,
  "test/core/test_strip_backtrace.rb".freeze,
  "test/extra/test_autoindent.rb".freeze,
  "test/more/test_anchor.rb".freeze,
  "test/more/test_beep.rb".freeze,
  "test/more/test_caller.rb".freeze,
  "test/more/test_color.rb".freeze,
  "test/more/test_multiline_history.rb".freeze,
  "test/test_api.rb".freeze,
  "test/test_plugin.rb".freeze,
  "test/test_runner.rb".freeze,
  "test/test_shell.rb".freeze]
  s.homepage = "https://github.com/godfat/rib".freeze
  s.licenses = ["Apache-2.0".freeze]
  s.rubygems_version = "4.0.4".freeze
  s.summary = "Ruby-Interactive-ruBy -- Yet another interactive Ruby shell".freeze
  s.test_files = [
  "test/core/test_completion.rb".freeze,
  "test/core/test_history.rb".freeze,
  "test/core/test_last_value.rb".freeze,
  "test/core/test_multiline.rb".freeze,
  "test/core/test_readline.rb".freeze,
  "test/core/test_squeeze_history.rb".freeze,
  "test/core/test_strip_backtrace.rb".freeze,
  "test/extra/test_autoindent.rb".freeze,
  "test/more/test_anchor.rb".freeze,
  "test/more/test_beep.rb".freeze,
  "test/more/test_caller.rb".freeze,
  "test/more/test_color.rb".freeze,
  "test/more/test_multiline_history.rb".freeze,
  "test/test_api.rb".freeze,
  "test/test_plugin.rb".freeze,
  "test/test_runner.rb".freeze,
  "test/test_shell.rb".freeze]
end


================================================
FILE: test/core/test_completion.rb
================================================

require 'rib/test'
require 'rib/core/completion'

describe Rib::Completion do
  paste :rib

  before do
    Rib::Completion.enable
  end

  would 'start bond' do
    new_shell do |sh|
      eval_binding = sh.method(:eval_binding).source_location

      mock(Bond).start(having(eval_binding: is_a(Proc))).peek_args do |*args|
        expect(args.first[:eval_binding].source_location).eq eval_binding

        args
      end
    end

    expect(Bond).started?
  end
end


================================================
FILE: test/core/test_history.rb
================================================

require 'rib/test'
require 'rib/test/history'
require 'rib/core/history'

describe Rib::History do
  paste :rib
  paste :setup_history

  test_for Rib::History do
    would '#after_loop save history' do
      inputs = %w[blih blah]
      shell.history.push(*inputs)

      shell.after_loop

      expect(File.read(history_file)).eq "#{inputs.join("\n")}\n"
    end

    would '#before_loop load previous history' do
      File.write(history_file, "check\nthe\nmike")

      shell.before_loop

      expect(shell.history.to_a).eq %w[check the mike]
    end

    would '#before_loop have empty history if no history file exists' do
      expect(shell.history.to_a).eq []
    end

    would '#read_history be accessible to plugins in #before_loop' do
      mod = Module.new do
        def read_history
          config[:history] = ['pong_read_history']
        end
      end
      klass = Rib::Shell.dup
      klass.use(mod)

      shell = klass.new.before_loop

      expect(shell.history).eq ['pong_read_history']
    end

    would '#write_history be accessible to plugins in #after_loop' do
      mod = Module.new do
        def write_history
          config[:history] = ['pong_write_history']
        end
      end
      klass = Rib::Shell.dup
      klass.use(mod)

      shell = klass.new.before_loop.after_loop

      expect(shell.history).eq ['pong_write_history']
    end
  end
end


================================================
FILE: test/core/test_last_value.rb
================================================

require 'rib/test'
require 'rib/core/last_value'

describe Rib::LastValue do
  paste :rib

  before do
    stub_output
    stub(Rib).shell{shell}
  end

  test_for Rib::LastValue do
    would 'set last_value' do
      mock(shell).get_input{'Rib.last_value'}
      mock(shell).get_input{'10**2'}
      mock(shell).get_input{'Rib.last_value'}

      expect(shell.loop_once).eq [nil, nil]

      shell.loop_once

      expect(shell.loop_once).eq [100, nil]
    end

    would 'set last_exception' do
      mock(shell).get_input{'XD'}
      mock(shell).get_input{'Rib.last_exception'}

      shell.loop_once

      expect(shell.loop_once.first).kind_of?(NameError)
    end
  end
end


================================================
FILE: test/core/test_multiline.rb
================================================

require 'rib/test'
require 'rib/test/multiline'
require 'rib/core/multiline'

describe Rib::Multiline do
  paste :rib
  paste :setup_multiline

  test_for Rib::Multiline do
    paste :multiline
  end
end


================================================
FILE: test/core/test_readline.rb
================================================

require 'rib/test'
require 'rib/core/readline'

describe Rib::Readline do
  paste :rib

  test_for Rib::Readline do
    would '#before_loop set @history' do
      expect(shell.history).eq Readline::HISTORY
    end

    would '#get_input calling Readline.readline' do
      mock(Readline).readline(shell.prompt, true){'ok'}

      expect(shell.get_input).eq 'ok'
    end
  end
end


================================================
FILE: test/core/test_squeeze_history.rb
================================================

require 'rib/test'
require 'rib/test/history'
require 'rib/core/squeeze_history'

describe Rib::SqueezeHistory do
  paste :rib
  paste :setup_history

  test_for Rib::History, Rib::SqueezeHistory do
    before do
      @input = %w[foo bar bar foo bar]
    end

    would 'after_loop saves squeezed history' do
      shell.history.push(*@input)
      shell.after_loop

      expect(File.read(history_file)).eq %w[foo bar foo bar].join("\n") + "\n"
    end

    would 'loop_once squeeze history' do
      stub_output
      stub(shell).get_input{ (shell.history << "'#{@input.shift}'").last }

      @input.size.times{ shell.loop_once }

      expect(shell.history.to_a).eq %w[foo bar foo bar].map{ |i| "'#{i}'" }
    end

    would 'be disabled if disabled' do
      Rib::SqueezeHistory.disable do
        stub_output
        stub(shell).get_input{ (shell.history << "'#{@input.shift}'").last }
        input = @input.dup

        @input.size.times{ shell.loop_once }

        expect(shell.history.to_a).eq input.map{ |i| "'#{i}'" }
      end
    end
  end
end


================================================
FILE: test/core/test_strip_backtrace.rb
================================================

require 'rib/test'
require 'rib/core/strip_backtrace'

describe Rib::StripBacktrace do
  would 'strip home' do
    backtrace = ["#{ENV['HOME']}/test", "/prefix/#{ENV['HOME']}/test"]

    expect(Rib::StripBacktrace.strip_home_backtrace(backtrace)).
      eq ['~/test', "/prefix/#{ENV['HOME']}/test"]
  end

  would 'strip current working directory' do
    backtrace = [File.expand_path(__FILE__)]

    expect(Rib::StripBacktrace.strip_cwd_backtrace(backtrace)).
      eq ['test/core/test_strip_backtrace.rb']
  end
end


================================================
FILE: test/extra/test_autoindent.rb
================================================

require 'rib/test'
require 'rib/extra/autoindent'

describe Rib::Autoindent do
  paste :rib

  autoindent = Class.new do
    include Rib::Autoindent, Rib::Multiline, Rib::API
    def config
      {:line => 0, :binding => TOPLEVEL_BINDING, :prompt => '>> '}
    end
    def stack_size
      autoindent_stack.size
    end
  end

  before do
    Rib::Multiline.enable
    Rib::Autoindent.enable
    @indent = autoindent.new

    mock(@indent).puts(matching(/^\e/)).times(0)

    expect(@indent.stack_size).eq 0
  end

  def ri input, size
    @indent.eval_input(input)

    expect(@indent.stack_size).eq size
  end

  def le input, size
    mock(@indent).puts(matching(/^\e/)){}

    @indent.eval_input(input)

    expect(@indent.stack_size).eq size
  end

  would 'begin rescue else ensure end' do
    ri('begin'         , 1)
    ri(  '1'           , 1)
    le('rescue'        , 1)
    ri(  '1'           , 1)
    le('rescue=>e'     , 1)
    le('rescue => e'   , 1)
    le('rescue =>e'    , 1)
    le('rescue E=>e '  , 1)
    le('rescue E'      , 1)
    le('rescue E => e ', 1)
    le('rescue E=> e'  , 1)
    le('rescue E =>e ' , 1)
    le('else'          , 1)
    ri(  '1'           , 1)
    le('ensure'        , 1)
    ri(  '1'           , 1)
    le('end while nil' , 0)
  end

  would 'def rescue else ensure end' do
    ri('def f a'       , 1)
    ri(  'if a'        , 2)
    le(  'end'         , 1)
    le('rescue'        , 1)
    ri(  '1'           , 1)
    le('rescue=>e'     , 1)
    le('rescue => e'   , 1)
    le('rescue =>e'    , 1)
    le('rescue E=>e '  , 1)
    le('rescue E'      , 1)
    le('rescue E => e ', 1)
    le('rescue E=> e'  , 1)
    le('rescue E =>e ' , 1)
    le('else'          , 1)
    ri(  '1'           , 1)
    le('ensure'        , 1)
    ri(  '1'           , 1)
    le('end while nil' , 0)
  end

  would 'if elsif else end' do
    ri('if true'       , 1)
    ri(  'if false'    , 2)
    ri(    '1'         , 2)
    le(  'end'         , 1)
    ri(  'if true'     , 2)
    le(  'elsif true'  , 2)
    ri(    '1'         , 2)
    le(  'else'        , 2)
    ri(    '1'         , 2)
    le(  'end'         , 1)
    ri(  'if 1'        , 2)
    ri(    'if 2'      , 3)
    le(    'end'       , 2)
    le(  'end'         , 1)
    le('end'           , 0)
  end

  would 'unless else end' do
    ri('unless 1'      , 1)
    ri(  'unless 1'    , 2)
    ri(    '1'         , 2)
    le(  'end '        , 1)
    le('else'          , 1)
    ri(  '1'           , 1)
    le('end'           , 0)
  end

  would 'case when else end' do
    ri('case 1'        , 1)
    le('when 1'        , 1)
    ri(  '1'           , 1)
    le('when 2'        , 1)
    ri('  if 1'        , 2)
    le('  end'         , 1)
    le('else'          , 1)
    ri(  '1'           , 1)
    le('end'           , 0)
  end

  would 'class Object end' do
    ri('class Object'  , 1)
    ri(  'if true'     , 2)
    le(  'end'         , 1)
    le('end'           , 0)
  end

  would 'module Rib end' do
    ri('module Rib'    , 1)
    ri(  'module_function', 1)
    ri(  'if true'     , 2)
    le(  'end'         , 1)
    le('end'           , 0)
  end

  would 'while end' do
    ri('while false'   , 1)
    ri(  'if true'     , 2)
    le(  'end'         , 1)
    le('end'           , 0)
  end

  would 'for end' do
    ri('for x in 1..2' , 1)
    ri(  'if true'     , 2)
    le(  'end'         , 1)
    le('end'           , 0)
  end

  would 'until end' do
    ri('until true'    , 1)
    ri(  'if true'     , 2)
    le(  'end'         , 1)
    le('end'           , 0)
  end

  would 'do end' do
    ri("to_s''do"      , 1)
    ri(  "to_s '' do"  , 2)
    le(  'end'         , 1)
    ri(  'to_s "" do'  , 2)
    le(  'end'         , 1)
    ri(  'to_s // do'  , 2)
    le(  'end'         , 1)
    le('end'           , 0)
  end

  would '{}' do
    ri('{'             , 1)
    ri(  ':a => :b'    , 1)
    le('}'             , 0)
  end

  would '[].each{}' do
    ri('[].each{'      , 1)
    ri(  '0'           , 1)
    ri(    '[].each {' , 2)
    le(    '}'         , 1)
    le('}'             , 0)
  end

  would '()' do
    ri('('             , 1)
    ri(  '0'           , 1)
    le(')'             , 0)
  end

  would '{}.dig()' do
    ri('{}.dig('       , 1)
    ri(  '0,'          , 1)
    ri(  '1'           , 1)
    le(')'             , 0)
  end

  would '[]' do
    ri('['             , 1)
    ri(  '0,'          , 1)
    ri(  '1,'          , 1)
    ri(  '['           , 2)
    ri(    '2'         , 2)
    le(  ']'           , 1)
    le(']'             , 0)
  end
end


================================================
FILE: test/more/test_anchor.rb
================================================

require 'rib/test'
require 'rib/more/anchor'
require 'rib/core/multiline'
require 'rib/test/multiline'

describe Rib::Anchor do
  paste :rib
  paste :setup_multiline

  before do
    Rib::Anchor.enable
  end

  describe '#anchor?' do
    would 'give true when anchoring' do
      stub(Rib).shell{shell}

      mock(shell).get_input do
        expect(shell).anchor?

        mock(shell).puts{}

        nil
      end

      Rib.anchor 'test'
    end

    would 'give false when not anchoring' do
      expect(new_shell).not.anchor?
    end
  end

  describe '.stop_anchors' do
    def anchor_deeper shell, index
      mock(shell).get_input do
        mock(shell).puts.times(0)

        expect(shell).anchor?
        expect(shell.loop_eval('self')).eq index

        mock_deeper(index + 1)
        'Rib.anchor self + 1'
      end
    end

    def escape shell
      mock(shell).get_input do
        'Rib.stop_anchors'
      end
    end

    def mock_deeper index
      mock(Rib).shell.times(2) # ignore first 2 calls, see Rib.anchor
      mock(Rib).shell.peek_return do |deeper_shell|
        if index < 5
          anchor_deeper(deeper_shell, index)
        else
          escape(deeper_shell)
        end

        deeper_shell
      end
    end

    would 'exit all anchors' do
      shell = Rib.shell

      mock(shell).get_input do
        mock_deeper(0)
        'Rib.anchor 0'
      end

      mock(shell).get_input{}
      mock(shell).puts{}

      shell.loop
    end
  end

  test_for Rib::Anchor, Rib::Multiline do
    paste :multiline
  end
end


================================================
FILE: test/more/test_beep.rb
================================================

require 'rib/test'
require 'rib/more/beep'

describe Rib::Beep do
  paste :rib

  before do
    Rib::Beep.enable
  end

  def verify delay, threshold=nil, &block
    shell(:started_at => Time.now - delay,
          :beep_threshold => threshold, &block)

    stub_output
    mock(shell).get_input{}

    shell.loop

    ok
  end

  def expect_beep sh
    mock(sh).print("\a"){}
  end

  def unexpect_beep sh
    stub(sh).print.with_any_args{ flunk }
  end

  describe 'beep' do
    would 'beep if loading too long' do
      verify(10, &method(:expect_beep))
    end

    would 'be configurable via beep_threshold' do
      verify(2, 1, &method(:expect_beep))
    end
  end

  describe 'not beep' do
    would 'not beep if not loading long' do
      verify(2, &method(:unexpect_beep))
    end

    would 'be configurable via beep_threshold' do
      verify(10, 15, &method(:unexpect_beep))
    end
  end
end


================================================
FILE: test/more/test_caller.rb
================================================

require 'rib/test'
require 'rib/more/caller'

describe Rib::Caller do
  paste :rib

  test_for Rib::Caller do
    would 'puts some backtrace' do
      mock(Rib.shell).puts(is_a(String)){ ok }

      Rib.caller
    end
  end
end


================================================
FILE: test/more/test_color.rb
================================================

require 'rib/test'
require 'rib/more/color'

describe Rib::Color do
  paste :rib

  before do
    Rib::Color.enable
  end

  color = Class.new do
    include Rib::Color
    def colors
      @colors ||= Rib::Shell.new.before_loop.config[:color]
    end

    def inspect_result result
      result.inspect
    end
  end.new

  would 'give correct color' do
    color.send(:format_color,
      [{0 => :a}, 'b', [nil, {false => Object}], {true => Exception.new}]).
        should.eq \
          "\e[34m[\e[0m\e[34m{\e[0m\e[31m0\e[0m\e[34m=>\e[0m\e[36m:a\e[0m\e" \
          "[34m}\e[0m\e[34m, \e[0m\e[32m\"b\"\e[0m\e[34m, \e[0m\e[34m[\e[0m" \
          "\e[35mnil\e[0m\e[34m, \e[0m\e[34m{\e[0m\e[35mfalse\e[0m\e[34m=>"  \
          "\e[0m\e[33mObject\e[0m\e[34m}\e[0m\e[34m]\e[0m\e[34m, \e[0m\e[34m"\
          "{\e[0m\e[35mtrue\e[0m\e[34m=>\e[0m\e[35m#<Exception: Exception>"  \
          "\e[0m\e[34m}\e[0m\e[34m]\e[0m"
  end

  would 'inspect recursive array and hash just like built-in inspect' do
    a = []
    a << a
    h = {}
    h[0] = h
    color.send(:format_color, [a, h]).should.eq \
      "\e[34m[\e[0m\e[34m[\e[0m\e[34m[...]\e[0m\e[34m]\e[0m\e[34m, \e[0m" \
      "\e[34m{\e[0m\e[31m0\e[0m\e[34m=>\e[0m\e[34m{...}\e[0m\e[34m}\e[0m" \
      "\e[34m]\e[0m"
  end

  # regression test
  would "colorize errors with `/' inside" do
    error = Class.new(Exception)

    begin
      line = __LINE__; raise error
    rescue error => e
      msg = "test/more/#{Rib::Color.yellow{'test_color.rb'}}:" \
            "#{Rib::Color.red{line}}:in #{Rib::Color.green}"
      Rib::Color.colorize_backtrace(e.backtrace).first.should =~ \
        Regexp.new(
          "#{Regexp.escape(msg)}(?:`|').+'#{Regexp.escape(Rib::Color.reset)}")
    end
  end

  would 'colorize warnings' do
    shell = new_shell

    shell.warn('test')

    expect(shell.warnings).eq ["\e[31mtest\e[0m"]
  end
end


================================================
FILE: test/more/test_multiline_history.rb
================================================

require 'rib/test'
require 'rib/test/multiline'
require 'rib/more/multiline_history'

describe Rib::MultilineHistory do
  paste :rib
  paste :setup_multiline

  def check str, err=nil
    shell.history.clear
    yield if block_given?
    with_history(str, err)

    @shell = nil
    stub_output

    shell.history.clear
    shell.history << 'old history'
    yield if block_given?
    with_history(str, err, 'old history')
  end

  def with_history str, err, *prefix
    lines = str.split("\n")
    lines[0...-1].inject([]){ |result, line|
      input(line)
      shell.loop_once
      result << line

      expect(shell.history.to_a).eq prefix + result

      result
    }
    input_done(lines.last, err)

    history = if lines.size == 1
                lines.first
              else
                "\n#{lines.join("\n")}"
              end

    expect(shell.history.to_a).eq prefix + [history]
  end

  test_for Rib::History, Rib::Multiline, Rib::MultilineHistory do
    paste :multiline
  end
end


================================================
FILE: test/test_api.rb
================================================

require 'rib/test'
require 'rib/shell'

describe Rib::API do
  paste :rib

  Rib::API.instance_methods.delete_if{ |e| e[/=$/] }.each do |meth|
    would "##{meth} be accessible to plugins" do
      mod = Module.new do
        define_method meth do
          "pong_#{meth}"
        end
      end
      klass = Rib::Shell.dup
      klass.use(mod)

      expect(klass.new.send(meth)).eq "pong_#{meth}"
    end
  end

  would 'emit a warning whenever result is not a string' do
    object = Class.new{ alias_method :inspect, :object_id }.new

    mock(shell).get_input{'object'}
    mock(shell).loop_eval('object'){object}
    mock(shell).puts("=> #{object.object_id}"){}
    mock($stderr).puts(including("#{object.class}#inspect")){}

    shell.loop_once

    ok
  end

  describe '#warn' do
    would 'append a warning message to warnings' do
      shell.warn('test')

      expect(shell.warnings).eq ['test']
    end
  end

  describe '#flush_warnings' do
    before do
      shell.warn('test')

      mock($stderr).puts('rib: test'){}
    end

    would 'warn to $stderr from #warnings' do
      shell.send(:flush_warnings)

      ok
    end
  end
end


================================================
FILE: test/test_plugin.rb
================================================

require 'rib/test'
require 'rib/all'

describe Rib::Plugin do
  paste :rib

  before do
    @names = Dir[File.expand_path(
               "#{File.dirname(__FILE__)}/../lib/rib/{core,more,zore}/*.rb")].
               map   {|path| File.basename(path)[0..-4]                     }
    @mods  = Rib.plugins
  end

  would 'have shortcut methods' do
    @names.each do |name|
      %w[enable disable].each do |meth|
        expect(Rib).respond_to?("#{meth}_#{name}")
      end

      %w[enabled? disabled?].each do |meth|
        expect(Rib).respond_to?("#{name}_#{meth}")
      end
    end
  end

  would 'be the same as mod methods' do
    @mods.shuffle.take(@mods.size/2).each(&:disable)

    @names.each do |name|
      %w[enabled? disabled?].each do |meth|
        expect(Rib.send("#{name}_#{meth}")).eq \
          @mods.find{ |mod|
            mod.name[/::\w+$/].tr(':', '') ==
            name.gsub(/([^_]+)/){$1.capitalize}.tr('_', '') }.
          send(meth)
      end
    end
  end

  would 'have backward compatibility for accessing Shell' do
    mock(Rib).warn(
      is_a(String), is_a(String), including("#{__FILE__}:47")){ok}

    Module.new.module_eval <<-RUBY, __FILE__, __LINE__ + 1
      extend Rib::Plugin
      Shell
    RUBY
  end
end


================================================
FILE: test/test_runner.rb
================================================

require 'rib/test'
require 'rib/runner'

describe Rib::Runner do
  paste :rib

  before do
    mock(Rib).shell{ shell }.times(2)
  end

  def input *args
    args.each{ |item| mock(shell).get_input{ item } }
    mock(shell).get_input{}
  end

  def output *args
    args.each{ |item| mock(shell).puts("=> #{item}"){} }
    mock(shell).puts{}
  end

  would '-e' do
     input('a')
    output('1')

    expect(Rib::Runner.run(%w[-ea=1])).eq shell
  end

  would '-e nothing' do
     input
    output

    expect(Rib::Runner.run(%w[-e])).eq shell
  end

  def verify_app_e argv
     input('a')
    output('1')
    conf = {:name => 'rib'}
    min  = 'rib-min'

    mock(Rib::Runner).which_bin(min){ min }
    mock(Rib::Runner).load(min){ Rib::Runner.run(argv) }
    stub(Rib).config{ conf }

    expect(Rib::Runner.run(argv)).eq shell
  end

  would 'min -e' do
    verify_app_e(%w[min -ea=1])
  end

  would '-e min' do
    verify_app_e(%w[-ea=1 min])
  end
end


================================================
FILE: test/test_shell.rb
================================================

require 'rib/test'
require 'rib/shell'

describe Rib::Shell do
  paste :rib

  describe '#loop' do
    def input str=Rib::Skip
      mock(shell).get_input{if block_given? then yield else str end}
      shell.loop
      ok
    end

    would 'exit'      do                              input('exit' ) end
    would 'also exit' do                              input(' exit') end
    would 'ctrl+d'    do mock(shell).puts{}         ; input(nil)     end
    would ':q'        do shell.config[:exit] << ':q'; input(':q')    end
    would '\q'        do shell.config[:exit] << '\q'; input('\q')    end

    would 'not puts anything if it is not running' do
      mock(shell).puts.times(0)

      shell.eval_binding.eval('self').instance_variable_set(:@shell, shell)

      input('@shell.stop; throw :rib_exit')
    end

    describe 'trap' do
      before do
        @token = Class.new(Exception)
        @old_trap = trap('INT'){ raise @token }
        mock(shell).handle_interrupt{ mock(shell).get_input{'exit'} }
      end

      after do
        trap('INT', &@old_trap)
      end

      def interrupt
        Process.kill('SIGINT', Process.pid)
        sleep
      end

      would 'fence and restore ctrl+c interruption' do
        input{ interrupt }

        expect.raise(@token){ interrupt }
      end
    end
  end

  describe '#loop_once' do
    def input str=nil
      if block_given?
        mock(shell).get_input{ yield }
      else
        mock(shell).get_input{ str }
      end

      shell.loop_once

      ok
    end

    would 'handles ctrl+c' do
      mock(shell).handle_interrupt{}

      input{ raise Interrupt }
    end

    would 'prints result' do
      mock(shell).puts('=> "mm"'){}

      input('"m" * 2')
    end

    %w[next break].each do |keyword|
      would "handle #{keyword}" do
        mock(shell).puts(matching(/^SyntaxError:/)){}

        input(keyword)
      end
    end

    would 'error in print_result' do
      mock(Rib).warn(matching(/Error while printing result.*BOOM/m)){}

      input('obj = Object.new; def obj.inspect; raise "BOOM"; end; obj')
    end

    would 'not crash if user input is a blackhole' do
      mock(Rib).warn(matching(/Error while printing result/)){}

      input('Rib::Blackhole')
    end

    would 'print error from eval' do
      mock(shell).puts(matching(/RuntimeError/)){}

      input('raise "blah"')
    end
  end

  describe '#prompt' do
    would 'be changeable' do
      shell.config[:prompt] = '> '

      expect(shell.prompt).eq  '> '
    end
  end

  describe '#eval_input' do
    before do
      @line = shell.config[:line]
    end

    would 'line' do
      shell.eval_input('10 ** 2')

      expect(shell.config[:line]).eq @line + 1
    end

    would 'print error and increments line' do
      result, err = shell.eval_input('{')

      expect(result).eq nil
      expect(err).kind_of?(SyntaxError)
      expect(shell.config[:line]).eq @line + 1
    end
  end

  describe '#running?' do
    would 'have complete flow' do
      expect(shell).not.running?

      mock(shell).get_input do
        expect(shell).running?

        mock(shell).puts{}

        nil
      end

      shell.loop

      expect(shell).not.running?
    end
  end

  describe '#stop' do
    would 'stop the loop if it is stopped' do
      mock(shell).get_input do
        expect(shell).running?

        shell.stop

        expect(shell).not.running?

        'Rib::Skip'
      end

      shell.loop
    end
  end

  would 'call after_loop even if in_loop raises' do
    mock(shell).loop_once{ raise 'boom' }
    mock(Rib).warn(is_a(String)){}
    mock(shell).after_loop{}

    expect.raise(RuntimeError) do
      shell.loop
    end
  end

  would 'have empty binding' do
    expect(shell(:binding => nil).eval_input('local_variables').first).empty?
  end

  would 'not pollute main' do
    expect(shell(:binding => nil).eval_input('main').first).eq 'rib'
  end

  would 'be main' do
    expect(shell(:binding => nil).eval_input('self.inspect').first).eq 'main'
  end

  would 'warn on removing main' do
    mock(TOPLEVEL_BINDING.eval('singleton_class')).method_defined?(:main) do
      true
    end

    mock(Rib).warn(is_a(String)){}

    expect(shell(:binding => nil).eval_input('main').first).eq 'rib'
  end
end
Download .txt
gitextract_3eo0hgho/

├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── CHANGES.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── TODO.md
├── asciicast.json
├── bin/
│   ├── rib
│   ├── rib-all
│   ├── rib-auto
│   ├── rib-min
│   ├── rib-rack
│   └── rib-rails
├── lib/
│   ├── rib/
│   │   ├── all.rb
│   │   ├── api.rb
│   │   ├── app/
│   │   │   ├── auto.rb
│   │   │   ├── rack.rb
│   │   │   └── rails.rb
│   │   ├── config.rb
│   │   ├── core/
│   │   │   ├── completion.rb
│   │   │   ├── history.rb
│   │   │   ├── last_value.rb
│   │   │   ├── multiline.rb
│   │   │   ├── readline.rb
│   │   │   ├── squeeze_history.rb
│   │   │   └── strip_backtrace.rb
│   │   ├── core.rb
│   │   ├── debug.rb
│   │   ├── extra/
│   │   │   ├── autoindent.rb
│   │   │   ├── byebug.rb
│   │   │   ├── hirb.rb
│   │   │   ├── paging.rb
│   │   │   └── spring.rb
│   │   ├── more/
│   │   │   ├── anchor.rb
│   │   │   ├── beep.rb
│   │   │   ├── bottomup_backtrace.rb
│   │   │   ├── caller.rb
│   │   │   ├── color.rb
│   │   │   ├── edit.rb
│   │   │   ├── multiline_history.rb
│   │   │   └── multiline_history_file.rb
│   │   ├── more.rb
│   │   ├── plugin.rb
│   │   ├── runner.rb
│   │   ├── shell.rb
│   │   ├── test/
│   │   │   ├── history.rb
│   │   │   └── multiline.rb
│   │   ├── test.rb
│   │   └── version.rb
│   └── rib.rb
├── rib.gemspec
└── test/
    ├── core/
    │   ├── test_completion.rb
    │   ├── test_history.rb
    │   ├── test_last_value.rb
    │   ├── test_multiline.rb
    │   ├── test_readline.rb
    │   ├── test_squeeze_history.rb
    │   └── test_strip_backtrace.rb
    ├── extra/
    │   └── test_autoindent.rb
    ├── more/
    │   ├── test_anchor.rb
    │   ├── test_beep.rb
    │   ├── test_caller.rb
    │   ├── test_color.rb
    │   └── test_multiline_history.rb
    ├── test_api.rb
    ├── test_plugin.rb
    ├── test_runner.rb
    └── test_shell.rb
Download .txt
SYMBOL INDEX (291 symbols across 40 files)

FILE: lib/rib.rb
  type Rib (line 6) | module Rib
    function config (line 14) | def config
    function shells (line 19) | def shells
    function vars (line 24) | def vars
    function home (line 34) | def home
    function shell (line 47) | def shell
    function plugins (line 58) | def plugins
    function disable_plugins (line 67) | def disable_plugins plugs=plugins
    function enable_plugins (line 76) | def enable_plugins plugs=plugins
    function require_config (line 84) | def require_config
    function config_path (line 98) | def config_path
    function config_path= (line 102) | def config_path= new_path
    function say (line 111) | def say *words
    function warn (line 120) | def warn *words
    function abort (line 129) | def abort *words
    function silence (line 134) | def silence
    function prepare (line 143) | def self.prepare words

FILE: lib/rib/api.rb
  type Rib (line 3) | module Rib; module API
    type API (line 3) | module API
      function before_loop (line 5) | def before_loop
      function after_loop (line 10) | def after_loop
      function handle_interrupt (line 15) | def handle_interrupt; puts                ; end
      function prompt (line 17) | def prompt       ; config[:prompt]        ; end
      function result_prompt (line 19) | def result_prompt; config[:result_prompt] ; end
      function name (line 21) | def name         ; config[:name]          ; end
      function eval_binding (line 23) | def eval_binding ; config[:binding]       ; end
      function line (line 25) | def line         ; config[:line]          ; end
      function started_at (line 27) | def started_at   ; config[:started_at]    ; end
      function in_loop (line 30) | def in_loop
      function loop_once (line 36) | def loop_once
      function get_input (line 58) | def get_input
      function eval_input (line 68) | def eval_input input
      function loop_eval (line 79) | def loop_eval input
      function puts (line 87) | def puts str=''
      function print_result (line 92) | def print_result result
      function print_eval_error (line 99) | def print_eval_error err
      function warn (line 105) | def warn message
      function format_result (line 110) | def format_result result
      function inspect_result (line 114) | def inspect_result result
      function format_error (line 122) | def format_error err
      function get_error (line 129) | def get_error err
      function format_backtrace (line 134) | def format_backtrace backtrace
      function equal_rib_skip (line 139) | def equal_rib_skip result
      function flush_warnings (line 145) | def flush_warnings

FILE: lib/rib/app/auto.rb
  type Rib (line 3) | module Rib; module Auto
    type Auto (line 3) | module Auto
      function load (line 5) | def load

FILE: lib/rib/app/rack.rb
  type Rib (line 3) | module Rib; module Rack
    type Rack (line 3) | module Rack
      function load (line 7) | def load
      function load_rack (line 13) | def load_rack
      function rack? (line 22) | def rack?
      function configru_path (line 26) | def configru_path

FILE: lib/rib/app/rails.rb
  type Rib (line 3) | module Rib; module Rails
    type Rails (line 3) | module Rails
      function load (line 5) | def load
      function load_rails (line 11) | def load_rails
      function load_rails2 (line 21) | def load_rails2
      function load_rails3 (line 40) | def load_rails3
      function optparse_env (line 51) | def optparse_env
      function optparse_rails (line 59) | def optparse_rails
      function rails? (line 108) | def rails?
      function path_for (line 113) | def path_for file

FILE: lib/rib/core/completion.rb
  type Rib (line 5) | module Rib; module Completion
    type Completion (line 5) | module Completion
      function before_loop (line 11) | def before_loop

FILE: lib/rib/core/history.rb
  type Rib (line 6) | module Rib; module History
    type History (line 6) | module History
      function before_loop (line 12) | def before_loop
      function after_loop (line 22) | def after_loop
      function get_input (line 29) | def get_input
      function history (line 37) | def history; config[:history] ||= []; end
      function read_history (line 40) | def read_history
      function write_history (line 47) | def write_history
      function history_file (line 56) | def history_file
      function history_file_path (line 60) | def history_file_path
      function history_size (line 64) | def history_size

FILE: lib/rib/core/last_value.rb
  type Rib (line 5) | module Rib; module LastValue
    type LastValue (line 5) | module LastValue
      function print_result (line 11) | def print_result result
      function print_eval_error (line 17) | def print_eval_error err
      type Imp (line 25) | module Imp
        function last_value (line 26) | def last_value
        function last_exception (line 30) | def last_exception

FILE: lib/rib/core/multiline.rb
  type Rib (line 6) | module Rib; module Multiline
    type Multiline (line 6) | module Multiline
      function loop_once (line 79) | def loop_once
      function loop_eval (line 89) | def loop_eval input
      function print_eval_error (line 99) | def print_eval_error err
      function prompt (line 108) | def prompt
      function handle_interrupt (line 118) | def handle_interrupt
      function multiline? (line 131) | def multiline? err
      function multiline_prompt (line 135) | def multiline_prompt
      function multiline_buffer (line 141) | def multiline_buffer

FILE: lib/rib/core/readline.rb
  type Rib (line 6) | module Rib; module Readline
    type Readline (line 6) | module Readline
      function before_loop (line 12) | def before_loop
      function get_input (line 18) | def get_input
    function last (line 25) | def (::Readline::HISTORY).last

FILE: lib/rib/core/squeeze_history.rb
  type Rib (line 5) | module Rib; module SqueezeHistory
    type SqueezeHistory (line 5) | module SqueezeHistory
      function loop_once (line 12) | def loop_once
      function write_history (line 28) | def write_history
      function squeezed_history (line 37) | def squeezed_history

FILE: lib/rib/core/strip_backtrace.rb
  type Rib (line 5) | module Rib; module StripBacktrace
    type StripBacktrace (line 5) | module StripBacktrace
      function format_error (line 11) | def format_error err
      function get_error (line 17) | def get_error err
      function format_backtrace (line 23) | def format_backtrace backtrace
      function strip_home_backtrace (line 30) | def strip_home_backtrace backtrace
      function strip_cwd_backtrace (line 34) | def strip_cwd_backtrace backtrace
      function strip_rib_backtrace (line 38) | def strip_rib_backtrace backtrace
      function replace_path_prefix (line 43) | def replace_path_prefix prefix, substitute, path

FILE: lib/rib/extra/autoindent.rb
  type Rib (line 7) | module Rib; module Autoindent
    type Autoindent (line 7) | module Autoindent
      function before_loop (line 71) | def before_loop
      function get_input (line 77) | def get_input
      function eval_input (line 94) | def eval_input raw_input
      function detect_autoindent (line 105) | def detect_autoindent input
      function handle_autoindent (line 120) | def handle_autoindent input, indent, err
      function handle_last_line (line 142) | def handle_last_line input,
      function current_autoindent (line 152) | def current_autoindent size=autoindent_stack.size
      function autoindent_spaces (line 156) | def autoindent_spaces
      function autoindent_stack (line 160) | def autoindent_stack

FILE: lib/rib/extra/byebug.rb
  type Rib (line 8) | module Rib; module Byebug
    type Byebug (line 8) | module Byebug
      function before_loop (line 12) | def before_loop
      type Imp (line 19) | module Imp
        function byebug (line 20) | def byebug
        function location (line 26) | def location
        function step (line 30) | def step times=1
        function next (line 34) | def next lines=1
        function finish (line 38) | def finish
  type Byebug (line 46) | module Byebug
    class RibProcessor (line 47) | class RibProcessor < CommandProcessor
      method start (line 48) | def self.start
      method at_line (line 56) | def at_line
      method at_return (line 60) | def at_return(_return_value)
      method at_end (line 64) | def at_end
      method at_breakpoint (line 68) | def at_breakpoint(breakpoint)
      method location (line 72) | def location
      method print_location (line 78) | def print_location
      method resume_rib (line 83) | def resume_rib
      method perform (line 99) | def perform action, args

FILE: lib/rib/extra/hirb.rb
  type Rib (line 5) | module Rib; module Hirb
    type Hirb (line 5) | module Hirb
      function format_result (line 11) | def format_result result

FILE: lib/rib/extra/paging.rb
  type Rib (line 5) | module Rib; module Paging
    type Paging (line 5) | module Paging
      function puts (line 12) | def puts str=''
      function one_screen? (line 23) | def one_screen? str
      function page_result (line 29) | def page_result str
      function pager (line 37) | def pager

FILE: lib/rib/extra/spring.rb
  type Spring (line 3) | module Spring
    type Commands (line 4) | module Commands
      class Rib (line 5) | class Rib
        method call (line 6) | def call

FILE: lib/rib/more/anchor.rb
  type Rib (line 5) | module Rib; module Anchor
    type Anchor (line 5) | module Anchor
      function prompt (line 11) | def prompt
      function anchor? (line 26) | def anchor?
      function prompt_anchor (line 33) | def prompt_anchor
      type Imp (line 42) | module Imp
        function anchor (line 55) | def anchor obj_or_binding, opts={}
        function stop_anchors (line 76) | def stop_anchors

FILE: lib/rib/more/beep.rb
  type Rib (line 5) | module Rib; module Beep
    type Beep (line 5) | module Beep
      function loop_once (line 11) | def loop_once
      function beep (line 19) | def beep
      function beep_threshold (line 23) | def beep_threshold

FILE: lib/rib/more/bottomup_backtrace.rb
  type Rib (line 5) | module Rib; module BottomupBacktrace
    type BottomupBacktrace (line 5) | module BottomupBacktrace
      function format_error (line 11) | def format_error err
      function format_backtrace (line 17) | def format_backtrace backtrace

FILE: lib/rib/more/caller.rb
  type Rib (line 5) | module Rib; module Caller
    type Caller (line 5) | module Caller
      type Imp (line 9) | module Imp
        function caller (line 10) | def caller *filters
        function display_backtrace (line 16) | def display_backtrace raw_backtrace, *filters

FILE: lib/rib/more/color.rb
  type Rib (line 5) | module Rib; module Color
    type Color (line 5) | module Color
      function before_loop (line 11) | def before_loop
      function format_result (line 16) | def format_result result
      function get_error (line 21) | def get_error err
      function warn (line 27) | def warn message
      function colors (line 34) | def colors
      function format_color (line 48) | def format_color result, display=inspect_result(result)
      function format_backtrace (line 80) | def format_backtrace backtrace
      function colorize_backtrace (line 87) | def colorize_backtrace backtrace
      function find_color (line 101) | def find_color colors, value
      function color (line 110) | def color rgb
      function black (line 114) | def   black &block; color(30, &block); end
      function red (line 115) | def     red &block; color(31, &block); end
      function green (line 116) | def   green &block; color(32, &block); end
      function yellow (line 117) | def  yellow &block; color(33, &block); end
      function blue (line 118) | def    blue &block; color(34, &block); end
      function magenta (line 119) | def magenta &block; color(35, &block); end
      function cyan (line 120) | def    cyan &block; color(36, &block); end
      function white (line 121) | def   white &block; color(37, &block); end
      function reset (line 122) | def   reset &block; color( 0, &block); end

FILE: lib/rib/more/edit.rb
  type Rib (line 6) | module Rib; module Edit
    type Edit (line 6) | module Edit
      type Imp (line 10) | module Imp
        function edit (line 11) | def edit
      function editor (line 34) | def editor

FILE: lib/rib/more/multiline_history.rb
  type Rib (line 6) | module Rib; module MultilineHistory
    type MultilineHistory (line 6) | module MultilineHistory
      function before_loop (line 12) | def before_loop
      function loop_eval (line 17) | def loop_eval input
      function handle_interrupt (line 25) | def handle_interrupt
      function handle_multiline (line 37) | def handle_multiline
      function multiline_trash (line 46) | def multiline_trash

FILE: lib/rib/more/multiline_history_file.rb
  type Rib (line 5) | module Rib; module MultilineHistoryFile
    type MultilineHistoryFile (line 5) | module MultilineHistoryFile
      function before_loop (line 11) | def before_loop
      function read_history (line 19) | def read_history
      function write_history (line 35) | def write_history
      function multiline_history_file_token (line 47) | def multiline_history_file_token

FILE: lib/rib/plugin.rb
  type Rib (line 3) | module Rib; module Plugin
    type Plugin (line 3) | module Plugin
      function enable (line 6) | def enable
      function disable (line 13) | def disable
      function enabled? (line 20) | def enabled?
      function disabled? (line 24) | def disabled?
      function const_missing (line 29) | def const_missing mod
      function extended (line 40) | def self.extended mod

FILE: lib/rib/runner.rb
  type Rib (line 5) | module Rib; module Runner
    type Runner (line 5) | module Runner
      function options (line 7) | def options
      function commands (line 35) | def commands
      function command_paths (line 43) | def command_paths
      function command_descriptions (line 53) | def command_descriptions
      function command_descriptions_find (line 63) | def command_descriptions_find path
      function run (line 69) | def run argv=ARGV
      function loop (line 82) | def loop retry_times=5
      function parse (line 100) | def parse argv
      function parse_next (line 152) | def parse_next argv, arg
      function help (line 156) | def help
      function load_command (line 171) | def load_command command
      function which_bin (line 185) | def which_bin bin # handle windows here

FILE: lib/rib/shell.rb
  type Rib (line 6) | module Rib; class Shell
    class Shell (line 6) | class Shell
      method use (line 9) | def self.use mod
      method initialize (line 38) | def initialize(config={})
      method loop (line 48) | def loop
      method start (line 63) | def start
      method stop (line 67) | def stop
      method running? (line 71) | def running?
      method warnings (line 75) | def warnings
      method set_trap (line 82) | def set_trap
      method release_trap (line 86) | def release_trap
      method new_private_binding (line 93) | def new_private_binding

FILE: lib/rib/test.rb
  function shell (line 19) | def shell opts={}
  function new_shell (line 23) | def new_shell opts={}
  function stub_output (line 33) | def stub_output
  function readline? (line 39) | def readline?
  function stub_readline (line 44) | def stub_readline meth=:stub
  function test_for (line 51) | def test_for *plugins, &block
  function test_level1 (line 77) | def test_level1 rest, block
  function test_level2 (line 89) | def test_level2 rest, block
  function test_level3 (line 101) | def test_level3 rest, block
  function main (line 121) | def main

FILE: lib/rib/test/history.rb
  function tempfile (line 19) | def tempfile
  function history_file (line 23) | def history_file

FILE: lib/rib/test/multiline.rb
  function setup_input (line 4) | def setup_input str
  function input (line 12) | def input str
  function input_done (line 17) | def input_done str, err=nil
  function check (line 28) | def check str, err=nil

FILE: lib/rib/version.rb
  type Rib (line 3) | module Rib

FILE: test/core/test_history.rb
  function read_history (line 34) | def read_history
  function write_history (line 48) | def write_history

FILE: test/extra/test_autoindent.rb
  function config (line 10) | def config
  function stack_size (line 13) | def stack_size
  function ri (line 28) | def ri input, size
  function le (line 34) | def le input, size

FILE: test/more/test_anchor.rb
  function anchor_deeper (line 36) | def anchor_deeper shell, index
  function escape (line 48) | def escape shell
  function mock_deeper (line 54) | def mock_deeper index

FILE: test/more/test_beep.rb
  function verify (line 12) | def verify delay, threshold=nil, &block
  function expect_beep (line 24) | def expect_beep sh
  function unexpect_beep (line 28) | def unexpect_beep sh

FILE: test/more/test_color.rb
  function colors (line 14) | def colors
  function inspect_result (line 18) | def inspect_result result

FILE: test/more/test_multiline_history.rb
  function check (line 10) | def check str, err=nil
  function with_history (line 24) | def with_history str, err, *prefix

FILE: test/test_runner.rb
  function input (line 12) | def input *args
  function output (line 17) | def output *args
  function verify_app_e (line 36) | def verify_app_e argv

FILE: test/test_shell.rb
  function input (line 9) | def input str=Rib::Skip
  function interrupt (line 40) | def interrupt
  function input (line 54) | def input str=nil
Condensed preview — 71 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (147K chars).
[
  {
    "path": ".gitignore",
    "chars": 17,
    "preview": "/pkg/\n/coverage/\n"
  },
  {
    "path": ".gitlab-ci.yml",
    "chars": 660,
    "preview": "\nstages:\n  - test\n\n.test:\n  stage: test\n  image: ruby:${RUBY_VERSION}-bullseye\n  variables:\n    GIT_DEPTH: \"1\"\n    GIT_S"
  },
  {
    "path": ".gitmodules",
    "chars": 76,
    "preview": "[submodule \"task\"]\n\tpath = task\n\turl = https://github.com/godfat/gemgem.git\n"
  },
  {
    "path": "CHANGES.md",
    "chars": 13410,
    "preview": "# CHANGES\n\n## Rib 1.6.2 -- 2026-01-20\n\n### Bugs fixed\n\n* [core/strip_backtrace] Now it works with backtrace quotes chang"
  },
  {
    "path": "Gemfile",
    "chars": 244,
    "preview": "\nsource 'https://rubygems.org'\n\ngemspec\n\ngem 'rake'\ngem 'pork'\ngem 'muack'\n\ngem 'bond'\ngem 'hirb'\n\ngem 'simplecov', :req"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 14659,
    "preview": "# Rib [![Pipeline status](https://gitlab.com/godfat/rib/badges/master/pipeline.svg)](https://gitlab.com/godfat/rib/-/pip"
  },
  {
    "path": "Rakefile",
    "chars": 340,
    "preview": "\nbegin\n  require \"#{__dir__}/task/gemgem\"\nrescue LoadError\n  sh 'git submodule update --init --recursive'\n  exec Gem.rub"
  },
  {
    "path": "TODO.md",
    "chars": 613,
    "preview": "# TODO\n\n* cleanup the tests. it's so messy right now\n\n* Runner tests\n* Documentation\n* Implement exception_spy\n\n<https:/"
  },
  {
    "path": "asciicast.json",
    "chars": 8345,
    "preview": "{\n  \"version\": 1,\n  \"width\": 80,\n  \"height\": 24,\n  \"duration\": 31.5,\n  \"command\": null,\n  \"title\": \"rib\",\n  \"env\": {\n   "
  },
  {
    "path": "bin/rib",
    "chars": 94,
    "preview": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\nRib.config[:mimic_irb] = true\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "bin/rib-all",
    "chars": 82,
    "preview": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\nrequire 'rib/all'\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "bin/rib-auto",
    "chars": 375,
    "preview": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\n# create the shell before app to prvent your bundler (if any) kicks in\nRib.she"
  },
  {
    "path": "bin/rib-min",
    "chars": 95,
    "preview": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\nRib.config[:mimic_irb] = false\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "bin/rib-rack",
    "chars": 375,
    "preview": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\n# create the shell before app to prvent your bundler (if any) kicks in\nRib.she"
  },
  {
    "path": "bin/rib-rails",
    "chars": 377,
    "preview": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\n# create the shell before app to prvent your bundler (if any) kicks in\nRib.she"
  },
  {
    "path": "lib/rib/all.rb",
    "chars": 69,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/core'\nrequire 'rib/more'\n"
  },
  {
    "path": "lib/rib/api.rb",
    "chars": 3527,
    "preview": "# frozen_string_literal: true\n\nmodule Rib; module API\n  # Called before shell starts looping\n  def before_loop\n    self\n"
  },
  {
    "path": "lib/rib/app/auto.rb",
    "chars": 497,
    "preview": "# frozen_string_literal: true\n\nmodule Rib; module Auto\n  module_function\n  def load\n    app, name = %w[rails rack].find{"
  },
  {
    "path": "lib/rib/app/rack.rb",
    "chars": 643,
    "preview": "# frozen_string_literal: true\n\nmodule Rib; module Rack\n  singleton_class.module_eval{ attr_accessor :app }\n\n  module_fun"
  },
  {
    "path": "lib/rib/app/rails.rb",
    "chars": 3023,
    "preview": "# frozen_string_literal: true\n\nmodule Rib; module Rails\n  module_function\n  def load\n    load_rails\n  rescue LoadError ="
  },
  {
    "path": "lib/rib/config.rb",
    "chars": 64,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\nRib.require_config\n"
  },
  {
    "path": "lib/rib/core/completion.rb",
    "chars": 812,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Completion\n  extend Plugin\n  Shell.use(self)\n\n  # -----"
  },
  {
    "path": "lib/rib/core/history.rb",
    "chars": 1578,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\nrequire 'fileutils'\n\nmodule Rib; module History\n  extend Plugin\n  Shell.use"
  },
  {
    "path": "lib/rib/core/last_value.rb",
    "chars": 538,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module LastValue\n  extend Plugin\n  Shell.use(self)\n\n  attr_rea"
  },
  {
    "path": "lib/rib/core/multiline.rb",
    "chars": 4234,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\n# from https://github.com/janlelis/ripl-multi_line\nmodule Rib; module Mult"
  },
  {
    "path": "lib/rib/core/readline.rb",
    "chars": 501,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\nrequire 'readline'\n\nmodule Rib; module Readline\n  extend Plugin\n  Shell.use"
  },
  {
    "path": "lib/rib/core/squeeze_history.rb",
    "chars": 1024,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/core/history' # dependency\n\nmodule Rib; module SqueezeHistory\n  extend Plugi"
  },
  {
    "path": "lib/rib/core/strip_backtrace.rb",
    "chars": 1155,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module StripBacktrace\n  extend Plugin\n  Shell.use(self)\n\n  # -"
  },
  {
    "path": "lib/rib/core.rb",
    "chars": 347,
    "preview": "# frozen_string_literal: true\n\n# before session starts\nrequire 'rib/core/completion'\n\n# upon session ends\nrequire 'rib/c"
  },
  {
    "path": "lib/rib/debug.rb",
    "chars": 153,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/config'\nrequire 'rib/more/anchor'\nRib::Anchor.disable\nRib::Debugger.disable "
  },
  {
    "path": "lib/rib/extra/autoindent.rb",
    "chars": 4895,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/core/history'   # otherwise the order might be wrong\nrequire 'rib/core/readl"
  },
  {
    "path": "lib/rib/extra/byebug.rb",
    "chars": 1954,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/more/anchor'\nrequire 'byebug/core'\n\n# This is based on lib/byebug/processors"
  },
  {
    "path": "lib/rib/extra/hirb.rb",
    "chars": 614,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Hirb\n  extend Plugin\n  Shell.use(self)\n\n  # -----------"
  },
  {
    "path": "lib/rib/extra/paging.rb",
    "chars": 1323,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Paging\n  extend Plugin\n  Shell.use(self)\n\n  # ---------"
  },
  {
    "path": "lib/rib/extra/spring.rb",
    "chars": 195,
    "preview": "# frozen_string_literal: true\n\nmodule Spring\n  module Commands\n    class Rib\n      def call\n        load `which rib`.cho"
  },
  {
    "path": "lib/rib/more/anchor.rb",
    "chars": 2024,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Anchor\n  extend Plugin\n  Shell.use(self)\n\n  # ---------"
  },
  {
    "path": "lib/rib/more/beep.rb",
    "chars": 433,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Beep\n  extend Plugin\n  Shell.use(self)\n\n  # -----------"
  },
  {
    "path": "lib/rib/more/bottomup_backtrace.rb",
    "chars": 404,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module BottomupBacktrace\n  extend Plugin\n  Shell.use(self)\n\n  "
  },
  {
    "path": "lib/rib/more/caller.rb",
    "chars": 906,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Caller\n  extend Plugin\n  Shell.use(self)\n\n  module Imp\n"
  },
  {
    "path": "lib/rib/more/color.rb",
    "chars": 4055,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Color\n  extend Plugin\n  Shell.use(self)\n\n  # ----------"
  },
  {
    "path": "lib/rib/more/edit.rb",
    "chars": 666,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\nrequire 'tempfile'\n\nmodule Rib; module Edit\n  extend Plugin\n  Shell.use(sel"
  },
  {
    "path": "lib/rib/more/multiline_history.rb",
    "chars": 1026,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/core/history'   # dependency\nrequire 'rib/core/multiline' # dependency\n\nmodu"
  },
  {
    "path": "lib/rib/more/multiline_history_file.rb",
    "chars": 1204,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/more/multiline_history'\n\nmodule Rib; module MultilineHistoryFile\n  extend Pl"
  },
  {
    "path": "lib/rib/more.rb",
    "chars": 376,
    "preview": "# frozen_string_literal: true\n\n# upon session ends\nrequire 'rib/more/multiline_history_file'\n\n# upon formatting output\nr"
  },
  {
    "path": "lib/rib/plugin.rb",
    "chars": 1356,
    "preview": "# frozen_string_literal: true\n\nmodule Rib; module Plugin\n  attr_accessor :disabled\n\n  def enable\n    self.disabled = fal"
  },
  {
    "path": "lib/rib/runner.rb",
    "chars": 5806,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Runner\n  module_function\n  def options\n    @options ||="
  },
  {
    "path": "lib/rib/shell.rb",
    "chars": 2725,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/plugin'\nrequire 'rib/api'\n\nmodule Rib; class Shell\n  include API\n\n  def self"
  },
  {
    "path": "lib/rib/test/history.rb",
    "chars": 370,
    "preview": "# frozen_string_literal: true\n\nrequire 'tempfile'\n\ncopy :setup_history do\n  before do\n    if readline?\n      ::Readline:"
  },
  {
    "path": "lib/rib/test/multiline.rb",
    "chars": 3062,
    "preview": "# frozen_string_literal: true\n\ncopy :setup_multiline do\n  def setup_input str\n    if readline?\n      stub_readline(:mock"
  },
  {
    "path": "lib/rib/test.rb",
    "chars": 2573,
    "preview": "# frozen_string_literal: true\n\nrequire 'pork/auto'\nrequire 'muack'\n\nPork::Suite.include(Muack::API)\n\nrequire 'rib'\n\ncopy"
  },
  {
    "path": "lib/rib/version.rb",
    "chars": 66,
    "preview": "# frozen_string_literal: true\n\nmodule Rib\n  VERSION = '1.6.3'\nend\n"
  },
  {
    "path": "lib/rib.rb",
    "chars": 3927,
    "preview": "# frozen_string_literal: true\n\nrequire 'rib/shell'\nrequire 'rib/version'\n\nmodule Rib\n  Skip = Object.new\n\n  module_funct"
  },
  {
    "path": "rib.gemspec",
    "chars": 4312,
    "preview": "# -*- encoding: utf-8 -*-\n# stub: rib 1.6.3 ruby lib\n\nGem::Specification.new do |s|\n  s.name = \"rib\".freeze\n  s.version "
  },
  {
    "path": "test/core/test_completion.rb",
    "chars": 469,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/core/completion'\n\ndescribe Rib::Completion do\n  paste :rib\n\n  before do\n    Rib::Comple"
  },
  {
    "path": "test/core/test_history.rb",
    "chars": 1390,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/test/history'\nrequire 'rib/core/history'\n\ndescribe Rib::History do\n  paste :rib\n  paste"
  },
  {
    "path": "test/core/test_last_value.rb",
    "chars": 680,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/core/last_value'\n\ndescribe Rib::LastValue do\n  paste :rib\n\n  before do\n    stub_output\n"
  },
  {
    "path": "test/core/test_multiline.rb",
    "chars": 205,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/test/multiline'\nrequire 'rib/core/multiline'\n\ndescribe Rib::Multiline do\n  paste :rib\n "
  },
  {
    "path": "test/core/test_readline.rb",
    "chars": 381,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/core/readline'\n\ndescribe Rib::Readline do\n  paste :rib\n\n  test_for Rib::Readline do\n   "
  },
  {
    "path": "test/core/test_squeeze_history.rb",
    "chars": 1060,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/test/history'\nrequire 'rib/core/squeeze_history'\n\ndescribe Rib::SqueezeHistory do\n  pas"
  },
  {
    "path": "test/core/test_strip_backtrace.rb",
    "chars": 519,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/core/strip_backtrace'\n\ndescribe Rib::StripBacktrace do\n  would 'strip home' do\n    back"
  },
  {
    "path": "test/extra/test_autoindent.rb",
    "chars": 4561,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/extra/autoindent'\n\ndescribe Rib::Autoindent do\n  paste :rib\n\n  autoindent = Class.new d"
  },
  {
    "path": "test/more/test_anchor.rb",
    "chars": 1553,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/more/anchor'\nrequire 'rib/core/multiline'\nrequire 'rib/test/multiline'\n\ndescribe Rib::A"
  },
  {
    "path": "test/more/test_beep.rb",
    "chars": 907,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/more/beep'\n\ndescribe Rib::Beep do\n  paste :rib\n\n  before do\n    Rib::Beep.enable\n  end\n"
  },
  {
    "path": "test/more/test_caller.rb",
    "chars": 229,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/more/caller'\n\ndescribe Rib::Caller do\n  paste :rib\n\n  test_for Rib::Caller do\n    would"
  },
  {
    "path": "test/more/test_color.rb",
    "chars": 1886,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/more/color'\n\ndescribe Rib::Color do\n  paste :rib\n\n  before do\n    Rib::Color.enable\n  e"
  },
  {
    "path": "test/more/test_multiline_history.rb",
    "chars": 1004,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/test/multiline'\nrequire 'rib/more/multiline_history'\n\ndescribe Rib::MultilineHistory do"
  },
  {
    "path": "test/test_api.rb",
    "chars": 1153,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/shell'\n\ndescribe Rib::API do\n  paste :rib\n\n  Rib::API.instance_methods.delete_if{ |e| e"
  },
  {
    "path": "test/test_plugin.rb",
    "chars": 1256,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/all'\n\ndescribe Rib::Plugin do\n  paste :rib\n\n  before do\n    @names = Dir[File.expand_pa"
  },
  {
    "path": "test/test_runner.rb",
    "chars": 961,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/runner'\n\ndescribe Rib::Runner do\n  paste :rib\n\n  before do\n    mock(Rib).shell{ shell }"
  },
  {
    "path": "test/test_shell.rb",
    "chars": 4265,
    "preview": "\nrequire 'rib/test'\nrequire 'rib/shell'\n\ndescribe Rib::Shell do\n  paste :rib\n\n  describe '#loop' do\n    def input str=Ri"
  }
]

About this extraction

This page contains the full source code of the godfat/rib GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 71 files (132.8 KB), approximately 40.1k tokens, and a symbol index with 291 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!