chitin 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -404,3 +404,7 @@ Did you know?
404
404
  * ^q quotes the word just behind your cursor
405
405
  * I think this train might ACTUALLY get to Chicago on time!
406
406
 
407
+ == Thanks
408
+
409
+ A huge thank you to Roger Pack. You know why.
410
+
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); super(args).chomp; end
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 emphasize
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
- setup name.to_s, *process_args(arr)
17
- self
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 that
43
- # in conjunction with * means things get expanded twice, resulting
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
 
@@ -1,5 +1,5 @@
1
1
  module Chitin
2
- class StringMethod
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 = self[:in].read
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.
@@ -0,0 +1,7 @@
1
+ class Array
2
+ # [[k, v], [k, v], ...]
3
+ def to_hash
4
+ self.inject({}) {|h, (k, v)| h[k] = v; h }
5
+ end
6
+ end
7
+
@@ -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
- @prompt = prompt
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
+
@@ -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
+
@@ -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
- (class << @sandbox; self; end).send :include, @config # include the config and builtins
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
@@ -1,4 +1,4 @@
1
1
  module Chitin
2
- VERSION = '1.0.5'
2
+ VERSION = '1.0.6'
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.5
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-03-11 00:00:00.000000000 Z
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