chitin 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,58 +3,64 @@ chitin
3
3
  by Ari Brown
4
4
  http://bitbucket.org/seydar/chitin
5
5
 
6
- Hai everybahdy
6
+ % gem install chitin # for bash
7
7
 
8
- Let's talk about the shell you're using real quick. It's most likely bash. Or
9
- at least it's bash-esque. There are a few hipsters among us who are using fish
10
- or zsh or whatever. A few of the older persuasion are into csh and tcsh.
11
- But that's not the point. The point is you're on a Ruby mailing list but you're
12
- not using a Ruby shell. It's time to upgrade. It's time to upgrade your shell
13
- to Chitin. I hope you all get the joke. I made it myself. The joke and the shell.
8
+ Hai everybahdy
14
9
 
15
10
  == So what IS Chitin?
16
11
 
17
12
  * Chitin is a Ruby interpreter
18
13
  * Turned into a shell.
19
14
 
20
- Everything you type is Ruby -- remember that. So let's look at it in action:
21
-
22
- ari: ~/src/chitin % 4 + 5
23
- => 9
24
-
25
- Boom. "Show me more!" Ok, but only because you asked so nicely:
26
-
27
- ari: ~/src/chitin % ls
28
- ANNOUNCEMENT README TODO bin chitin-1.0.gem chitin.gemspec
29
- chitinrc lib sample.txt
30
- ari: ~/src/chitin % hg.stat | wc | proc {|i| i.read.size } > '/tmp/test.out'
31
- ari: ~/src/chitin %
32
-
33
- Holy Batman! Yeah, waddap, git on mah level. I don't even know why you'd want
34
- to run that last command, but thar ya go.
35
-
36
- It's supposed to replace your current shell. Now OBVIOUSLY, you're not going
37
- to replace the entirety of the bash infrastructure that exists in computing and
38
- has existed for like 40 years since the dinosaurs first walked the Earth, but
39
- it's a start. It's just supposed to be for personal use.
15
+ I hope you all get the joke. I made it myself. The joke and the shell.
16
+
17
+ Everything you type is Ruby -- remember that. So let's look at it in action.
18
+ Remember that the tab completion makes typing quotes painless. Plus you don't
19
+ even need closing quotes if they're the final character in a line:
20
+
21
+ % hg.commit :m => 'fixed issues with procs in pipes...
22
+ % hg.push
23
+ pushing to https://seydar:***@bitbucket.org/seydar/chitin
24
+ ...
25
+ remote: bb/acl: seydar is allowed. accepted payload.
26
+ % cat("ANNOUNCEMENT") | pbcopy
27
+ % ll
28
+ total 136
29
+ -rw-r--r-- 1 ari staff 1.7K Nov 25 14:43 ANNOUNCEMENT
30
+ ...
31
+ -rw-r--r-- 1 ari staff 7.7K Nov 24 20:44 sample.txt
32
+ % rm "chitin-1.0.1.gem"
33
+ % gem.build "chitin.gemspec"
34
+ Successfully built RubyGem
35
+ Name: chitin
36
+ Version: 1.0.1
37
+ File: chitin-1.0.1.gem
38
+ % vim "ANNOUNCEMENT"
39
+ % ll | grep('gem')
40
+ -rw-r--r-- 1 ari staff 24K Nov 25 14:49 chitin-1.0.1.gem
41
+ -rw-r--r-- 1 ari staff 883B Nov 21 14:43 chitin.gemspec
42
+ % ll | split("\n").map {|l| l.size }
43
+ => [9, 57, 51, 49, 48, 61, 59, 53, 48, 55]
40
44
 
41
45
  == Why use it?
42
46
 
43
47
  Because it's written in Ruby and supadupes easy to modify. Also:
44
48
 
45
- * No need to use closing quotes. If you need a final quote in a line, don't
46
- sweat it. Chitin will take care of that.
47
- * Syntax highlighting while you type (thanks to Coolline!)
48
- * You can do simple arithmatic on the command line without having to switch
49
- interfaces (this was the original itch I had to scratch).
50
49
  * The power of Ruby in a shell
51
50
  * The command utility of a shell in Ruby
52
- * No underlying shell usage
51
+ * Text processing is SO. MUCH. EASIER.
53
52
  * A much more programmatic shell
54
53
  * Prevents against accidental `rm -rf /usr /local/bin` like that one thing
