arsh 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/arsh +138 -0
- data/libs/alias.rb +21 -0
- data/libs/cd.rb +13 -0
- data/libs/compat.rb +14 -0
- data/libs/replacestring.rb +19 -0
- data/libs/rubyeval.rb +31 -0
- data/libs/version.rb +3 -0
- data/plugins/history.rb +5 -0
- data/plugins/ls.rb +17 -0
- metadata +70 -0
data/bin/arsh
ADDED
@@ -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
|
data/libs/alias.rb
ADDED
@@ -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
|
data/libs/cd.rb
ADDED
@@ -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
|
data/libs/compat.rb
ADDED
@@ -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
|
data/libs/rubyeval.rb
ADDED
@@ -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
|
data/libs/version.rb
ADDED
data/plugins/history.rb
ADDED
data/plugins/ls.rb
ADDED
@@ -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: []
|