OSDN Git Service

change prefix to '/data/ruby'
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / lib / shell.rb
1 #
2 #   shell.rb - 
3 #       $Release Version: 0.7 $
4 #       $Revision: 1.9 $
5 #       by Keiju ISHITSUKA(keiju@ruby-lang.org)
6 #
7 # --
8 #
9 #   
10 #
11
12 require "e2mmap"
13
14 require "thread" unless defined?(Mutex)
15
16 require "forwardable"
17
18 require "shell/error"
19 require "shell/command-processor"
20 require "shell/process-controller"
21
22 class Shell
23   @RCS_ID='-$Id: shell.rb,v 1.9 2002/03/04 12:01:10 keiju Exp keiju $-'
24
25   include Error
26   extend Exception2MessageMapper
27
28 #  @cascade = true
29   # debug: true -> normal debug
30   # debug: 1    -> eval definition debug
31   # debug: 2    -> detail inspect debug
32   @debug = false
33   @verbose = true
34
35   @debug_display_process_id = false
36   @debug_display_thread_id = true
37   @debug_output_mutex = Mutex.new
38
39   class << Shell
40     extend Forwardable
41
42     attr_accessor :cascade, :debug, :verbose
43
44 #    alias cascade? cascade
45     alias debug? debug
46     alias verbose? verbose
47     @verbose = true
48
49     def debug=(val)
50       @debug = val
51       @verbose = val if val
52     end
53
54     def cd(path)
55       new(path)
56     end
57
58     def default_system_path
59       if @default_system_path
60         @default_system_path
61       else
62         ENV["PATH"].split(":")
63       end
64     end
65
66     def default_system_path=(path)
67       @default_system_path = path
68     end
69
70     def default_record_separator
71       if @default_record_separator
72         @default_record_separator
73       else
74         $/
75       end
76     end
77
78     def default_record_separator=(rs)
79       @default_record_separator = rs
80     end
81
82     # os resource mutex
83     mutex_methods = ["unlock", "lock", "locked?", "synchronize", "try_lock", "exclusive_unlock"]
84     for m in mutex_methods
85       def_delegator("@debug_output_mutex", m, "debug_output_"+m.to_s)
86     end
87
88   end
89
90   def initialize(pwd = Dir.pwd, umask = nil)
91     @cwd = File.expand_path(pwd)
92     @dir_stack = []
93     @umask = umask
94
95     @system_path = Shell.default_system_path
96     @record_separator = Shell.default_record_separator
97
98     @command_processor = CommandProcessor.new(self)
99     @process_controller = ProcessController.new(self)
100
101     @verbose = Shell.verbose
102     @debug = Shell.debug
103   end
104
105   attr_reader :system_path
106
107   def system_path=(path)
108     @system_path = path
109     rehash
110   end
111
112   attr_accessor :umask, :record_separator
113   attr_accessor :verbose, :debug
114
115   def debug=(val)
116     @debug = val
117     @verbose = val if val
118   end
119
120   alias verbose? verbose
121   alias debug? debug
122
123   attr_reader :command_processor
124   attr_reader :process_controller
125
126   def expand_path(path)
127     File.expand_path(path, @cwd)
128   end
129
130   # Most Shell commands are defined via CommandProcessor
131
132   #
133   # Dir related methods
134   #
135   # Shell#cwd/dir/getwd/pwd
136   # Shell#chdir/cd
137   # Shell#pushdir/pushd
138   # Shell#popdir/popd
139   # Shell#mkdir
140   # Shell#rmdir
141
142   attr_reader :cwd
143   alias dir cwd
144   alias getwd cwd
145   alias pwd cwd
146
147   attr_reader :dir_stack
148   alias dirs dir_stack
149
150   # If called as iterator, it restores the current directory when the
151   # block ends.
152   def chdir(path = nil, verbose = @verbose)
153     check_point
154
155     if iterator?
156       notify("chdir(with block) #{path}") if verbose
157       cwd_old = @cwd
158       begin
159         chdir(path, nil)
160         yield
161       ensure
162         chdir(cwd_old, nil)
163       end
164     else
165       notify("chdir #{path}") if verbose
166       path = "~" unless path
167       @cwd = expand_path(path)
168       notify "current dir: #{@cwd}"
169       rehash
170       Void.new(self)
171     end
172   end
173   alias cd chdir
174
175   def pushdir(path = nil, verbose = @verbose)
176     check_point
177
178     if iterator?
179       notify("pushdir(with block) #{path}") if verbose
180       pushdir(path, nil)
181       begin
182         yield
183       ensure
184         popdir
185       end
186     elsif path
187       notify("pushdir #{path}") if verbose
188       @dir_stack.push @cwd
189       chdir(path, nil)
190       notify "dir stack: [#{@dir_stack.join ', '}]"
191       self
192     else
193       notify("pushdir") if verbose
194       if pop = @dir_stack.pop
195         @dir_stack.push @cwd
196         chdir pop
197         notify "dir stack: [#{@dir_stack.join ', '}]"
198         self
199       else
200         Shell.Fail DirStackEmpty
201       end
202     end
203     Void.new(self)
204   end
205   alias pushd pushdir
206
207   def popdir
208     check_point
209
210     notify("popdir")
211     if pop = @dir_stack.pop
212       chdir pop
213       notify "dir stack: [#{@dir_stack.join ', '}]"
214       self
215     else
216       Shell.Fail DirStackEmpty
217     end
218     Void.new(self)
219   end
220   alias popd popdir
221
222   #
223   # process management
224   #
225   def jobs
226     @process_controller.jobs
227   end
228
229   def kill(sig, command)
230     @process_controller.kill_job(sig, command)
231   end
232
233   #
234   # command definitions
235   #
236   def Shell.def_system_command(command, path = command)
237     CommandProcessor.def_system_command(command, path)
238   end
239
240   def Shell.undef_system_command(command)
241     CommandProcessor.undef_system_command(command)
242   end
243
244   def Shell.alias_command(ali, command, *opts, &block)
245     CommandProcessor.alias_command(ali, command, *opts, &block)
246   end
247
248   def Shell.unalias_command(ali)
249     CommandProcessor.unalias_command(ali)
250   end
251
252   def Shell.install_system_commands(pre = "sys_")
253     CommandProcessor.install_system_commands(pre)
254   end
255
256   #
257   def inspect
258     if debug.kind_of?(Integer) && debug > 2
259       super
260     else
261       to_s
262     end
263   end
264
265   def self.notify(*opts, &block)
266     Shell::debug_output_synchronize do
267       if opts[-1].kind_of?(String)
268         yorn = verbose?
269       else
270         yorn = opts.pop
271       end
272       return unless yorn
273
274       if @debug_display_thread_id
275         if @debug_display_process_id
276           prefix = "shell(##{Process.pid}:#{Thread.current.to_s.sub("Thread", "Th")}): "
277         else
278           prefix = "shell(#{Thread.current.to_s.sub("Thread", "Th")}): "
279         end
280       else
281         prefix = "shell: "
282       end
283       _head = true
284       STDERR.print opts.collect{|mes|
285         mes = mes.dup
286         yield mes if iterator?
287         if _head
288           _head = false
289 #         "shell" " + mes
290           prefix + mes
291         else
292           " "* prefix.size + mes
293         end
294       }.join("\n")+"\n"
295     end
296   end
297
298   CommandProcessor.initialize
299   CommandProcessor.run_config
300 end