Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 89 lines (68 sloc) 1.74 KB
#!/usr/bin/env ruby
require 'shellwords'
def main
loop do
$stdout.print ENV['PROMPT']
line = $stdin.gets
if line
line.strip!
else
exit
end
commands = split_on_pipes(line)
placeholder_in = $stdin
placeholder_out = $stdout
pipe = []
commands.each_with_index do |command, index|
program, *arguments = Shellwords.shellsplit(command)
if builtin?(program)
call_builtin(program, *arguments)
else
if index+1 < commands.size
pipe = IO.pipe
placeholder_out = pipe.last
else
placeholder_out = $stdout
end
spawn_program(program, *arguments, placeholder_out, placeholder_in)
placeholder_out.close unless placeholder_out == $stdout
placeholder_in.close unless placeholder_in == $stdin
placeholder_in = pipe.first
end
end
Process.waitall
end
end
def split_on_pipes(line)
line.scan( /([^"'|]+)|["']([^"']*)["']/ ).flatten.compact
end
def spawn_program(program, *arguments, placeholder_out, placeholder_in)
fork {
unless placeholder_out == $stdout
$stdout.reopen(placeholder_out)
placeholder_out.close
end
unless placeholder_in == $stdin
$stdin.reopen(placeholder_in)
placeholder_in.close
end
exec program, *arguments
}
end
def builtin?(program)
BUILTINS.has_key?(program)
end
def call_builtin(program, *arguments)
BUILTINS[program].call(*arguments)
end
BUILTINS = {
'cd' => lambda { |dir = ENV["HOME"]| Dir.chdir(dir) },
'exit' => lambda { |code = 0| exit(code.to_i) },
'exec' => lambda { |*command| exec *command },
'set' => lambda { |args|
key, value = args.split('=')
ENV[key] = value
}
}
ENV['PROMPT'] = '-> '
main