55
54
  we all saw on Reddit.
55
+ * Syntax highlighting while you type (thanks to Coolline!)
56
+ * You can do simple arithmetic on the command line without having to switch
57
+ interfaces (this was the original itch I had to scratch).
58
+ * No underlying shell usage
59
+ * Sweet tab completion
60
+ * No need to use closing quotes. If you need a final quote in a line, don't
61
+ sweat it. Chitin will take care of that.
62
+ * You can set key bindings to arbitrary keys
56
63
  * Makes for a great Christmas present
57
- * Text processing is SO. MUCH. EASIER.
58
64
  * Great library for calling executable files from your own program without
59
65
  shelling your soul or shelling out.
60
66
 
data/TODO CHANGED
@@ -1,32 +1,21 @@
1
1
  FUTURE:
2
- * add STDERR support
3
- * fix it so that self.err isn't alone in the whole `if self.err` bit.
4
2
  * set local variables in config, have them appear in shell
5
3
  * getting the menu to NOT have leading quotes
6
4
  * remove/edit history
7
5
  -> important for removing passwords if accidentally typed
8
6
  * improve library usage of executables
9
- * output silencing
10
- -> learn to fake being an IO
11
- -> shit won't work until then
12
- * get consistent on what methods needs #[] and what methods don't
7
+
8
+ QUIRKS:
9
+ * menu doesn't erase itself sometimes
10
+ -> cat and tabcomplete a file that is empty. output is correct but confusing
13
11
 
14
12
  FAILURES:
15
- * cursor display issues with the menu
16
- -> it places the cursor at the location of the cursor on the input line
17
- except the cursor is actually placed on the final line of the menu
18
- (the input line is several lines above it)
19
- * get coolline to play well with missing newlines before it
20
- -> right now it preserves junk on the line up until the first character is
21
- typed. once the user types something, the line is made pristine.
22
- -> see if you can replace reset_line with something like
23
- reset_what_was_written, deleting the prompt and the visible portion of
24
- the line
25
13
 
26
14
  Questions:
27
15
  * Why do you have to do @line = '' in Coolline in order to not affect the
28
16
  history? History calls el.dup which creates a new object. It shouldn't
29
17
  matter if I do @line.clear on the original.
30
- * Are there any ANSI codes for deleting part of a line? Yes. Duh. But what
31
- are they?
18
+
19
+ RELEASE
20
+ * failures
32
21
 
@@ -25,7 +25,7 @@ DESC
25
25
  # specify any dependencies here; for example:
26
26
  # s.add_development_dependency "rspec"
27
27
  s.add_runtime_dependency "wirble"
28
- s.add_runtime_dependency "coolline"
28
+ s.add_runtime_dependency "coolline", ">= 0.4.0"
29
29
  s.add_runtime_dependency "coderay"
30
30
  end
31
31
 
@@ -96,18 +96,8 @@ module Chitin
96
96
  module Prompts
97
97
  # The standard prompt. Must return a string. Override this to provide
98
98
  # a custom prompt.
99
- def big_prompt
100
- "+-#{'-' * ENV['USER'].length}--#{'-' * short_pwd.length}-+\n" +
101
- "| #{ENV['USER']}: #{short_pwd} |\n" +
102
- "+-#{'-' * ENV['USER'].length}--#{'-' * short_pwd.length}-+ "
103
- end
104
-
105
- def small_prompt
106
- "#{ENV['USER']}: #{short_pwd} % "
107
- end
108
-
109
99
  def prompt
110
- big_prompt
100
+ "#{ENV['USER']}: #{short_pwd} % "
111
101
  end
112
102
  end
113
103
  include Prompts
@@ -1,5 +1,7 @@
1
1
  module Chitin
2
2
  class Executable
3
+ __sweep__ :[]
4
+
3
5
  include Runnable
4
6
 
5
7
  def initialize(path, *args)
@@ -54,6 +56,10 @@ module Chitin
54
56
  @args += arr.map {|a| a.to_s }
55
57
  self # need to return this so that the shell can just run it
56
58
  end
59
+
60
+ def returning
61
+ :io
62
+ end
57
63
 
58
64
  # TODO fix it so that self.err isn't alone in the whole `if self.err`
59
65
  # bit. figure out a good way to make it default or something. i dunno.
