Class: Environment
- Inherits:
-
Object
show all
- Defined in:
- lib/rash.rb,
lib/rash/aliasing.rb,
lib/rash/pipeline.rb,
lib/rash/capturing.rb,
lib/rash/jobcontrol.rb,
lib/rash/prompt/irb.rb,
lib/rash/redirection.rb,
lib/rash/ext/filesystem.rb
Defined Under Namespace
Classes: Directory, Pipeline
Constant Summary
collapse
- RASH_LOCAL_FILE =
".rashrc.local"
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#add_path(path) ⇒ Object
-
#alias?(f) ⇒ Boolean
-
#aliases ⇒ Object
-
#as_pipe_command(&block) ⇒ Object
-
#as_superuser(&block) ⇒ Object
-
#as_sync_pipe_command(&block) ⇒ Object
-
#async(&block) ⇒ Object
-
#capture_block(&block) ⇒ Object
-
#capture_command(m, *args) ⇒ Object
-
#chdir(dir = nil) ⇒ Object
-
#clear_alias(func) ⇒ Object
-
#continued_prompt=(prompt) ⇒ Object
-
#dirs ⇒ Object
-
#dispatch(m, *args) ⇒ Object
-
#indent_prompt=(prompt) ⇒ Object
-
#initialize ⇒ Environment
constructor
Has to be a better way of adding extensions and dynamically loading them.
-
#jobs ⇒ Object
-
#local_call(name, *args, &block) ⇒ Object
-
#local_def(name, locked: false, &block) ⇒ Object
-
#local_method?(name) ⇒ Boolean
-
#local_methods ⇒ Object
-
#local_undef(name) ⇒ Object
-
#local_var(name, v = nil, locked: false) ⇒ Object
-
#local_var?(name) ⇒ Boolean
-
#local_vars ⇒ Object
-
#make_alias(new_func, old_func) ⇒ Object
-
#make_pipeline(&block) ⇒ Object
-
#make_sync_pipeline(&block) ⇒ Object
-
#method_missing(m, *args, &block) ⇒ Object
-
#name?(v) ⇒ Boolean
-
#pipelined? ⇒ Boolean
-
#pop_dir ⇒ Object
-
#push_dir(dir = nil) ⇒ Object
Note that this works regardless of which version of chdir is used.
-
#reset_io ⇒ Object
-
#reset_stderr ⇒ Object
-
#reset_stdin ⇒ Object
-
#reset_stdout ⇒ Object
-
#return_value_header=(prompt) ⇒ Object
This method can only be run from .rashrc.
-
#standard_prompt=(prompt) ⇒ Object
-
#stderr=(file) ⇒ Object
-
#stdin=(file) ⇒ Object
-
#stdout=(file) ⇒ Object
-
#string_prompt=(prompt) ⇒ Object
-
#synced_pipeline? ⇒ Boolean
-
#use_irb_prompt ⇒ Object
-
#with_aliasing ⇒ Object
-
#with_limits(limits, &block) ⇒ Object
-
#without_aliasing ⇒ Object
Constructor Details
Has to be a better way of adding extensions and dynamically loading them
6
7
8
|
# File 'lib/rash/ext/filesystem.rb', line 6
def initialize
common_init
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(m, *args, &block) ⇒ Object
37
38
39
40
41
42
43
44
45
|
# File 'lib/rash.rb', line 37
def method_missing(m, *args, &block)
if args.length == 0 && !block_given?
ENV[m.to_s.upcase]
elsif m.to_s[-1] == "=" && args.length == 1 && !block_given?
ENV[m.to_s.upcase.delete_suffix("=")] = args[0].to_s
else
super
end
end
|
Instance Attribute Details
#aliasing_disabled ⇒ Object
Returns the value of attribute aliasing_disabled.
3
4
5
|
# File 'lib/rash.rb', line 3
def aliasing_disabled
@aliasing_disabled
end
|
#prompt ⇒ Object
Returns the value of attribute prompt.
2
3
4
|
# File 'lib/rash/prompt/irb.rb', line 2
def prompt
@prompt
end
|
#umask ⇒ Object
Returns the value of attribute umask.
4
5
6
|
# File 'lib/rash.rb', line 4
def umask
@umask
end
|
Instance Method Details
#add_path(path) ⇒ Object
33
34
35
|
# File 'lib/rash.rb', line 33
def add_path(path)
ENV["PATH"] += File::PATH_SEPARATOR + (path.respond_to?(:path) ? path.path : path.to_s)
end
|
#alias?(f) ⇒ Boolean
10
11
12
|
# File 'lib/rash/aliasing.rb', line 10
def alias?(f)
@aliases.key?(f.to_sym)
end
|
#aliases ⇒ Object
14
15
16
|
# File 'lib/rash/aliasing.rb', line 14
def aliases
@aliases.dup
end
|
#as_pipe_command(&block) ⇒ Object
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
# File 'lib/rash/pipeline.rb', line 33
def as_pipe_command(&block)
raise IOError.new("pipelining not enabled") unless @in_pipeline
return as_sync_pipe_command(&block) if @synchronous_pipeline
input = (@active_pipelines.empty? ? $stdin : @active_pipelines.last.reader)
@active_pipelines << Pipeline.new
output = @active_pipelines.last.writer
error = ($stderr == $stdout ? output : $stderr)
pid = fork do
@in_pipeline = false
$stdin = input
$stdout = output
$stderr = error
block.call
output.close
exit!(true)
end
output.close
@active_pipelines.last.link_process(pid)
nil
end
|
#as_superuser(&block) ⇒ Object
52
53
54
55
56
57
58
59
|
# File 'lib/rash.rb', line 52
def as_superuser(&block)
@superuser_mode = true
begin
block.call
ensure
@superuser_mode = false
end
end
|
#as_sync_pipe_command(&block) ⇒ Object
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
# File 'lib/rash/pipeline.rb', line 57
def as_sync_pipe_command(&block)
raise IOError.new("pipelining not enabled") unless @in_pipeline
raise IOError.new("pipeline is not synchronous") unless @synchronous_pipeline
@next_pipe.close
@next_pipe = Pipeline.new
@prev_pipe.writer.close
input = (@first_sync_command ? $stdin : @prev_pipe.reader)
@first_sync_command = false
output = @next_pipe.writer
error = ($stderr == $stdout ? @next_pipe.writer : $stdin)
pid = fork do
@in_pipeline = false
@synchronous_pipeline = false
$stdin = input
$stdout = output
$stderr = error
block.call
exit!(true)
end
Process.wait(pid)
@prev_pipe, @next_pipe = @next_pipe, @prev_pipe
nil
end
|
#async(&block) ⇒ Object
6
7
8
9
10
11
12
13
14
|
# File 'lib/rash/jobcontrol.rb', line 6
def async(&block)
pid = fork {
block.call
exit!(true)
}
@active_jobs << pid
Process.detach(pid)
pid
end
|
#capture_block(&block) ⇒ Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# File 'lib/rash/capturing.rb', line 2
def capture_block(&block)
raise ArgumentError.new("no block provided") unless block_given?
result = nil
old_pipeline = @in_pipeline
begin
reader, writer = IO.pipe
self.stdout = writer
@in_pipeline = false
block.call
ensure
@in_pipeline = old_pipeline
reset_stdout
writer.close
result = reader.read
reader.close
end
result
end
|
#capture_command(m, *args) ⇒ Object
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/rash/capturing.rb', line 21
def capture_command(m, *args)
raise NameError.new("no such command", m) unless which(m) || ($env.alias?(m) && !$env.aliasing_disabled)
result = nil
begin
reader, writer = IO.pipe
system_command(m, *args, out: writer)
ensure
writer.close
result = reader.read
reader.close
end
result
end
|
#chdir(dir = nil) ⇒ Object
10
11
12
13
14
15
16
17
|
# File 'lib/rash.rb', line 10
def chdir(dir = nil)
old = @working_directory
Dir.chdir(dir.nil? ? "~" : dir.to_s)
@working_directory = Dir.pwd
ENV["OLDPWD"] = old.to_s
ENV["PWD"] = Dir.pwd
Dir.pwd
end
|
#clear_alias(func) ⇒ Object
6
7
8
|
# File 'lib/rash/aliasing.rb', line 6
def clear_alias(func)
@aliases.delete(func.to_sym)
end
|
#continued_prompt=(prompt) ⇒ Object
41
42
43
44
45
46
47
48
49
50
51
52
|
# File 'lib/rash/prompt/irb.rb', line 41
def continued_prompt=(prompt)
@prompt[:prompt_c] = case prompt
when Proc
prompt
else
err_msg = "expecting stringable type or method that resolves to string"
raise ArgumentError.new(err_msg) unless prompt.respond_to?(:to_s)
lambda {prompt.to_s}
end
@prompt[:PROMPT_C] = "".tap {|s| def s.dup; $env.prompt[:prompt_c].call; end}
end
|
#dirs ⇒ Object
29
30
31
|
# File 'lib/rash.rb', line 29
def dirs
@directory_stack
end
|
#dispatch(m, *args) ⇒ Object
74
75
76
77
78
79
80
|
# File 'lib/rash.rb', line 74
def dispatch(m, *args)
if @in_pipeline
add_pipeline(m, *args)
else
system_command(m, *args)
end
end
|
#indent_prompt=(prompt) ⇒ Object
15
16
17
18
19
20
21
22
23
24
25
26
|
# File 'lib/rash/prompt/irb.rb', line 15
def indent_prompt=(prompt)
@prompt[:prompt_n] = case prompt
when Proc
prompt
else
err_msg = "expecting stringable type or method that resolves to string"
raise ArgumentError.new(err_msg) unless prompt.respond_to?(:to_s)
lambda {prompt.to_s}
end
@prompt[:PROMPT_N] = "".tap {|s| def s.dup; $env.prompt[:prompt_n].call; end}
end
|
#jobs ⇒ Object
2
3
4
|
# File 'lib/rash/jobcontrol.rb', line 2
def jobs
@active_jobs.keep_if{|pid| Process.kill(0, pid) rescue false}.dup
end
|
#local_call(name, *args, &block) ⇒ Object
37
38
39
|
# File 'lib/rash/ext/filesystem.rb', line 37
def local_call(name, *args, &block)
@working_directory.local_method(name).call(*args, &block)
end
|
#local_def(name, locked: false, &block) ⇒ Object
19
20
21
22
23
|
# File 'lib/rash/ext/filesystem.rb', line 19
def local_def(name, locked: false, &block)
@working_directory.add_local_method(name, &block)
@working_directory.lock_method(name) if locked
name.to_sym
end
|
#local_method?(name) ⇒ Boolean
29
30
31
|
# File 'lib/rash/ext/filesystem.rb', line 29
def local_method?(name)
@working_directory.local_method?(name)
end
|
#local_methods ⇒ Object
33
34
35
|
# File 'lib/rash/ext/filesystem.rb', line 33
def local_methods
@working_directory.local_methods
end
|
#local_undef(name) ⇒ Object
25
26
27
|
# File 'lib/rash/ext/filesystem.rb', line 25
def local_undef(name)
@working_directory.clear_local_method(name)
end
|
#local_var(name, v = nil, locked: false) ⇒ Object
41
42
43
44
45
46
47
48
49
50
51
|
# File 'lib/rash/ext/filesystem.rb', line 41
def local_var(name, v = nil, locked: false)
res = nil
if v.nil?
res = @working_directory.local_variable(name)
else
@working_directory.set_local_variable(name, v)
res = v
end
@working_directory.lock_variable(name) if locked
res
end
|
#local_var?(name) ⇒ Boolean
53
54
55
|
# File 'lib/rash/ext/filesystem.rb', line 53
def local_var?(name)
@working_directory.local_variable?(name)
end
|
#local_vars ⇒ Object
57
58
59
|
# File 'lib/rash/ext/filesystem.rb', line 57
def local_vars
@working_directory.local_variables
end
|
#make_alias(new_func, old_func) ⇒ Object
2
3
4
|
# File 'lib/rash/aliasing.rb', line 2
def make_alias(new_func, old_func)
@aliases[new_func.to_sym] = old_func.to_s.split(" ")
end
|
#make_pipeline(&block) ⇒ Object
11
12
13
14
15
16
17
18
19
20
|
# File 'lib/rash/pipeline.rb', line 11
def make_pipeline(&block)
raise IOError.new("pipelining already enabled") if @in_pipeline
start_pipeline
begin
block.call
ensure
end_pipeline
end
nil
end
|
#make_sync_pipeline(&block) ⇒ Object
22
23
24
25
26
27
28
29
30
31
|
# File 'lib/rash/pipeline.rb', line 22
def make_sync_pipeline(&block)
raise IOError.new("pipelining already enabled") if @in_pipeline
start_sync_pipeline
begin
block.call
ensure
end_sync_pipeline
end
nil
end
|
#name?(v) ⇒ Boolean
82
83
84
|
# File 'lib/rash.rb', line 82
def name?(v)
v.kind_of?(String) || v.kind_of?(Symbol)
end
|
#pipelined? ⇒ Boolean
3
4
5
|
# File 'lib/rash/pipeline.rb', line 3
def pipelined?
@in_pipeline
end
|
#pop_dir ⇒ Object
25
26
27
|
# File 'lib/rash.rb', line 25
def pop_dir
self.chdir(@directory_stack.pop) if @directory_stack.size > 0
end
|
#push_dir(dir = nil) ⇒ Object
Note that this works regardless of which version of chdir is used.
20
21
22
23
|
# File 'lib/rash.rb', line 20
def push_dir(dir = nil)
@directory_stack.push(Dir.pwd)
self.chdir(dir)
end
|
#reset_io ⇒ Object
3
4
5
6
7
|
# File 'lib/rash/redirection.rb', line 3
def reset_io
reset_stdout
reset_stderr
reset_stdin
end
|
#reset_stderr ⇒ Object
49
50
51
52
53
|
# File 'lib/rash/redirection.rb', line 49
def reset_stderr
$stderr.flush
$stderr.close unless standard_stream?($stderr)
$stderr = DEFAULT_IO[:err]
end
|
#reset_stdin ⇒ Object
69
70
71
72
|
# File 'lib/rash/redirection.rb', line 69
def reset_stdin
$stdin.close unless standard_stream>($stdin)
$stdin = DEFAULT_IO[:in]
end
|
#reset_stdout ⇒ Object
26
27
28
29
30
|
# File 'lib/rash/redirection.rb', line 26
def reset_stdout
$stdout.flush
$stdout.close unless standard_stream?($stdout)
$stdout = DEFAULT_IO[:out]
end
|
This method can only be run from .rashrc. Anywhere else and it will simply do nothing
55
56
57
|
# File 'lib/rash/prompt/irb.rb', line 55
def (prompt)
@prompt[:RETURN] = prompt
end
|
#standard_prompt=(prompt) ⇒ Object
3
4
5
6
7
8
9
10
11
12
13
|
# File 'lib/rash/prompt/irb.rb', line 3
def standard_prompt=(prompt)
@prompt[:prompt_i] = case prompt
when Proc
prompt
else
err_msg = "expecting stringable type or method that resolves to string"
raise ArgumentError.new(err_msg) unless prompt.respond_to?(:to_s)
lambda {prompt.to_s}
end
@prompt[:PROMPT_I] = "".tap {|s| def s.dup; $env.prompt[:prompt_i].call; end}
end
|
#stderr=(file) ⇒ Object
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# File 'lib/rash/redirection.rb', line 32
def stderr=(file)
$stderr.flush
old_stderr = $stderr
case file
when String
$stderr = File.new(file, "w")
when :out
$stderr = STDOUT
when :err
$stderr = STDERR
else
raise ArgumentError.new("not an output stream - #{file}") unless file.is_a?(IO)
$stderr = file
end
old_stderr.close unless standard_stream?(old_stderr)
end
|
#stdin=(file) ⇒ Object
55
56
57
58
59
60
61
62
63
64
65
66
67
|
# File 'lib/rash/redirection.rb', line 55
def stdin=(file)
old_stdin = $stdin
case file
when String
$stdin = File.new(file, "r")
when :in
$stdin = STDIN
else
raise ArgumentError.new("not an input stream - #{file}") unless file.is_a?(IO)
$stdin = file
end
old_stdin.close unless standard_stream?(old_stdin)
end
|
#stdout=(file) ⇒ Object
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# File 'lib/rash/redirection.rb', line 9
def stdout=(file)
$stdout.flush
old_stdout = $stdout
case file
when String
$stdout = File.new(file, "w")
when :out
$stdout = STDOUT
when :err
$stdout = STDERR
else
raise ArgumentError.new("not an output stream - #{file}") unless file.is_a?(IO)
$stdout = file
end
old_stdout.close unless standard_stream?(old_stdout)
end
|
#string_prompt=(prompt) ⇒ Object
28
29
30
31
32
33
34
35
36
37
38
39
|
# File 'lib/rash/prompt/irb.rb', line 28
def string_prompt=(prompt)
@prompt[:prompt_s] = case prompt
when Proc
prompt
else
err_msg = "expecting stringable type or method that resolves to string"
raise ArgumentError.new(err_msg) unless prompt.respond_to?(:to_s)
lambda {prompt.to_s}
end
@prompt[:PROMPT_S] = "".tap {|s| def s.dup; $env.prompt[:prompt_s].call; end}
end
|
#synced_pipeline? ⇒ Boolean
7
8
9
|
# File 'lib/rash/pipeline.rb', line 7
def synced_pipeline?
@in_pipeline && @synchronous_pipeline
end
|
#use_irb_prompt ⇒ Object
59
60
61
62
63
64
|
# File 'lib/rash/prompt/irb.rb', line 59
def use_irb_prompt
if $0 == "irb"
IRB.conf[:PROMPT][:RASH] = @prompt
IRB.conf[:PROMPT_MODE] = :RASH
end
end
|
#with_aliasing ⇒ Object
30
31
32
33
34
35
36
37
38
39
40
|
# File 'lib/rash/aliasing.rb', line 30
def with_aliasing
old_aliasing = @aliasing_disabled
@aliasing_disabled = false
if block_given?
begin
yield
ensure
@aliasing_disabled = old_aliasing
end
end
end
|
#with_limits(limits, &block) ⇒ Object
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'lib/rash.rb', line 61
def with_limits(limits, &block)
if block_given?
pid = fork do
limits.each {|resource, limit| Process.setrlimit(resource, *limit)}
block.call
exit!(true)
end
Process.wait(pid)
else
limits.each {|resource, limit| Process.setrlimit(resource, *limit)}
end
end
|
#without_aliasing ⇒ Object
18
19
20
21
22
23
24
25
26
27
28
|
# File 'lib/rash/aliasing.rb', line 18
def without_aliasing
old_aliasing = @aliasing_disabled
@aliasing_disabled = true
if block_given?
begin
yield
ensure
@aliasing_disabled = old_aliasing
end
end
end
|