diff --git a/ruby/shell/builtins.rb b/ruby/shell/builtins.rb index 1259d57..2feb094 100644 --- a/ruby/shell/builtins.rb +++ b/ruby/shell/builtins.rb @@ -52,11 +52,16 @@ module Shell def builtin_cd(args) dir = args.first - if dir.nil? - Dir.chdir Dir.home + oldpwd = Dir.pwd + target = if dir.nil? + Dir.home + elsif dir == "-" + ENV["OLDPWD"] || oldpwd else - Dir.chdir dir + dir end + Dir.chdir target + ENV["OLDPWD"] = oldpwd ENV["PWD"] = Dir.pwd 0 end diff --git a/ruby/shell/repl.rb b/ruby/shell/repl.rb index a0c0b40..c61ace6 100644 --- a/ruby/shell/repl.rb +++ b/ruby/shell/repl.rb @@ -51,8 +51,12 @@ module Shell logger.verbose "Processing command: #{line.inspect}" commands = parse_line(line) - result = nil - commands.each do |command| + result = 0 + commands.each do |entry| + command = entry[:command] + next if command.strip.empty? + next if entry[:op] == :and && result != 0 + args = word_expander.expand(command) program = args.shift logger.verbose "Parsed command: #{program} #{args.inspect}" @@ -79,13 +83,29 @@ module Shell commands = [] command = "".dup state = :unquoted - line.each_char do |c| + next_op = :always + i = 0 + while i < line.length + c = line[i] case state when :unquoted case c when ";" - commands << command + commands << {command: command, op: next_op} command = "".dup + next_op = :always + i += 1 + next + when "&" + if line[i + 1] == "&" + commands << {command: command, op: next_op} + command = "".dup + next_op = :and + i += 2 + next + else + command << c + end when "'" command << c state = :single_quoted @@ -124,8 +144,9 @@ module Shell else raise "Unknown state #{state}" end + i += 1 end - commands << command + commands << {command: command, op: next_op} commands end end diff --git a/ruby/test/shell_test.rb b/ruby/test/shell_test.rb index bd451ef..d53e56c 100644 --- a/ruby/test/shell_test.rb +++ b/ruby/test/shell_test.rb @@ -167,11 +167,11 @@ class ShellTest < Minitest::Test end def test_builtin_cd_dash - skip "cannot easily implement without sequencing with ; or &&" + assert_equal Dir.pwd, `#{A1_PATH} -c 'mkdir -p blah; cd blah; cd -; rm -rf blah; echo $PWD'`.strip end def test_builtin_cd_parent - skip "cannot easily implement without sequencing with ; or &&" + assert_equal Dir.pwd, `#{A1_PATH} -c 'mkdir -p blah; cd blah; cd ..; rm -rf blah; echo $PWD'`.strip end def test_builtin_pwd