Class: Environment

Inherits:
Object
  • 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

Constructor Details

#initializeEnvironment

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



22
23
24
25
26
27
28
29
30
# File 'lib/rash.rb', line 22

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_disabledObject (readonly)

Returns the value of attribute aliasing_disabled.



3
4
5
# File 'lib/rash.rb', line 3

def aliasing_disabled
  @aliasing_disabled
end

#promptObject (readonly)

Returns the value of attribute prompt.



2
3
4
# File 'lib/rash/prompt/irb.rb', line 2

def prompt
  @prompt
end

#umaskObject

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



18
19
20
# File 'lib/rash.rb', line 18

def add_path(path) 
  ENV["PATH"] += File::PATH_SEPARATOR + (path.respond_to?(:path) ? path.path : path.to_s)
end

#alias?(f) ⇒ Boolean

Returns:

  • (Boolean)


10
11
12
# File 'lib/rash/aliasing.rb', line 10

def alias?(f)
  @aliases.key?(f.to_sym)
end

#aliasesObject



14
15
16
# File 'lib/rash/aliasing.rb', line 14

def aliases
  @aliases.dup
end

#as_pipe_command(&block) ⇒ Object

Raises:

  • (IOError)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rash/pipeline.rb', line 18

def as_pipe_command(&block)
  raise IOError.new("pipelining not enabled") unless @in_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



37
38
39
40
41
42
43
44
# File 'lib/rash.rb', line 37

def as_superuser(&block)
  @superuser_mode = true
  begin
    block.call
  ensure
    @superuser_mode = false
  end
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

Raises:

  • (ArgumentError)


2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# File 'lib/rash/capturing.rb', line 2

def capture_block(&block)
  raise ArgumentError.new("no block provided") unless block_given?
  result = nil
  begin
    reader, writer = IO.pipe
    self.stdout = writer
    block.call
  ensure
    reset_stdout
    writer.close
    result = reader.read
    reader.close
  end
  result
end

#capture_command(m, *args) ⇒ Object

Raises:

  • (NameError)


18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rash/capturing.rb', line 18

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
# 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
  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

#dispatch(m, *args) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/rash.rb', line 59

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

#jobsObject



2
3
4
# File 'lib/rash/jobcontrol.rb', line 2

def jobs
  @active_jobs.keep_if {|pid| Process.kill(0, pid) rescue false}
end

#local_call(name, *args, &block) ⇒ Object



31
32
33
# File 'lib/rash/ext/filesystem.rb', line 31

def local_call(name, *args, &block)
  @working_directory.local_methods[name.to_sym].call(*args, &block)
end

#local_def(name, &block) ⇒ Object



19
20
21
# File 'lib/rash/ext/filesystem.rb', line 19

def local_def(name, &block)
  @working_directory.add_local_method(name.to_sym, &block)
end

#local_method?(name) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/rash/ext/filesystem.rb', line 27

def local_method?(name)
  @working_directory.local_methods.key?(name.to_sym)
end

#local_undef(name) ⇒ Object



23
24
25
# File 'lib/rash/ext/filesystem.rb', line 23

def local_undef(name)
  @working_directory.clear_local_method(name.to_sym)
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

Raises:

  • (IOError)


7
8
9
10
11
12
13
14
15
16
# File 'lib/rash/pipeline.rb', line 7

def make_pipeline(&block) 
  raise IOError.new("pipelining already enabled") if @in_pipeline
  start_pipeline
  begin
    block.call
  ensure
    end_pipeline
  end
  nil
end

#pipelined?Boolean

Returns:

  • (Boolean)


3
4
5
# File 'lib/rash/pipeline.rb', line 3

def pipelined?
  @in_pipeline
end

#reset_ioObject



3
4
5
6
7
# File 'lib/rash/redirection.rb', line 3

def reset_io
  reset_stdout
  reset_stderr
  reset_stdin
end

#reset_stderrObject



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_stdinObject



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_stdoutObject



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

#return_value_header=(prompt) ⇒ Object

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 return_value_header=(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

#use_irb_promptObject



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_aliasingObject



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



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rash.rb', line 46

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_aliasingObject



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