Class: Rush::Shell
- Inherits:
-
Object
- Object
- Rush::Shell
- Defined in:
- lib/rush/shell.rb
Instance Attribute Summary collapse
-
#suppress_output ⇒ Object
Returns the value of attribute suppress_output.
Instance Method Summary collapse
- #complete_method(receiver, dot, partial_name, pre) ⇒ Object
-
#complete_path(possible_var, accessor, quote, partial_path, pre) ⇒ Object
:nodoc:.
- #complete_variable(partial_name, pre) ⇒ Object
-
#completion_proc ⇒ Object
Try to do tab completion on dir square brackets and slash accessors.
-
#execute(cmd) ⇒ Object
Run a single command.
-
#finish ⇒ Object
Save history to ~/.rush/history when the shell exists.
-
#initialize ⇒ Shell
constructor
Set up the user’s environment, including a pure binding into which env.rb and commands.rb are mixed.
-
#path_parts(input) ⇒ Object
:nodoc:.
-
#print_result(res) ⇒ Object
Nice printing of different return types, particularly Rush::SearchResults.
-
#run ⇒ Object
Run the interactive shell using readline.
Constructor Details
#initialize ⇒ Shell
Set up the user’s environment, including a pure binding into which env.rb and commands.rb are mixed.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/rush/shell.rb', line 9 def initialize root = Rush::Dir.new('/') home = Rush::Dir.new(ENV['HOME']) if ENV['HOME'] pwd = Rush::Dir.new(ENV['PWD']) if ENV['PWD'] @config = Rush::Config.new @config.load_history.each do |item| Readline::HISTORY.push(item) end Readline.basic_word_break_characters = "" Readline.completion_append_character = nil Readline.completion_proc = completion_proc @box = Rush::Box.new @pure_binding = @box.instance_eval "binding" $last_res = nil eval @config.load_env, @pure_binding commands = @config.load_commands Rush::Dir.class_eval commands Array.class_eval commands end |
Instance Attribute Details
#suppress_output ⇒ Object
Returns the value of attribute suppress_output.
6 7 8 |
# File 'lib/rush/shell.rb', line 6 def suppress_output @suppress_output end |
Instance Method Details
#complete_method(receiver, dot, partial_name, pre) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/rush/shell.rb', line 122 def complete_method(receiver, dot, partial_name, pre) path = eval("#{receiver}.full_path", @pure_binding) rescue nil box = eval("#{receiver}.box", @pure_binding) rescue nil if path and box (box[path].methods - Object.methods).select do |e| e.match(/^#{Regexp.escape(partial_name)}/) end.map do |e| (pre || '') + receiver + dot + e end end end |
#complete_path(possible_var, accessor, quote, partial_path, pre) ⇒ Object
:nodoc:
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/rush/shell.rb', line 134 def complete_path(possible_var, accessor, quote, partial_path, pre) # :nodoc: original_var, fixed_path = possible_var, '' if /^(.+\/)([^\/]*)$/ === partial_path fixed_path, partial_path = $~.captures possible_var += "['#{fixed_path}']" end full_path = eval("#{possible_var}.full_path", @pure_binding) rescue nil box = eval("#{possible_var}.box", @pure_binding) rescue nil if full_path and box Rush::Dir.new(full_path, box).entries.select do |e| e.name.match(/^#{Regexp.escape(partial_path)}/) end.map do |e| (pre || '') + original_var + accessor + quote + fixed_path + e.name + (e.dir? ? "/" : "") end end end |
#complete_variable(partial_name, pre) ⇒ Object
151 152 153 154 155 156 157 158 159 160 |
# File 'lib/rush/shell.rb', line 151 def complete_variable(partial_name, pre) lvars = eval('local_variables', @pure_binding) gvars = eval('global_variables', @pure_binding) ivars = eval('instance_variables', @pure_binding) (lvars + gvars + ivars).select do |e| e.match(/^#{Regexp.escape(partial_name)}/) end.map do |e| (pre || '') + e end end |
#completion_proc ⇒ Object
Try to do tab completion on dir square brackets and slash accessors.
Example:
dir[‘subd # presing tab here will produce dir[’subdir/ if subdir exists dir/‘subd # presing tab here will produce dir/’subdir/ if subdir exists
This isn’t that cool yet, because it can’t do multiple levels of subdirs. It does work remotely, though, which is pretty sweet.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/rush/shell.rb', line 171 def completion_proc proc do |input| receiver, accessor, *rest = path_parts(input) if receiver case accessor when /^[\[\/]$/ complete_path(receiver, accessor, *rest) when /^\.$/ complete_method(receiver, accessor, *rest) when nil complete_variable(receiver, *rest) end end end end |
#execute(cmd) ⇒ Object
Run a single command.
36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/rush/shell.rb', line 36 def execute(cmd) res = eval(cmd, @pure_binding) $last_res = res eval("_ = $last_res", @pure_binding) print_result res rescue Rush::Exception => e puts "Exception #{e.class} -> #{e.}" rescue ::Exception => e puts "Exception #{e.class} -> #{e.}" e.backtrace.each do |t| puts " #{::File.(t)}" end end |
#finish ⇒ Object
Save history to ~/.rush/history when the shell exists.
64 65 66 67 68 |
# File 'lib/rush/shell.rb', line 64 def finish @config.save_history(Readline::HISTORY.to_a) puts exit end |
#path_parts(input) ⇒ Object
:nodoc:
109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/rush/shell.rb', line 109 def path_parts(input) # :nodoc: case input when /((?:@{1,2}|\$|)\w+(?:\[[^\]]+\])*)([\[\/])(['"])([^\3]*)$/ $~.to_a.slice(1, 4).push($~.pre_match) when /((?:@{1,2}|\$|)\w+(?:\[[^\]]+\])*)(\.)(\w*)$/ $~.to_a.slice(1, 3).push($~.pre_match) when /((?:@{1,2}|\$|)\w+)$/ $~.to_a.slice(1, 1).push(nil).push($~.pre_match) else [ nil, nil, nil ] end end |
#print_result(res) ⇒ Object
Nice printing of different return types, particularly Rush::SearchResults.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/rush/shell.rb', line 71 def print_result(res) return if self.suppress_output if res.kind_of? String puts res elsif res.kind_of? Rush::SearchResults widest = res.entries.map { |k| k.full_path.length }.max res.entries_with_lines.each do |entry, lines| print entry.full_path print ' ' * (widest - entry.full_path.length + 2) print "=> " print res.colorize(lines.first.strip.head(30)) print "..." if lines.first.strip.length > 30 if lines.size > 1 print " (plus #{lines.size - 1} more matches)" end print "\n" end puts "#{res.entries.size} matching files with #{res.lines.size} matching lines" elsif res.respond_to? :each counts = {} res.each do |item| puts item counts[item.class] ||= 0 counts[item.class] += 1 end if counts == {} puts "=> (empty set)" else count_s = counts.map do |klass, count| "#{count} x #{klass}" end.join(', ') puts "=> #{count_s}" end else puts "=> #{res.inspect}" end end |
#run ⇒ Object
Run the interactive shell using readline.
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/rush/shell.rb', line 51 def run loop do cmd = Readline.readline('rush> ') finish if cmd.nil? or cmd == 'exit' next if cmd == "" Readline::HISTORY.push(cmd) execute(cmd) end end |