Skip to content

Commit

Permalink
Implement 'cd -'
Browse files Browse the repository at this point in the history
  • Loading branch information
st0012 committed Jun 17, 2024
1 parent 4ac5305 commit 5c14c0e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 8 deletions.
26 changes: 18 additions & 8 deletions lib/irb/command/cd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,39 @@ class CD < Base
description "Move into the given object or leave the current context."

help_message(<<~HELP)
Usage: cd ([target]|..)
Usage: cd ([target]|..|-)
When given an object, cd will move into that object, making it the current context.
When given "..", cd will leave the current context, moving back to the previous context.
When given no arguments, cd will move back to the top-level (main object) context.
When given:
- an object, cd will move into that object, making it the current context.
- "..", cd will leave the current context, moving back to the previous context.
- "-", cd will toggle between the last 2 contexts. This does not work with other workspace commands.
- no arguments, cd will move back to the top-level (main object) context.
Examples:
cd Foo
cd Foo.new
cd @ivar
cd ..
cd -
cd
HELP

def execute(arg)
case arg
previous_workspace = irb_context.workspace

case arg.strip
when ".."
irb_context.pop_workspace
when "-"
irb_context.replace_workspace(irb_context.previous_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
popped_workspace = irb_context.pop_workspace
while popped_workspace
popped_workspace = irb_context.pop_workspace
end
else
begin
Expand All @@ -41,6 +49,8 @@ def execute(arg)
warn "Error: #{e}"
end
end

irb_context.previous_workspace = previous_workspace
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/irb/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ def initialize(irb, workspace = nil, input_method = nil)
else
@workspace_stack << WorkSpace.new
end
# for cd command's `-` argument
@previous_workspace = workspace
@thread = Thread.current

# copy of default configuration
Expand Down Expand Up @@ -241,6 +243,8 @@ def workspace
@workspace_stack.last
end

attr_accessor :previous_workspace

# Replace the current workspace with the given +workspace+.
def replace_workspace(workspace)
@workspace_stack.pop
Expand Down
38 changes: 38 additions & 0 deletions test/irb/command/test_cd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,44 @@ def test_cd
assert_match(/irb\(Foo\):006>/, out)
end

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

assert_match(/irb\(Foo::Bar\):003>/, out)
assert_match(/irb\(Foo\):004>/, out)
assert_match(/irb\(Foo::Bar\):005>/, out)
assert_match(/irb\(main\):006>/, out)
assert_match(/irb\(Foo::Bar\):007>/, out)
assert_match(/irb\(main\):008>/, out)

out = run_ruby_file do
type "cd -"
type "cd Foo"
type "cd -"
type "cd -"
type "cd Bar"
type "cd .."
type "cd -"
type "exit"
end

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

def test_cd_moves_top_level_with_no_args
out = run_ruby_file do
type "cd Foo"
Expand Down

0 comments on commit 5c14c0e

Please sign in to comment.