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 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