chitin 1.0.5 → 1.0.6
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/README +4 -0
- data/TODO +6 -1
- data/bin/chitin +5 -2
- data/lib/chitin/commands/builtins.rb +51 -3
- data/lib/chitin/commands/executable.rb +27 -6
- data/lib/chitin/commands/ruby.rb +25 -2
- data/lib/chitin/core_ext/array.rb +7 -0
- data/lib/chitin/core_ext/coolline.rb +10 -1
- data/lib/chitin/core_ext/kernel.rb +21 -0
- data/lib/chitin/file.rb +0 -17
- data/lib/chitin/manifests/manifest.rb +36 -0
- data/lib/chitin/session.rb +11 -5
- data/lib/chitin/version.rb +1 -1
- metadata +5 -2
data/README
CHANGED
data/TODO
CHANGED
@@ -12,6 +12,9 @@ FUTURE:
|
|
12
12
|
* tab complete ruby/shell things
|
13
13
|
* post_processing for shell commands
|
14
14
|
-> make it asynchronous and use pipes
|
15
|
+
* ability to 'neuter' a command, so that it won't automatically be run
|
16
|
+
-> i think i just did this in a commit (6/11/13)
|
17
|
+
* grep through history
|
15
18
|
|
16
19
|
QUIRKS:
|
17
20
|
* menu doesn't erase itself sometimes
|
@@ -19,9 +22,11 @@ QUIRKS:
|
|
19
22
|
* does not play nice with GDB if it is called within the bash profile file
|
20
23
|
|
21
24
|
FAILURES:
|
22
|
-
* ^C on running ruby programs kills the whole interpreter... womp.
|
23
25
|
* slashes in filenames
|
24
26
|
* `include Math; sin(5)` fails
|
27
|
+
* too many open pipes
|
28
|
+
-> don't close them in the first place
|
29
|
+
* unable to do "STDIN > ls > NULLOUT ^ NULLERR"
|
25
30
|
|
26
31
|
Questions:
|
27
32
|
* Why do you have to do @line = '' in Coolline in order to not affect the
|
data/bin/chitin
CHANGED
@@ -12,9 +12,12 @@ end
|
|
12
12
|
require File.join(File.dirname(follow_link(__FILE__)), "..", "lib", "chitin")
|
13
13
|
|
14
14
|
rc = ARGV[0] || File.expand_path('~/.chitinrc')
|
15
|
-
FileUtils.touch rc
|
16
15
|
|
17
|
-
Chitin::Builtins.class_eval File.read(rc)
|
16
|
+
Chitin::Builtins.class_eval File.read(rc) if rc
|
17
|
+
|
18
|
+
if rc && File.exists?(rc)
|
19
|
+
Chitin::Builtins.class_eval File.read(rc)
|
20
|
+
end
|
18
21
|
|
19
22
|
SESSION = Chitin::Session.new Chitin::Builtins
|
20
23
|
SESSION.start
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# Things are contained in modules or functions so that they play well with
|
2
2
|
# code folding.
|
3
|
+
# Picked up that trick from Sinatra
|
3
4
|
|
4
5
|
require 'etc'
|
5
6
|
ENV['USER'] ||= Etc.getlogin
|
@@ -47,7 +48,17 @@ module Chitin
|
|
47
48
|
|
48
49
|
# ruby's backtick doesn't chomp off the newline, which makes it more
|
49
50
|
# or less useless for piping into other commands
|
50
|
-
def `(args)
|
51
|
+
def `(*args)
|
52
|
+
res = eval args.join
|
53
|
+
|
54
|
+
if Runnable === res
|
55
|
+
composed = res | L {|str| str }
|
56
|
+
res = composed[:raw_run].chomp
|
57
|
+
composed[:wait]
|
58
|
+
end
|
59
|
+
|
60
|
+
res.to_s
|
61
|
+
end
|
51
62
|
|
52
63
|
# Place the last argument on the line
|
53
64
|
# This is a total hack. It would need proper parsing to accomodate for
|
@@ -109,6 +120,41 @@ module Chitin
|
|
109
120
|
def prompt
|
110
121
|
"#{ENV['USER']}: #{short_pwd} % "
|
111
122
|
end
|
123
|
+
|
124
|
+
# Get the elapsed time of the last command.
|
125
|
+
def last_elapsed
|
126
|
+
SESSION.last_elapsed || 0.0
|
127
|
+
end
|
128
|
+
|
129
|
+
def last_elapsed_formatted
|
130
|
+
hours = (last_elapsed / 3600).floor
|
131
|
+
min = ((last_elapsed - 3600 * hours) / 60).floor
|
132
|
+
sec = last_elapsed - 3600 * hours - 60 * min
|
133
|
+
|
134
|
+
if hours > 0
|
135
|
+
"%02d:%02d:%f" % [hours, min, sec]
|
136
|
+
elsif min > 0
|
137
|
+
"%02d:%f" % [min, sec]
|
138
|
+
else
|
139
|
+
"%f" % sec
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# My personal fancy shell.
|
144
|
+
# On the first line it has the time, elapsed time of the last
|
145
|
+
# run command, and the shortened working directory.
|
146
|
+
# On the second line, it has three colored dots.
|
147
|
+
def time_elapsed_working_multiline_prompt
|
148
|
+
"(".purple + Time.now.to_s + ") ".purple +
|
149
|
+
"(".purple + "last => " + "#{last_elapsed_formatted}".cyan + ") ".purple +
|
150
|
+
"(".purple + short_pwd.yellow + ")\n".purple +
|
151
|
+
'.'.red + '.'.yellow + '.'.cyan + ' '
|
152
|
+
end
|
153
|
+
|
154
|
+
# Minimalist.
|
155
|
+
def minimalist_prompt
|
156
|
+
'.'.red + '.'.yellow + '.'.cyan + ' '
|
157
|
+
end
|
112
158
|
end
|
113
159
|
include Prompts
|
114
160
|
|
@@ -141,14 +187,16 @@ module Chitin
|
|
141
187
|
end
|
142
188
|
end
|
143
189
|
|
144
|
-
# i know puts returns nil, but this is to
|
145
|
-
# the fact that we want it to return nil
|
190
|
+
# i know puts returns nil and p returns the object, but this is to
|
191
|
+
# emphasize the fact that we want it to return nil. also, so that
|
192
|
+
# we don't accidentally run a Runnable while inspecting it
|
146
193
|
nil
|
147
194
|
end
|
148
195
|
end
|
149
196
|
include Aliases
|
150
197
|
|
151
198
|
# Fixnum math is now floating-point math
|
199
|
+
# hashtag gitonmahlevel
|
152
200
|
class ::Fixnum
|
153
201
|
alias_method :old_div, :/
|
154
202
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Chitin
|
2
2
|
class Executable
|
3
|
+
# this is needed to work in tandem with #method_missing.
|
4
|
+
# this will sweep all inherited methods BUT #[] under the rug.
|
3
5
|
__sweep__ :[]
|
4
6
|
|
5
7
|
include Runnable
|
@@ -9,12 +11,17 @@ module Chitin
|
|
9
11
|
|
10
12
|
@path = path
|
11
13
|
@args = process_args(args)
|
14
|
+
@suspended = false
|
12
15
|
end
|
13
16
|
|
14
17
|
# EVERYTHING will be sent to the command. ERRTHANG!!!!
|
15
18
|
def method_missing(name, *arr, &blk)
|
16
|
-
|
17
|
-
|
19
|
+
if @suspended
|
20
|
+
super(name, *arr, &blk)
|
21
|
+
else
|
22
|
+
setup name.to_s, *process_args(arr)
|
23
|
+
self
|
24
|
+
end
|
18
25
|
end
|
19
26
|
|
20
27
|
private
|
@@ -39,9 +46,9 @@ module Chitin
|
|
39
46
|
end
|
40
47
|
else
|
41
48
|
# I'm leaving this here so that I know what went down in this
|
42
|
-
# battlefield. I tried automatically expanding globs, but
|
43
|
-
# in conjunction with * means things get expanded twice,
|
44
|
-
# in a lot of duplicates.
|
49
|
+
# battlefield. I tried automatically expanding FileObject globs, but
|
50
|
+
# that in conjunction with * means things get expanded twice,
|
51
|
+
# resulting in a lot of duplicates.
|
45
52
|
#
|
46
53
|
# Maybe an answer is to get rid of * and only do automatic expansion
|
47
54
|
# for executables.
|
@@ -137,6 +144,21 @@ module Chitin
|
|
137
144
|
end
|
138
145
|
end
|
139
146
|
|
147
|
+
# Make it so you can treat it like a normal object.
|
148
|
+
# This stops method forwarding
|
149
|
+
def suspend
|
150
|
+
@suspended_methods = private_methods.dup
|
151
|
+
@suspended_methods.each {|m| public m }
|
152
|
+
|
153
|
+
@suspended = true
|
154
|
+
end
|
155
|
+
|
156
|
+
def unsuspend
|
157
|
+
@suspended_methods.each {|m| private m }
|
158
|
+
@suspended_methods = []
|
159
|
+
@suspended = false
|
160
|
+
end
|
161
|
+
|
140
162
|
def inspect
|
141
163
|
"#<Chitin::Executable #{super}>"
|
142
164
|
end
|
@@ -146,7 +168,6 @@ module Chitin
|
|
146
168
|
|
147
169
|
[path, *arr.flatten].join ' '
|
148
170
|
end
|
149
|
-
|
150
171
|
end
|
151
172
|
end
|
152
173
|
|
data/lib/chitin/commands/ruby.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Chitin
|
2
|
-
class
|
2
|
+
class PVC
|
3
3
|
__sweep__ :[]
|
4
4
|
|
5
5
|
include Runnable
|
@@ -26,8 +26,13 @@ module Chitin
|
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
|
+
# prepare the initial input to be sent down through `@chains`
|
30
|
+
def prepare
|
31
|
+
self[:in]
|
32
|
+
end
|
33
|
+
|
29
34
|
def result
|
30
|
-
val =
|
35
|
+
val = prepare
|
31
36
|
@chains.each do |arr|
|
32
37
|
val = if Proc === arr.last
|
33
38
|
val.send *arr[0..-2], &arr[-1]
|
@@ -87,12 +92,30 @@ module Chitin
|
|
87
92
|
end.join '.'
|
88
93
|
end
|
89
94
|
|
95
|
+
def inspect
|
96
|
+
"#<PVC #{to_s}>"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class StringMethod < PVC
|
101
|
+
private
|
102
|
+
|
103
|
+
# the only difference is that we have `self[:in]`
|
104
|
+
# instead of just `self[:in].read`
|
105
|
+
def prepare
|
106
|
+
self[:in].read
|
107
|
+
end
|
108
|
+
|
90
109
|
def inspect
|
91
110
|
"#<StringMethod #{to_s}>"
|
92
111
|
end
|
93
112
|
end
|
94
113
|
end
|
95
114
|
|
115
|
+
# I'm leaving this all here because it's important in understanding the
|
116
|
+
# motivation for the above classes (PVC and StringMethod).
|
117
|
+
# But the Proc stuff below was replaced by PVC above.
|
118
|
+
|
96
119
|
# class Proc
|
97
120
|
# # So let's quick chat about what including Runnable to a proc means.
|
98
121
|
# # It means that it can be chained with pipes.
|
@@ -49,6 +49,8 @@ class Coolline
|
|
49
49
|
# In tests, this reads the first character of buffered input.
|
50
50
|
# In practice, this does not do anything differently than `@input.getch`
|
51
51
|
# C'est la vie.
|
52
|
+
# Notice how I went back to `@input.getch`, since Roger Pack was saying
|
53
|
+
# that `@input.raw { @input.getc }` wasn't working on Windows.
|
52
54
|
def read_char
|
53
55
|
#@input.raw { @input.getc }
|
54
56
|
@input.getch
|
@@ -68,7 +70,14 @@ class Coolline
|
|
68
70
|
#
|
69
71
|
# Also, @history_moved appears to be a useless variable.
|
70
72
|
def readline(prompt = ">> ")
|
71
|
-
|
73
|
+
lines = prompt.split("\n")
|
74
|
+
|
75
|
+
if lines.size == 1
|
76
|
+
@prompt = prompt
|
77
|
+
else
|
78
|
+
puts lines[0..-2]
|
79
|
+
@prompt = lines.last
|
80
|
+
end
|
72
81
|
|
73
82
|
@history.delete_empty
|
74
83
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Kernel
|
2
|
+
def D(path); Chitin::Directory.new path; end
|
3
|
+
def F(path); Chitin::FileObject.new path; end
|
4
|
+
def S(path); Chitin::Symlink.new path; end
|
5
|
+
|
6
|
+
alias_method :d, :D
|
7
|
+
alias_method :f, :F
|
8
|
+
alias_method :s, :S
|
9
|
+
|
10
|
+
# L for Lambda. Creates a proc as a RubyMethod
|
11
|
+
def L(&block)
|
12
|
+
Chitin::StringMethod.new :bottle, &block
|
13
|
+
end
|
14
|
+
|
15
|
+
def P(&block)
|
16
|
+
Chitin::PVC.new :bottle, &block
|
17
|
+
end
|
18
|
+
|
19
|
+
NULLIN = NULLOUT = NULLERR = File.open(File::NULL, 'w+')
|
20
|
+
end
|
21
|
+
|
data/lib/chitin/file.rb
CHANGED
@@ -143,20 +143,3 @@ module Chitin
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
146
|
-
module Kernel
|
147
|
-
def D(path); Chitin::Directory.new path; end
|
148
|
-
def F(path); Chitin::FileObject.new path; end
|
149
|
-
def S(path); Chitin::Symlink.new path; end
|
150
|
-
|
151
|
-
alias_method :d, :D
|
152
|
-
alias_method :f, :F
|
153
|
-
alias_method :s, :S
|
154
|
-
|
155
|
-
# L for Lambda. Creates a proc as a RubyMethod
|
156
|
-
def L(&block)
|
157
|
-
Chitin::StringMethod.new :bottle, &block
|
158
|
-
end
|
159
|
-
|
160
|
-
NULLIN = NULLOUT = NULLERR = File.open(File::NULL, 'w+')
|
161
|
-
end
|
162
|
-
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module Chitin
|
4
|
+
class Manifest
|
5
|
+
|
6
|
+
def self.register(hash)
|
7
|
+
@@password_hash = hash
|
8
|
+
end
|
9
|
+
|
10
|
+
# retrieve the manifest entry for the name
|
11
|
+
def self.find(name)
|
12
|
+
manifest_path = File.expand_path '.chitin_manifest'
|
13
|
+
manifest = File.read manifest_path
|
14
|
+
manifest_hmac = manifest_data[0..511]
|
15
|
+
manifest_data = manifest_data[512..-1]
|
16
|
+
|
17
|
+
# verify the authenticity of the file
|
18
|
+
computed_hmac = OpenSSL::HMAC.hexdigest('sha256',
|
19
|
+
@@password_hash,
|
20
|
+
manifest_data)
|
21
|
+
|
22
|
+
unless computed_hmac == manifest_hmac
|
23
|
+
puts "MANIFEST FILE HAS BEEN TAMPERED WITH"
|
24
|
+
return {}
|
25
|
+
end
|
26
|
+
|
27
|
+
@@data ||= {}
|
28
|
+
@@data[manifest_path] ||= YAML.load manifest_data
|
29
|
+
@@data[manifest_path][name]
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
data/lib/chitin/session.rb
CHANGED
@@ -7,17 +7,21 @@ module Chitin
|
|
7
7
|
|
8
8
|
attr_reader :config
|
9
9
|
attr_reader :editor
|
10
|
+
attr_reader :last_elapsed
|
10
11
|
|
11
12
|
def initialize(config=nil)
|
12
13
|
@config = config
|
13
14
|
@out = STDOUT
|
14
15
|
@sandbox = Sandbox.new # give it its own private space to work
|
15
|
-
|
16
|
+
|
17
|
+
# include the config and builtins
|
18
|
+
(class << @sandbox; self; end).send :include, @config
|
16
19
|
|
17
20
|
@editor = Coolline.new do |c|
|
18
21
|
# Remove the default of '-' and add support for strings
|
19
22
|
# starting after parentheses.
|
20
|
-
c.word_boundaries = [' ', "\t", "(", ")", '[', ']'
|
23
|
+
c.word_boundaries = [' ', "\t", "(", ")", '[', ']', '`', '@', '$', '>',
|
24
|
+
'<', '=', ';', '|', '&', '{', '}']
|
21
25
|
c.history_file = File.join ENV['HOME'], '.chitin_history'
|
22
26
|
|
23
27
|
# Make sure we don't kill the shell accidentally when we're trying to
|
@@ -40,9 +44,6 @@ module Chitin
|
|
40
44
|
# if there's a quote, remove it. we'll add it back in later, but it ruins
|
41
45
|
# searching so we need it removed for now.
|
42
46
|
unquoted_line = ['"', '\''].include?(line[0, 1]) ? line[1..-1] : line
|
43
|
-
|
44
|
-
#options = Dir[unquoted_line + '*']
|
45
|
-
#options +=
|
46
47
|
|
47
48
|
Dir[unquoted_line + '*'].map do |w|
|
48
49
|
slash_it = File.directory?(w) and line[-1] != '/' and w[-1] != '/'
|
@@ -65,6 +66,9 @@ module Chitin
|
|
65
66
|
while (val = read)
|
66
67
|
next if val.empty?
|
67
68
|
|
69
|
+
# a little bit of infrastructure for timing purposes
|
70
|
+
timing = Time.now
|
71
|
+
|
68
72
|
begin
|
69
73
|
res = evaluate val
|
70
74
|
display res unless val.lstrip[0, 1] == '#'
|
@@ -75,6 +79,8 @@ module Chitin
|
|
75
79
|
puts "#{e.message} (#{e.class})"
|
76
80
|
e.backtrace[1..-1].each {|l| puts "\t#{l}" }
|
77
81
|
nil
|
82
|
+
ensure
|
83
|
+
@last_elapsed = Time.now - timing
|
78
84
|
end
|
79
85
|
|
80
86
|
end
|
data/lib/chitin/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chitin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: wirble
|
@@ -85,13 +85,16 @@ files:
|
|
85
85
|
- lib/chitin/commands/pipe.rb
|
86
86
|
- lib/chitin/commands/ruby.rb
|
87
87
|
- lib/chitin/commands/runnable.rb
|
88
|
+
- lib/chitin/core_ext/array.rb
|
88
89
|
- lib/chitin/core_ext/class.rb
|
89
90
|
- lib/chitin/core_ext/coolline.rb
|
90
91
|
- lib/chitin/core_ext/io.rb
|
92
|
+
- lib/chitin/core_ext/kernel.rb
|
91
93
|
- lib/chitin/core_ext/object.rb
|
92
94
|
- lib/chitin/core_ext/string.rb
|
93
95
|
- lib/chitin/core_ext/symbol.rb
|
94
96
|
- lib/chitin/file.rb
|
97
|
+
- lib/chitin/manifests/manifest.rb
|
95
98
|
- lib/chitin/sandbox.rb
|
96
99
|
- lib/chitin/session.rb
|
97
100
|
- lib/chitin/support.rb
|