@@ -100,11 +100,7 @@ module Chitin
100
100
  end
101
101
 
102
102
  def returning
103
- if [StringMethod, Proc].include?(@parts.last[:class])
104
- :ruby
105
- else
106
- :io
107
- end
103
+ parts.last[:returning]
108
104
  end
109
105
 
110
106
  end
@@ -1,5 +1,7 @@
1
1
  module Chitin
2
2
  class StringMethod
3
+ __sweep__ :[]
4
+
3
5
  include Runnable
4
6
 
5
7
  attr_reader :chains
@@ -18,6 +20,7 @@ module Chitin
18
20
  end
19
21
 
20
22
  def method_missing(*arr, &block)
23
+ puts caller[0]
21
24
  latest = [*arr]
22
25
  latest << block if block
23
26
  @chains << latest
@@ -29,7 +32,7 @@ module Chitin
29
32
  def result
30
33
  val = self[:in].read
31
34
  @chains.each do |arr|
32
- val = if arr.last.is_a? Proc
35
+ val = if Proc === arr.last
33
36
  val.send *arr[0..-2], &arr[-1]
34
37
  else
35
38
  val.send *arr
@@ -53,6 +56,8 @@ module Chitin
53
56
  reset
54
57
 
55
58
  @pid = child
59
+
60
+ self
56
61
  end
57
62
 
58
63
  # like #run, except instead of writing the output
@@ -67,13 +72,18 @@ module Chitin
67
72
  end
68
73
 
69
74
  def wait
70
- Process.wait @pid
75
+ @pid && Process.wait(@pid)
71
76
  end
72
77
 
73
78
  def reset
74
79
  self.in, self.out, self.err = nil
75
80
  end
81
+
82
+ def returning
83
+ :ruby
84
+ end
76
85
 
86
+ # fix this. What if someone passes an executable as an argument?
77
87
  def to_s
78
88
  @chains.map do |arr|
79
89
  "#{arr[0]}(#{arr[1..-1].map {|a| a.is_a?(Proc) ? "&block" : a.inspect }.join ', '})"
@@ -86,67 +96,69 @@ module Chitin
86
96
  end
87
97
  end
88
98
 
89
- class Proc
90
- # So let's quick chat about what including Runnable to a proc means.
91
- # It means that it can be chained with pipes.
92
- # It also means that you can run private methods with #[].
93
- # The important thing isn't that you can run private methods. You could
94
- # do that since the beginning of time.
95
- # The take-away is that it OVERRIDES #[]. In the words of Joe Biden,
96
- # this is a big fucking deal.
97
- #
98
- # whatdo.jpg
99
- #
100
- # This means that you cannot, in the environment of Chitin, use
101
- # Proc#[] for anything other than accessing private methods. This
102
- # means it does not play well with others. This is what we in the biz
103
- # call bad.
104
- undef_method :[]
105
- include Chitin::Runnable
106
-
107
- # # access private methods
108
- # def [](*args)
109
- # if method(args.first)
110
- # method(args.first).call *args[1..-1]
111
- # else
112
- # raise NoMethodError.new("undefined method" +
113
- # "`#{args.first}' for #{self}:#{self.class}")
114
- # end
115
- # end
116
-
117
- def |(other)
118
- Pipe.new self, other
119
- end
120
-
121
- private
122
-
123
- def run
124
- child = fork do
125
- self.out.puts call(self.in)
126
-
127
- close_all
128
- end
129
-
130
- close_all
131
- reset
132
-
133
- @pid = child
134
- end
135
-
136
- def raw_run
137
- val = call self.in
138
-
139
- close_all
140
- reset
141
- val
142
- end
143
-
144
- def wait
145
- Process.wait @pid
146
- end
147
-
148
- def reset
149
- self.in, self.out, self.err = nil
150
- end
151
- end
99
+ # class Proc
100
+ # # So let's quick chat about what including Runnable to a proc means.
101
+ # # It means that it can be chained with pipes.
102
+ # # It also means that you can run private methods with #[].
103
+ # # The important thing isn't that you can run private methods. You could
104
+ # # do that since the beginning of time.
105
+ # # The take-away is that it OVERRIDES #[]. In the words of Joe Biden,
106
+ # # this is a big fucking deal.
107
+ # #
108
+ # # whatdo.jpg
109
+ # #
110
+ # # This means that you cannot, in the environment of Chitin, use
111
+ # # Proc#[] for anything other than accessing private methods. This
112
+ # # means it does not play well with others. This is what we in the biz
113
+ # # call bad.
114
+ # #
115
+ # # Maybe I shouldn't even offer this as a feature.
116
+ # undef_method :[]
117
+ # include Chitin::Runnable
118
+ #
119
+ # # # access private methods
120
+ # # def [](*args)
121
+ # # if method(args.first)
122
+ # # method(args.first).call *args[1..-1]
123
+ # # else
124
+ # # raise NoMethodError.new("undefined method" +
125
+ # # "`#{args.first}' for #{self}:#{self.class}")
126
+ # # end
127
+ # # end
128
+ #
129
+ # def |(other)
130
+ # Pipe.new self, other
131
+ # end
132
+ #
133
+ # private
134
+ #
135
+ # def run
136
+ # child = fork do
137
+ # self.out.puts call(self.in)
138
+ #
139
+ # close_all
140
+ # end
141
+ #
142
+ # close_all
143
+ # reset
144
+ #
145
+ # @pid = child
146
+ # end
147
+ #
148
+ # def raw_run
149
+ # val = call self.in
150
+ #
151
+ # close_all
152
+ # reset
153
+ # val
154
+ # end
155
+ #
156
+ # def wait
157
+ # Process.wait @pid
158
+ # end
159
+ #
160
+ # def reset
161
+ # self.in, self.out, self.err = nil
162
+ # end
163
+ # end
152
164
 
