arsh 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+ ARSH_INSTALL_PATH=File.expand_path("../../",__FILE__)
3
+ require 'rb-readline'
4
+
5
+ Dir.glob("#{ARSH_INSTALL_PATH}/libs/*.rb").each { |mod| load(mod) }
6
+ trap('QUIT',"IGNORE")
7
+ trap('INT') do
8
+ begin
9
+ break
10
+ rescue
11
+ print "^C"
12
+ end
13
+ end
14
+ ## Set up some default variables
15
+ $ps1="(arsh)<% ENV['USER'] %>@<% Dir.pwd %>$ "
16
+ $ps2=">"
17
+
18
+ ## Setup readline's completion
19
+ Readline.completion_append_character = nil
20
+ Readline.completion_proc = lambda do |search|
21
+ # Complete files and directories
22
+ # Complete programs and files within the path.
23
+ files = []
24
+ case search
25
+ when ""
26
+ files = ArshCommands.search_current_directory(files,search)
27
+ files = ArshCommands.search_path(files)
28
+ else
29
+ files = ArshCommands.search_current_directory(files,search)
30
+ if files.select { |f| f =~ %r[^#{search}] }.empty?
31
+ files = ArshCommands.search_path(files)
32
+ end
33
+ end
34
+ # Complete builtin methods
35
+ ArshCommands.singleton_methods.each { |method| files << method if method =~ /^#{search}/ }
36
+ files.uniq
37
+ files = files.select { |f| f =~ %r[^#{search}] }
38
+ end
39
+
40
+ # Builtin commands
41
+
42
+ module ArshCommands
43
+ INTHIST = Array.new
44
+ def internal_history
45
+ @internal_history
46
+ end
47
+ def internal_history=(input)
48
+ @internal_history << input
49
+ end
50
+ # Exit with exit code.
51
+ def self.exit(code)
52
+ Kernel.exit(code.to_s.to_i)
53
+ end
54
+
55
+ # Determine if a file is included in the path.
56
+ def self.in_path?(cmd,parms)
57
+ ENV['PATH'].split(/:/).each do |path|
58
+ if File.exists?("#{path}/#{cmd}") && File.executable?("#{path}/#{cmd}")
59
+ system("#{path}/#{cmd} #{parms.join(" ")}")
60
+ return true
61
+ end
62
+ end
63
+ return false
64
+ end
65
+
66
+ def self.parseinput(input)
67
+ cmd = input.split(/\s/)[0]
68
+ parms = replacestring(input).split(/\s/)[1..-1]
69
+ if ArshCommands.respond_to? cmd
70
+ begin
71
+ ArshCommands.send(replacestring(cmd),parms)
72
+ rescue
73
+ puts "#{$!}"
74
+ end
75
+ # If (full path) file is executable..
76
+ elsif File.exists?(cmd) && File.executable?(cmd)
77
+ system("#{cmd} #{parms}")
78
+ # If file is in PATH
79
+ elsif ArshCommands.in_path?(cmd,parms) == false
80
+ # Try to run input as ruby code.
81
+ ArshCommands.ruby_eval(input)
82
+ end
83
+ end
84
+
85
+ def self.search_current_directory(files,search)
86
+ Dir["#{search.gsub(%r[^/],"")}*"].each { |f| files << f }
87
+
88
+ files.map! { |f| f.gsub(%r[#{Dir.pwd}/],"") }.map! { |f| File.directory?(f) ? f + "/" : f }
89
+
90
+ return files
91
+ end
92
+
93
+ def self.search_path(files)
94
+ ENV['PATH'].split(":").each do |path|
95
+ begin
96
+ Dir.entries(path).each do |prog|
97
+ files << prog if File.executable?("#{path}/#{prog}")
98
+ end
99
+ rescue Errno::ENOENT
100
+ next
101
+ end
102
+ end
103
+ return files
104
+ end
105
+ end
106
+
107
+ # Load Plugins
108
+ begin
109
+ Dir.glob("#{ARSH_INSTALL_PATH}/plugins/*.rb").each { |plugin| require plugin }
110
+ rescue
111
+ puts "Error loading plugin: #{$!}"
112
+ end
113
+ # Main Loop
114
+
115
+ # Load rbshrc's
116
+ ["/etc/arshrc","#{ENV['HOME']}/.arshrc"].each do |arshrc|
117
+ File.open(arshrc,"r").readlines.each do |line|
118
+ ArshCommands.parseinput(line) if line != ""
119
+ end if File.exist?(arshrc)
120
+ end
121
+
122
+ while true
123
+
124
+ # Get input
125
+ begin
126
+ prompt = ArshCommands.rubyeval_indent == 0 ? $ps1 : "#{$ps2 * ArshCommands.rubyeval_indent} "
127
+ input = Readline::readline(ArshCommands.replacestring(prompt)).to_s.strip
128
+ rescue
129
+ puts ""
130
+ input = ""
131
+ end
132
+ next if input == "" # don't error on blank input
133
+ #begin puts input.gsub(/\#\{*\}/,'\1') rescue puts "#{$!}" end
134
+ Readline::HISTORY.push("#{input}") # Add command to history
135
+ ArshCommands::INTHIST.push("[#{Time.now.strftime("%a %b %d %H:%M:%S")}] #{input}")
136
+ # If command is builtin to shell...
137
+ ArshCommands.parseinput(input)
138
+ end
@@ -0,0 +1,21 @@
1
+ module ArshCommands
2
+ def self.alias(args)
3
+ args = args.join(" ")
4
+ alias_cmd, alias_body = args.split(/=/,2)
5
+ alias_body_cmd, alias_body_params = alias_body.split(/ /,2)
6
+ alias_cmd.strip!
7
+ alias_body_cmd.strip!
8
+ if alias_body_params != nil then
9
+ alias_body_params.strip
10
+ else
11
+ alias_body_params = ""
12
+ end
13
+ new_alias =<<-EOS
14
+ def self.#{alias_cmd}(args=[])
15
+ args = ["#{alias_body_params} "] + args
16
+ system("#{alias_body_cmd} \#{args.join(' ')}")
17
+ end
18
+ EOS
19
+ ArshCommands.module_eval(new_alias)
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module ArshCommands
2
+ # Change directory
3
+ def self.cd(dir)
4
+ dir = ["#{ENV['HOME']}"] if dir.nitems == 0
5
+ if File.directory?(File.expand_path(dir.join(" ")))
6
+ Dir.chdir(File.expand_path(dir.join(" ")))
7
+ elsif dir =~ /~/
8
+ dir.gsub("~","#{ENV['HOME']}")
9
+ else
10
+ puts "Invalid Directory #{dir.to_s}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/ruby
2
+ if ! String.respond_to?("each") then
3
+ class String
4
+ def each(splitter)
5
+ return self.split(splitter)
6
+ end
7
+ end
8
+ end
9
+
10
+ if ! Array.respond_to?("nitems") then
11
+ class Array
12
+ alias :nitems :count
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ module ArshCommands
2
+ def self.replacestring(string)
3
+ @rep_new_string = string
4
+ begin
5
+ repstring = /<%(.*?)%>/.match(@rep_new_string)
6
+ loop do
7
+ rep_original = repstring[0]
8
+ rep_new = eval(repstring[1]).to_s
9
+ @rep_new_string = @rep_new_string.gsub(rep_original,rep_new)
10
+ repstring = /<%(.*?)%>/.match(@rep_new_string)
11
+ break if repstring == nil
12
+ end if /<%(.*?)%>/.match(@rep_new_string) != nil
13
+ rescue
14
+ puts $!
15
+ @rep_new_string.gsub!(repstring[0],"[ERR]")
16
+ end
17
+ return @rep_new_string
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ # Evaluate ruby code typed into command line. Allow multiple lines of code before evaluting blcoks.
2
+ module ArshCommands
3
+ @rubyeval_proc = Proc.new {}
4
+ @rubyeval_indent = 0
5
+ @rubyeval_history = Array.new
6
+ def self.rubyeval_indent
7
+ return @rubyeval_indent
8
+ end
9
+ def self.ruby_eval(input)
10
+ # keywords that start a block
11
+ start_strings = ["class,","module","def","do","{","("]
12
+ # Keywords that end a block
13
+ end_strings = ["end","}",")"]
14
+ # Add last line typed to
15
+ @rubyeval_history << input
16
+ start_strings.each {|string| @rubyeval_indent += 1 if input.include? string}
17
+ end_strings.each {|string| @rubyeval_indent -=1 if input.include? string}
18
+ #input.strip.each(" ") {|string| @rubyeval_indent += 1 if start_strings.include? string }
19
+ #input.strip.each(" ") {|string| @rubyeval_indent -= 1 if end_strings.include? string }
20
+ if @rubyeval_indent <= 0
21
+ @rubyeval_indent = 0
22
+ begin
23
+ eval(@rubyeval_history.join("\n"),@rubyeval_proc.binding)
24
+ @rubyeval_history = Array.new
25
+ rescue ScriptError, StandardError
26
+ @rubyeval_history = Array.new
27
+ puts "#{$!}"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Arsh
2
+ VERSION = "1.0.1"
3
+ end
@@ -0,0 +1,5 @@
1
+ module ArshCommands
2
+ def self.history(args)
3
+ puts ArshCommands::INTHIST.find_all { |x| puts x }
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ # ls.rb v0.1.0
2
+ # ls.rb - A partial implentation of ls all written in ruby.
3
+ #
4
+ # This example shows how easy it is to create a plugin for arsh.
5
+
6
+ # The ArshCommands module holds all internal commands.
7
+ module ArshCommands
8
+ def self.lsa(args = "")
9
+ directories = Dir.entries("#{Dir.pwd}").sort
10
+ directories.delete_if { |x| x =~ /^\./ unless args.include?("-a") }
11
+ directories.map! { |x| "#{("0x"+File.stat(x).mode.to_s)} #{File.stat(x).uid} #{File.stat(x).gid} #{File.stat(x).mtime} #{x} "} if args.include?("-l")
12
+ return directories
13
+ end
14
+ def self.lsx(args) # Each command is a method.
15
+ puts self.lsa(args)
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arsh
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - James Paterni
9
+ - Brian Faga
10
+ - Eugene Howe
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2011-12-22 00:00:00.000000000Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rb-readline
18
+ requirement: &9188080 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *9188080
27
+ description: Provides a shell that can run pure Ruby code as well as ordinary linux
28
+ commands.
29
+ email:
30
+ - james@ruby-code.com
31
+ - eugene@xtreme-computers.net
32
+ executables:
33
+ - arsh
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - bin/arsh
38
+ - plugins/ls.rb
39
+ - plugins/history.rb
40
+ - libs/replacestring.rb
41
+ - libs/compat.rb
42
+ - libs/rubyeval.rb
43
+ - libs/cd.rb
44
+ - libs/alias.rb
45
+ - libs/version.rb
46
+ homepage: http://github.com/jamez01/arsh
47
+ licenses: []
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: 1.3.6
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 1.8.10
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Linux shell implemented in pure Ruby
70
+ test_files: []