Skip to content

Commit

Permalink
Introduce cd command (#971)
Browse files Browse the repository at this point in the history
It's essentially a combination of pushws and popws commands that are
easier to use.

Help message:

```
Usage: cd ([target]|..)

IRB uses a stack of workspaces to keep track of context(s), with `pushws` and `popws` commands to manipulate the stack.
The `cd` command is an attempt to simplify the operation and will be subject to change.

When given:
- an object, cd will use that object as the new context by pushing it onto the workspace stack.
- "..", cd will leave the current context by popping the top workspace off the stack.
- no arguments, cd will move to the top workspace on the stack by popping off all workspaces.

Examples:

  cd Foo
  cd Foo.new
  cd @ivar
  cd ..
  cd
```
  • Loading branch information
st0012 authored Jul 3, 2024
1 parent 00603d4 commit 4a0e0e8
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
51 changes: 51 additions & 0 deletions lib/irb/command/cd.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# frozen_string_literal: true

module IRB
module Command
class CD < Base
category "Workspace"
description "Move into the given object or leave the current context."

help_message(<<~HELP)
Usage: cd ([target]|..)
IRB uses a stack of workspaces to keep track of context(s), with `pushws` and `popws` commands to manipulate the stack.
The `cd` command is an attempt to simplify the operation and will be subject to change.
When given:
- an object, cd will use that object as the new context by pushing it onto the workspace stack.
- "..", cd will leave the current context by popping the top workspace off the stack.
- no arguments, cd will move to the top workspace on the stack by popping off all workspaces.
Examples:
cd Foo
cd Foo.new
cd @ivar
cd ..
cd
HELP

def execute(arg)
case arg
when ".."
irb_context.pop_workspace
when ""
# TODO: decide what workspace commands should be kept, and underlying APIs should look like,
# and perhaps add a new API to clear the workspace stack.
prev_workspace = irb_context.pop_workspace
while prev_workspace
prev_workspace = irb_context.pop_workspace
end
else
begin
obj = eval(arg, irb_context.workspace.binding)
irb_context.push_workspace(obj)
rescue StandardError => e
warn "Error: #{e}"
end
end
end
end
end
end
3 changes: 3 additions & 0 deletions lib/irb/default_commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require_relative "command/backtrace"
require_relative "command/break"
require_relative "command/catch"
require_relative "command/cd"
require_relative "command/chws"
require_relative "command/context"
require_relative "command/continue"
Expand Down Expand Up @@ -240,6 +241,8 @@ def load_command(command)
_register_with_aliases(:irb_disable_irb, Command::DisableIrb,
[:disable_irb, NO_OVERRIDE]
)

register(:cd, Command::CD)
end

ExtendCommand = Command
Expand Down
65 changes: 65 additions & 0 deletions test/irb/command/test_cd.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require "tempfile"
require_relative "../helper"

module TestIRB
class CDTest < IntegrationTestCase
def setup
super

write_ruby <<~'RUBY'
class Foo
class Bar
def bar
"this is bar"
end
end
def foo
"this is foo"
end
end
binding.irb
RUBY
end

def test_cd
out = run_ruby_file do
type "cd Foo"
type "ls"
type "cd Bar"
type "ls"
type "cd .."
type "exit"
end

assert_match(/irb\(Foo\):002>/, out)
assert_match(/Foo#methods: foo/, out)
assert_match(/irb\(Foo::Bar\):004>/, out)
assert_match(/Bar#methods: bar/, out)
assert_match(/irb\(Foo\):006>/, out)
end

def test_cd_moves_top_level_with_no_args
out = run_ruby_file do
type "cd Foo"
type "cd Bar"
type "cd"
type "exit"
end

assert_match(/irb\(Foo::Bar\):003>/, out)
assert_match(/irb\(main\):004>/, out)
end

def test_cd_with_error
out = run_ruby_file do
type "cd Baz"
type "exit"
end

assert_match(/Error: uninitialized constant Baz/, out)
assert_match(/irb\(main\):002>/, out) # the context should not change
end
end
end

0 comments on commit 4a0e0e8

Please sign in to comment.