@@ -15,7 +15,22 @@ module Chitin
15
15
 
16
16
  self
17
17
  end
18
+
19
+ def >>(io)
20
+ case io
21
+ when IO, File
22
+ self[:set_err, io]
23
+ when String, FileObject
24
+ f = File.open io, 'w'
25
+ self[:set_err, f]
26
+ f.close
27
+ else
28
+ raise "Unknown piping type: #{io.class}"
29
+ end
18
30
 
31
+ self
32
+ end
33
+
19
34
  # access private methods
20
35
  def [](*args)
21
36
  if method(args.first)
@@ -25,13 +40,20 @@ module Chitin
25
40
  "`#{args.first}' for #{self}:#{self.class}")
26
41
  end
27
42
  end
28
-
43
+
44
+ def bg!; @bg = true; self; end
45
+ def bg?; @bg; end
46
+
29
47
  private
30
48
 
31
49
  attr_accessor :bg
32
50
  attr_accessor :in
33
51
  attr_accessor :out
34
52
  attr_accessor :err
53
+
54
+ def returning
55
+ raise "Not Yet Implemented"
56
+ end
35
57
 
36
58
  # Generally the same as +run+, except for the ruby commands
37
59
  # they return real ruby that can be given back to the user.
@@ -0,0 +1,9 @@
1
+ class Class
2
+ def __sweep__(*save)
3
+ instance_methods.each do |meth|
4
+ next if save.include? meth
5
+ private meth
6
+ end
7
+ end
8
+ end
9
+
@@ -70,7 +70,7 @@ class Coolline
70
70
 
71
71
  @should_exit = false
72
72
 
73
- #reset_line
73
+ reset_line
74
74
  print @prompt
75
75
 
76
76
  @history.index = @history.size - 1
@@ -98,6 +98,7 @@ class Coolline
98
98
 
99
99
  @history.save_line
100
100
 
101
+ @menu.erase
101
102
  @line
102
103
  end
103
104
  end
@@ -1,6 +1,9 @@
1
1
  module Chitin
2
2
  class FSObject
3
+ include Enumerable
4
+
3
5
  attr_accessor :path
6
+ attr_accessor :search
4
7
 
5
8
  # The choice to not have File.expand_path here is explicitly done.
6
9
  # Relativity is up to the user.
@@ -8,6 +11,7 @@ module Chitin
8
11
  # and over again on lists of files.
9
12
  def initialize(path, opts={})
10
13
  @path = path
14
+ @search = proc { path }
11
15
  @unknown = opts[:unknown]
12
16
  end
13
17
 
@@ -15,6 +19,37 @@ module Chitin
15
19
  @unknown
16
20
  end
17
21
 
