require 'pry' require 'pastel' module Exa class ShellConfig attr_accessor :prompt end class ShellCommand def initialize(title:,args:) @title = title @args = args end def evaluate(shell) case @title when "ls" then if shell.pwd.children.any? shell.print_collection shell.pwd.children.map(&:name) else shell.print_warning "(no children of #{shell.pwd.path})" end when "cd" then target = Exa.expand(@args.first) if target && !target.empty? shell.change_directory target.first else shell.print_warning "Invalid path for cd: #{@args.first}" end when "mkdir" then target = Exa.recall(@args.first) when "pwd" then shell.print_info shell.pwd.path else shell.print_warning "Unknown command: '#@title'" end end def self.extract(string) tokens = string.split(' ') # p [ :extract, tokens: tokens ] cmd,*args = *tokens # p [ :extract, cmd: cmd, args: args ] new(title: cmd, args: args) end end class Shell attr_reader :pwd def initialize(pwd) @pwd = pwd end def configuration @config ||= ShellConfig.new end def kickstart! loop do print configuration.prompt.call(self) inp = gets.chomp outp = shell_eval(inp) p outp unless outp.nil? || (outp.respond_to?(:empty?) && outp.empty?) end end def shell_eval(cmd_str) cmd = ShellCommand.extract(cmd_str) cmd.evaluate(self) end def change_directory(target) @pwd = target end def print_collection(elements) puts elements.each do |element| puts " - " + pastel.blue(" #{element}") end puts end def print_warning(message) puts puts pastel.red(message) puts end def print_info(message) puts puts pastel.green(message) puts end def pastel @pastel ||= Pastel.new end def self.repl! shell = new(Exa['/']) yield shell.configuration shell.kickstart! end end end