22
+ def files
23
+ return @files if @files
24
+ files = Dir[search.call]
25
+ @files = files.inject({}) do |h, f|
26
+ f = f[2..-1] if f.start_with? './'
27
+ h[f] = if File.directory? f
28
+ D f
29
+ elsif File.file? f
30
+ F f
31
+ elsif File.symlink? f
32
+ S f
33
+ else
34
+ FSObject.new f, :unknown => true
35
+ end
36
+
37
+ h
38
+ end
39
+ end
40
+
41
+ def each(&block)
42
+ files.values.each &block
43
+ end
44
+
45
+ def to_a
46
+ files.values
47
+ end
48
+
49
+ def size
50
+ files.size
51
+ end
52
+
18
53
  def lstat
19
54
  File.lstat @path
20
55
  end
@@ -42,7 +77,7 @@ module Chitin
42
77
  block.call f
43
78
  end
44
79
  end
45
-
80
+
46
81
  def delete
47
82
  File.safe_unlink @path
48
83
  end
@@ -71,49 +106,27 @@ module Chitin
71
106
  end
72
107
 
73
108
  class Directory < FSObject
74
- include Enumerable
75
-
76
- def files
77
- return @files if @files
78
- files = Dir[File.join(path, '*')]
79
- @files = files.inject({}) do |h, f|
80
- f = f[2..-1] if f.start_with? './'
81
- h[f] = if File.directory? f
82
- D f
83
- elsif File.file? f
84
- F f
85
- elsif File.symlink? f
86
- S f
87
- else
88
- FSObject.new f, :unknown => true
89
- end
90
-
91
- h
92
- end
109
+ def initialize(path, opts={})
110
+ super
111
+ @search = proc { File.join self.path, '*' }
93
112
  end
94
-
113
+
95
114
  def down
96
- self.path = File.join path, '**'
115
+ @path = File.join path, '**'
116
+ @files = nil
97
117
  self
98
118
  end
99
119
 
100
120
  # Get a specific level down
101
121
  def level(n=1)
102
- n.times { self.path = File.join path, '*' }
122
+ n.times { @path = File.join self.path, '*' }
123
+ @files = nil
103
124
  self
104
125
  end
105
-
106
- def each(&block)
107
- files.values.each &block
108
- end
109
-
110
- def to_a
111
- files.values
112
- end
113
-
126
+
114
127
  def delete
115
128
  # this is probably unwise...
116
- File.rm_rf @path
129
+ File.rm_rf path
117
130
  end
118
131
 
119
132
  def inspect
@@ -124,40 +137,17 @@ module Chitin
124
137
  false
125
138
  end
126
139
  end
140
+ end
127
141
 
128
- # Consumes all input.
129
- # Gives no output.
130
- # Takes no prisoners.
131
- # Used for NULLIN, NULLOUT, and NULLERR.
132
- class Abyss
133
- def eof?
134
- true
135
- end
136
-
137
- def read
138
- ""
139
- end
140
- alias_method :readline, :read
141
-
142
- def <<(*args)
143
- end
144
- alias_method :write, :<<
145
- alias_method :puts, :<<
142
+ module Kernel
143
+ def D(path); Chitin::Directory.new path; end
144
+ def F(path); Chitin::FileObject.new path; end
145
+ def S(path); Chitin::Symlink.new path; end
146
146
 
147
- def >(executable)
148
- executable[:in=, self]
149
- executable
150
- end
147
+ alias_method :d, :D
148
+ alias_method :f, :F
149
+ alias_method :s, :S
151
150
 
152
- def close
153
- true
154
- end
155
- end
151
+ NULLIN = NULLOUT = NULLERR = File.open File::NULL
156
152
  end
157
-
158
- def D(path); Chitin::Directory.new path; end
159
- def F(path); Chitin::FileObject.new path; end
160
- def S(path); Chitin::Symlink.new path; end
161
-
162
- NULLIN = NULLOUT = NULLERR = Chitin::Abyss.new
163
153
 
@@ -80,6 +80,20 @@ module Chitin
80
80
  # THIS METHOD WILL POSSIBLY RETURN NIL!!!!!
81
81
  # So it can return a string or nil. Remember that, folks.
82
82
  def read
83
+ # find out the column (1-indexed) that will next be printed
84
+ # if it's NOT 1, then something was printed, and we want to insert
85
+ # a newline
86
+ a = nil
87
+ STDIN.raw do
88
+ print "\e[6n"
89
+ a = STDIN.gets 'R'
90
+ end
91
+
92
+ if a.chomp('R').split(';').last != '1'
93
+ puts
94
+ puts "(no trailing newline)"
95
+ end
96
+
83
97
  inp = @editor.readline @sandbox.prompt
84
98
 
85
99
 
@@ -97,21 +111,32 @@ module Chitin
97
111
  @sandbox.evaluate val
98
112
  end
99
113
 
100
- def shell_command?(res)
101
- res.is_a?(Executable) || (res.is_a?(Pipe) && res[:returning] != :ruby)
114
+ def returning_ruby?(res)
115
+ # We have to use #stat here because reopened pipes retain the file
116
+ # descriptor of the original pipe. Example:
117
+ # r, w = IO.pipe; r.reopen STDIN; r == STDIN # => false
118
+ # Thus, we have to use #stat (or, more lamely, #inspect).
119
+ return true unless Runnable === res
120
+
121
+ res[:returning] == :ruby &&
122
+ (res[:out] == nil ||
123
+ res[:out].stat == STDOUT.stat)
124
+ end
125
+
126
+ def all_not_ruby?(res)
127
+ if Array === res
128
+ !res.empty? && res.map {|r| not returning_ruby? r }.all?
129
+ else
130
+ not returning_ruby? res
131
+ end
102
132
  end
103
133
 
104
134
  def display(res)
105
135
  # The reason that this is here instead of in #evaluate is that
106
136
  # pipes could, in fact, have NO display output, but that isn't for
107
137
  # #evaluate to decide; rather, it is for #display
108
- #
109
- # Only pipes and executables are standalone. StringMethods need to be
110
- # chained, and proc is also a general Ruby type, so we don't want to
111
- # automatically call it.
112
- if shell_command?(res) || (res.is_a?(Array) && !res.empty? && res.map {|r| shell_command? r }.all?)
113
-
114
- res = [res] unless res.is_a?(Array)
138
+ if all_not_ruby? res
139
+ res = [res] unless Array === res
115
140
 
116
141
  res.each do |res|
117
142
  # set up the inputs and outputs
@@ -125,30 +150,19 @@ module Chitin
125
150
 
126
151
  else # else it's a standard ruby type (or a pipe returning as such)
127
152
 
128
- unless res.is_a? Pipe
129
- # RUBY values pass through here
130
- txt = @config.post_processing[:color].call res.inspect
131
- puts " => #{txt}"
132
- else
153
+ if Pipe === res || StringMethod === res
133
154
  # set up the inputs and outputs
134
155
  res[:set_in, STDIN] unless res[:in]
135
156
  res[:set_out, STDOUT] unless res[:out]
136
157
  res[:set_err, STDOUT] unless res[:err]
137
-
138
- # We have to use #stat here because reopened pipes retain the file
139
- # descriptor of the original pipe. Example:
140
- # r, w = IO.pipe; r.reopen STDIN; r == STDIN # => false
141
- # Thus, we have to use #stat (or, more lamely, #inspect).
142
- if res[:out].stat == STDOUT.stat
143
- val = res[:raw_run]
144
- txt = @config.post_processing[:color].call val.inspect
145
- puts " => #{txt}"
146
- else
147
- res[:run]
148
- res[:wait] unless res[:bg]
149
- end
158
+
159
+ val = res[:raw_run]
160
+ else
161
+ val = res
150
162
  end
151
163
 
164
+ txt = @config.post_processing[:color].call val.inspect
165
+ puts " => #{txt}"
152
166
  end
153
167
 
154
168
  # Run all the post_processing stuff
@@ -1,4 +1,4 @@
1
1
  module Chitin
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  end
4
4
 
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.1
4
+ version: 1.0.2
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: 2012-11-25 00:00:00.000000000 Z
12
+ date: 2012-12-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: wirble
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: '0'
37
+ version: 0.4.0
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: '0'
45
+ version: 0.4.0
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: coderay
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -84,6 +84,7 @@ files:
84
84
  - lib/chitin/commands/pipe.rb
85
85
  - lib/chitin/commands/ruby.rb
86
86
  - lib/chitin/commands/runnable.rb
87
+ - lib/chitin/core_ext/class.rb
87
88
  - lib/chitin/core_ext/coolline.rb
88
89
  - lib/chitin/core_ext/io.rb
89
90
  - lib/chitin/core_ext/object.rb