chitin 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ANNOUNCEMENT +67 -0
- data/README +414 -0
- data/TODO +32 -0
- data/bin/chitin +26 -0
- data/chitin.gemspec +31 -0
- data/chitinrc +86 -0
- data/lib/chitin/commands/builtins.rb +224 -0
- data/lib/chitin/commands/executable.rb +139 -0
- data/lib/chitin/commands/pipe.rb +112 -0
- data/lib/chitin/commands/ruby.rb +152 -0
- data/lib/chitin/commands/runnable.rb +84 -0
- data/lib/chitin/core_ext/coolline.rb +104 -0
- data/lib/chitin/core_ext/io.rb +7 -0
- data/lib/chitin/core_ext/object.rb +21 -0
- data/lib/chitin/core_ext/string.rb +35 -0
- data/lib/chitin/core_ext/symbol.rb +6 -0
- data/lib/chitin/file.rb +163 -0
- data/lib/chitin/sandbox.rb +18 -0
- data/lib/chitin/session.rb +167 -0
- data/lib/chitin/support.rb +51 -0
- data/lib/chitin/tools/csv.rb +0 -0
- data/lib/chitin/tools/replay.rb +45 -0
- data/lib/chitin/tools/string_methods.rb +10 -0
- data/lib/chitin/version.rb +4 -0
- data/lib/chitin.rb +26 -0
- data/sample.txt +187 -0
- metadata +126 -0
data/ANNOUNCEMENT
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
chitin
|
2
|
+
========================
|
3
|
+
by Ari Brown
|
4
|
+
http://bitbucket.org/seydar/chitin
|
5
|
+
|
6
|
+
Hai everybahdy
|
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.
|
14
|
+
|
15
|
+
== So what IS Chitin?
|
16
|
+
|
17
|
+
* Chitin is a Ruby interpreter
|
18
|
+
* Turned into a shell.
|
19
|
+
|
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.
|
40
|
+
|
41
|
+
== Why use it?
|
42
|
+
|
43
|
+
Because it's written in Ruby and supadupes easy to modify. Also:
|
44
|
+
|
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
|
+
* The power of Ruby in a shell
|
51
|
+
* The command utility of a shell in Ruby
|
52
|
+
* No underlying shell usage
|
53
|
+
* A much more programmatic shell
|
54
|
+
* Prevents against accidental `rm -rf /usr /local/bin` like that one thing
|
55
|
+
we all saw on Reddit.
|
56
|
+
* Makes for a great Christmas present
|
57
|
+
* Text processing is SO. MUCH. EASIER.
|
58
|
+
* Great library for calling executable files from your own program without
|
59
|
+
shelling your soul or shelling out.
|
60
|
+
|
61
|
+
Anyways, I really like it and find it useful. I much prefer it over Bash. I
|
62
|
+
encourage you all to take a quick look at the README and maybe try it out
|
63
|
+
yourselves.
|
64
|
+
|
65
|
+
- Ari/seydar
|
66
|
+
ari@aribrown.com
|
67
|
+
|
data/README
ADDED
@@ -0,0 +1,414 @@
|
|
1
|
+
== Quick Intro
|
2
|
+
|
3
|
+
Rules of the road:
|
4
|
+
|
5
|
+
* Everything you enter is pure Ruby. When you type, you are typing pure Ruby.
|
6
|
+
* When in doubt of what something is: use #inspect by doing command[:inspect]
|
7
|
+
* #[] allows you to run methods of Executables, Pipes, and StringMethods
|
8
|
+
without accidentally running them.
|
9
|
+
|
10
|
+
Sample commands and shizzle:
|
11
|
+
|
12
|
+
ari: ~/src/chitin % ls
|
13
|
+
ari: ~/src/chitin % 5 + 4
|
14
|
+
ari: ~/src/chitin % ll = ls -:al
|
15
|
+
ari: ~/src/chitin % hg.stat
|
16
|
+
ari: ~/src/chitin % hg.stat | wc | L {|i| i.size }
|
17
|
+
ari: ~/src/chitin % hg.stat | wc | L {|i| i.size } > '/tmp/test.out'
|
18
|
+
ari: ~/src/chitin % 44 - 2
|
19
|
+
ari: ~/src/chitin % _ + 5
|
20
|
+
ari: ~/src/chitin % wget "http://bigbad.evils.in
|
21
|
+
ari: ~/src/chitin % _ # run the same command again
|
22
|
+
|
23
|
+
Look! Thanks to Mon_Ouie, it even has syntax highlighting on the line as you
|
24
|
+
type! Hooray! Thank you, monsieur!
|
25
|
+
|
26
|
+
For the most part, you can just use chitin as you would bash or any other
|
27
|
+
shell.
|
28
|
+
|
29
|
+
Why should you use Chitin?
|
30
|
+
|
31
|
+
* You can do simple arithmatic on the command line without having to switch
|
32
|
+
interfaces.
|
33
|
+
* The power of Ruby in a shell
|
34
|
+
* The command utility of a shell in Ruby
|
35
|
+
* No underlying shell usage
|
36
|
+
* A much more programmatic shell
|
37
|
+
* Prevents against accidental `rm -rf /usr /local/bin` like that one thing
|
38
|
+
we all saw on Reddit.
|
39
|
+
* Syntax highlighting while you type
|
40
|
+
* Makes for a great Christmas present
|
41
|
+
* Text processing is SO. MUCH. EASIER.
|
42
|
+
* Great library for calling executable files from your own program without
|
43
|
+
shelling your soul or shelling out.
|
44
|
+
|
45
|
+
== The Library
|
46
|
+
|
47
|
+
Buckle up, kids:
|
48
|
+
|
49
|
+
include Chitin
|
50
|
+
|
51
|
+
Real simply, here's how you create a reference to a file with Chitin:
|
52
|
+
|
53
|
+
f = FileObject.new "/bin/ls"
|
54
|
+
f = F "/bin/ls"
|
55
|
+
|
56
|
+
and a directory:
|
57
|
+
|
58
|
+
d = Directory.new "/bin"
|
59
|
+
d = D "/bin"
|
60
|
+
|
61
|
+
Which is sweet and all, but you kinda need read and write priveleges in order
|
62
|
+
to read and write to it. And if you're writing to /bin/ls, you're a bad person.
|
63
|
+
|
64
|
+
So we can make it an executable really easily:
|
65
|
+
|
66
|
+
f = Executable.new "/bin/ls"
|
67
|
+
|
68
|
+
By default, it reads and writes from and to, respectively, empty pipes.
|
69
|
+
So to make it work in a standard manner, we need to set it up to use STDIN,
|
70
|
+
STDOUT, and STDERR.
|
71
|
+
|
72
|
+
f.in.reopen STDIN # f.in is the input to f
|
73
|
+
f.out.reopen STDOUT # f.out is the output of f
|
74
|
+
f.err.reopen STDERR # f.err is the error of f
|
75
|
+
|
76
|
+
We can easily run this:
|
77
|
+
|
78
|
+
f.run
|
79
|
+
|
80
|
+
SWEET!
|
81
|
+
|
82
|
+
A more complicated example of "cat /tmp/cool | wc -l":
|
83
|
+
|
84
|
+
f = Executable.new "/bin/cat", "/tmp/cool"
|
85
|
+
g = Executable.new "/bin/wc", "-l"
|
86
|
+
|
87
|
+
Now we link them together (something like f | g)
|
88
|
+
|
89
|
+
g.in.reopen f.out
|
90
|
+
|
91
|
+
And make the overall input and output visible to us
|
92
|
+
|
93
|
+
f.in.reopen STDIN
|
94
|
+
g.out.reopen STDOUT
|
95
|
+
|
96
|
+
and run them
|
97
|
+
|
98
|
+
f.run # since these are asynchronous
|
99
|
+
g.run # this seems like an ok thing to do
|
100
|
+
|
101
|
+
That's a lot of work, though. Luckily, we can simplify it all:
|
102
|
+
|
103
|
+
STDIN > f | g > STDOUT
|
104
|
+
|
105
|
+
What's that? You have another function called h?
|
106
|
+
|
107
|
+
h = Executable.new "/bin/cat"
|
108
|
+
pipe = STDIN > f | g | h > STDOUT
|
109
|
+
|
110
|
+
And then you can run the pipe simply:
|
111
|
+
|
112
|
+
pipe.run
|
113
|
+
|
114
|
+
Easy peasy, right? But what if you want to run the exact same command again?
|
115
|
+
No worries:
|
116
|
+
|
117
|
+
pipe.run
|
118
|
+
|
119
|
+
It automatically resets itself internally after being run.
|
120
|
+
|
121
|
+
You can even use ruby code:
|
122
|
+
|
123
|
+
STDIN > f | gsub(/asdf/, "LAWL") > STDOUT
|
124
|
+
|
125
|
+
And you can chain it simply:
|
126
|
+
|
127
|
+
STDIN > f | gsub(/asdf/, "LAWL").chomp > STDOUT
|
128
|
+
|
129
|
+
You can even set up a pipe to return a random ruby object of your choice:
|
130
|
+
|
131
|
+
STDIN > f | split.size > STDOUT
|
132
|
+
|
133
|
+
Although you have to run it with `pipe.raw_run`.
|
134
|
+
|
135
|
+
If you have your own method and you want to take the result of something as an
|
136
|
+
input, you can use a special proc to make it happen:
|
137
|
+
|
138
|
+
STDIN > f | L {|i| my_method(i) } > STDOUT
|
139
|
+
|
140
|
+
And let's say that you want it all into a file. No problemo, broski.
|
141
|
+
|
142
|
+
STDIN > f | L {|i| my_method(i) } > '/tmp/lolwut'
|
143
|
+
|
144
|
+
Dis ish goes both ways:
|
145
|
+
|
146
|
+
'/tmp/my_input' > f | L {|i| my_method(i) } > '/tmp/lolwut'
|
147
|
+
|
148
|
+
SILENCE ALLLLLLLLLLLLLLLLLLLL
|
149
|
+
|
150
|
+
NULLIN > f | L {|i| my_method(i) } > NULLOUT > NULLERR
|
151
|
+
|
152
|
+
Git on mah level, son.
|
153
|
+
|
154
|
+
== The Shell
|
155
|
+
|
156
|
+
Chitin is such named because it is the material that comprises the exoskeleton
|
157
|
+
shells of insects. Yes, I know insects suck, but chitin is a pretty cool word,
|
158
|
+
especially when you learn that it's pronounced chitin and not chitin.
|
159
|
+
|
160
|
+
By default, chitin gives you a funky prompt that's big like yo mamma. The
|
161
|
+
reason the default prompt is so AWESOME is so that it doesn't look identical
|
162
|
+
to my bash prompt (leading me to get confused) but still provides useful
|
163
|
+
information. Before we continue our tutorial, let's change that. Add the
|
164
|
+
following bit of code to ~/.chitinrc
|
165
|
+
|
166
|
+
def prompt
|
167
|
+
"#{ENV['USER']}: #{short_pwd} % "
|
168
|
+
end
|
169
|
+
|
170
|
+
1337. Well done! You've been promoted to tenderfoot. I'm proud of you.
|
171
|
+
|
172
|
+
So now let's get going with this thang. Try out some random math equation:
|
173
|
+
|
174
|
+
ari: ~/src/chitin % 4 + 5
|
175
|
+
=> 9
|
176
|
+
ari: ~/src/chitin % (1 + 3 + 4 +65 + 7 +345) / 23
|
177
|
+
=> 18.4782608695652
|
178
|
+
|
179
|
+
NB: integer division is off by default because it sucks and always has sucked.
|
180
|
+
If I'm cranking out some quick maths, I don't want to deal with the fact that
|
181
|
+
3/4 = 0. NIQUE LA POLICE WOOT WOOT!!!!!
|
182
|
+
|
183
|
+
So ladida, you're doing some math, this could be IRB with a few changes.
|
184
|
+
HOLY BATMAN! LOOK AT THAT SHIZNIZZLE YOU JUST DID!!! Oh, you mean this bit?
|
185
|
+
|
186
|
+
ari: ~/src/chitin % ls
|
187
|
+
NOTES README TODO bin lib
|
188
|
+
|
189
|
+
Yeah, that's right. We just ran a command. And guess what? We didn't have to
|
190
|
+
start a shell underneath to get it to work! We also didn't use any system
|
191
|
+
calls because that would be hell to get right for every system. Though it
|
192
|
+
might be neat for a future version. Note to self...
|
193
|
+
|
194
|
+
But that's not all! Let's make ruby do some heavy lifting for us:
|
195
|
+
|
196
|
+
ari: ~/src/chitin % ls | L {|s| s.split }
|
197
|
+
=> ["NOTES", "README", "TODO", "bin", "lib"]
|
198
|
+
|
199
|
+
Chyeah son, it even returned us a ruby object.
|
200
|
+
|
201
|
+
What Chitin as a shell does is it automatically does the STDIN > ... > STDOUT
|
202
|
+
boilerplate that you saw in the first section. It also automagically runs your
|
203
|
+
pipe, calling #run in the general case and #raw_run if it's supposed to return
|
204
|
+
ruby.
|
205
|
+
|
206
|
+
To earn your second class rank, you need to do a few things. First, you must
|
207
|
+
demonstrate proficiency with the bowline knot and clove hitch. These are just
|
208
|
+
good life skillz. Second, you must solve a problem for "your friend Jimmy".
|
209
|
+
|
210
|
+
Jimmmy has a pokemon folder on his computer that he doesn't want his dad to see.
|
211
|
+
Unfortunately, Jimmy doesn't know about cryptography and wants to give you
|
212
|
+
(hah, as if you and Jimmy aren't the same person) a task to solve with Chitin.
|
213
|
+
Help him hide his pokemon folder from his dad who likes to cd and ls around!
|
214
|
+
|
215
|
+
ari: ~/src/chitin % ls
|
216
|
+
NOTES POKEMON README TODO bin lib
|
217
|
+
ari: ~/src/chitin % ls | L {|s| a = s.gsub /pokemon/i, "digimon"} | cat
|
218
|
+
NOTES
|
219
|
+
digimon
|
220
|
+
README
|
221
|
+
TODO
|
222
|
+
bin
|
223
|
+
lib
|
224
|
+
ari: ~/src/chitin % def ls; raw_command('/bin/ls') | L {|s| s.gsub /pokemon/i, "digimon" } | cat; end
|
225
|
+
=> nil
|
226
|
+
ari: ~/src/chitin % ls
|
227
|
+
NOTES
|
228
|
+
digimon
|
229
|
+
README
|
230
|
+
TODO
|
231
|
+
bin
|
232
|
+
lib
|
233
|
+
|
234
|
+
Save that in you ~/.chitinrc and your dad won't find out about your pokemon
|
235
|
+
collection.
|
236
|
+
|
237
|
+
Congratulations! You are now a second class scout!
|
238
|
+
|
239
|
+
Alright, hotshot. Let's see if you've got what it takes to be first class.
|
240
|
+
Your boss rolls into your office and asks to speak with you. You know it
|
241
|
+
couldn't be about your porn collection because you fixed that in attaining
|
242
|
+
second class; now he just thinks you're a nerd for having a 40GB digimon
|
243
|
+
collection. So bossman rolls in and says "Yo dawg, delete every file and folder
|
244
|
+
in a directory." Naturally, he decides not to open up a GUI and do that himself
|
245
|
+
using the wonders of modern technology (the mouse). You look that cat dead in
|
246
|
+
the eye and say "YES SIR LET'S DO DIS THANG!"
|
247
|
+
|
248
|
+
ari: ~/src/chitin % Dir['pokemon/*'].each {|f| rm f }
|
249
|
+
|
250
|
+
But since I'm a sick bastard, I showed you code that DOES NOT WORK. Before I
|
251
|
+
get into why it doesn't work, lemme show you code that DOES work, first:
|
252
|
+
|
253
|
+
ari: ~/src/chitin % Dir['pokemon/*'].map {|f| rm f}
|
254
|
+
|
255
|
+
The difference here is that we used #map instead of #each. Why?
|
256
|
+
|
257
|
+
#each is a function that returns self after running the block. Since an
|
258
|
+
executable is just a Ruby object that is only run when told to, those blocks
|
259
|
+
will never run the code you want. In order to run the code, we use #map to
|
260
|
+
return the executables we want to run in an array. Chitin knows that whenever
|
261
|
+
it sees an array of executables, its job is to execute them.
|
262
|
+
|
263
|
+
But let's get back to the original problem, which was removing a buttload of
|
264
|
+
files:
|
265
|
+
|
266
|
+
ari: ~/src/chitin % rm *Dir['pokemon/*']
|
267
|
+
|
268
|
+
The built-in Ruby * (glob) operator enables us to do batch functions as an
|
269
|
+
afterthought. It is like `rm "file1", "file2", ...`.
|
270
|
+
|
271
|
+
Sweet deal brah, you're a second class scout. To become a first class scout,
|
272
|
+
you need to install something. Luckily, Rosy the Nosy Neighbor from down the
|
273
|
+
street (guess who just watch "Trapped in the Closet" -- all fucking 23 videos)
|
274
|
+
wants you to install this C program that she wrote so she can monitor your
|
275
|
+
keystrokes. Here comes you to the rescue! OH MAN that rhymed. Time to give
|
276
|
+
up 'gramming and move to lyrical wordsmithing.
|
277
|
+
|
278
|
+
First, you gotsta download the codez:
|
279
|
+
|
280
|
+
ari: ~/src/chitin % wget "http://supersecret.com/rosys_stuff.tar.gz
|
281
|
+
|
282
|
+
Simple enough, you're just running the `wget` command. Now, unzip it to remove
|
283
|
+
it from its archived format. Use tab completion to make your life simpler! Or
|
284
|
+
not...
|
285
|
+
|
286
|
+
ari: ~/src/chitin % tar.zxf "rosys_stuff.tar.gz"
|
287
|
+
|
288
|
+
Easy there, cowboy. You have no idea what Rosy the Asshole just sent you.
|
289
|
+
Let's try it again except THIS time, use the "v" flag for "tar".
|
290
|
+
|
291
|
+
ari: ~/src/chitin % rm -:rf, "rosys_stuff
|
292
|
+
ari: ~/src/chitin % tar.zxvf "rosys_stuff.tar.gz"
|
293
|
+
|
294
|
+
So here we learned a few things about Chitin and how it plays well with 40
|
295
|
+
fucking years of bash-style syntax and history. Most obviously, -:rf takes
|
296
|
+
a symbol and translates it into '-rf'. These three are all equal:
|
297
|
+
|
298
|
+
-:rf == -'rf' == '-rf'
|
299
|
+
|
300
|
+
You want two dashes? Sweet deal brah.
|
301
|
+
|
302
|
+
--:rf == --'rf == -'-rf' == '--rf'
|
303
|
+
|
304
|
+
Next in the commands, we use tar. But we don't just run tar. We run tar.zxvf.
|
305
|
+
tar refers to the command itself, and then calling any methods on it send the
|
306
|
+
method name directly to the executable. Thus, 'tar.zxvf' becomes 'tar zxvf'. We
|
307
|
+
do this here because tar does NOT want any dashes.
|
308
|
+
|
309
|
+
So back to the installation process:
|
310
|
+
|
311
|
+
ari: ~/src/chitin % here 'configure', :prefix => '/Users/ari/local'
|
312
|
+
ari: ~/src/chitin % make & make.install
|
313
|
+
|
314
|
+
`here` is the method we use to refer to an executable file relative to the
|
315
|
+
current directory. We're using hash notation in configure to automatically
|
316
|
+
prepend two dashes to 'prefix' ('--prefix'); the whole line is translated
|
317
|
+
as "./configure --prefix /Users/ari/local". We're also using the #& operator
|
318
|
+
to do each command only if the previous one succeeds.
|
319
|
+
|
320
|
+
In lieu of using `here`, which can understandably get a little tedious, we
|
321
|
+
can do two other things:
|
322
|
+
|
323
|
+
ari: ~/src/chitin % raw_exec 'configure', :prefix => '/Users/ari/local
|
324
|
+
|
325
|
+
And if you didn't want to include any arguments:
|
326
|
+
|
327
|
+
ari: ~/src/chitin % '.'/'configure'
|
328
|
+
|
329
|
+
For the second one using String#/, it can't take any arguments because
|
330
|
+
otherwise it wouldn't be valid Ruby. I'm still trying to figure out a better
|
331
|
+
way to make use of it.
|
332
|
+
|
333
|
+
So now that we have this all, let's try archiving it all up again.
|
334
|
+
|
335
|
+
ari: ~/src/chitin % tar.zcf 'compiled.tar.gz' => 'rosys_stuff'
|
336
|
+
|
337
|
+
Much better.
|
338
|
+
|
339
|
+
== Color Guard: Working with Flags
|
340
|
+
|
341
|
+
Here's a quick synopsis of flag equivalencies from bash-style flags to Chitin.
|
342
|
+
The first on the left is the bash, and everything else is Chitin:
|
343
|
+
|
344
|
+
-h == -:h == -'h' == '-h'
|
345
|
+
-f file == :f => file
|
346
|
+
-help == -:help == -'help' == '-help'
|
347
|
+
--d == --:h == --'h' == '--h'
|
348
|
+
--pref file == :pref => file
|
349
|
+
|
350
|
+
You should be able to get the idea after that. The important things to note
|
351
|
+
are how hashes are treated. If the key is one character long, it gets one dash.
|
352
|
+
If the key is two or more characters long, it gets two dashes. This makes
|
353
|
+
dealing with Java programs really fucking annoying.
|
354
|
+
|
355
|
+
== String Methods
|
356
|
+
|
357
|
+
One of the points of using Ruby in a shell is that you can use Ruby. For
|
358
|
+
instance:
|
359
|
+
|
360
|
+
ari: ~/src/chitin % ll | split("\n")
|
361
|
+
|
362
|
+
However, what if there's an executable on your path entitled "split"? Then
|
363
|
+
the executable would be the one to be run. However, I really, really, really
|
364
|
+
want to use a few String methods such as #gsub and #split regardless of whether
|
365
|
+
there is an executable named as such. So, there's the Kernel::string_method
|
366
|
+
function that takes a string method and makes it a PRIORITY method. This means
|
367
|
+
that the Ruby method will take precedence over any executables found.
|
368
|
+
|
369
|
+
The string methods which take precedence over executables are:
|
370
|
+
|
371
|
+
gsub
|
372
|
+
split
|
373
|
+
size
|
374
|
+
pack
|
375
|
+
unpack
|
376
|
+
|
377
|
+
== Globbing: Globins and Hobglobins
|
378
|
+
|
379
|
+
Globbing is simple in Chitin: there is none. However, that's ok because
|
380
|
+
globbing is a really really cheap hack. So here's what Chitin offers in its
|
381
|
+
stead:
|
382
|
+
|
383
|
+
ari: ~/src/chitin % D('.').map {|f| echo f } # D stands for Directory
|
384
|
+
ari: ~/src/chitin % all.map {|f| echo f } # all is an alias to D('.')
|
385
|
+
ari: ~/src/chitin % echo *all # Ruby's natural glob!
|
386
|
+
|
387
|
+
Now, all and D('.') will only get the files and directories in the current
|
388
|
+
directory. What if you wanted to see just how far the rabbit hole went?
|
389
|
+
|
390
|
+
ari: ~/src/chitin % all.down.map {|f| echo f }
|
391
|
+
ari: ~/src/chitin % echo *all.down
|
392
|
+
|
393
|
+
#down will go from the directory it's called on allllll the way down to
|
394
|
+
Davey Jones' locker.
|
395
|
+
|
396
|
+
== Kewl Features
|
397
|
+
|
398
|
+
Did you know?
|
399
|
+
|
400
|
+
* A FULL RUBY INTERPRETER!
|
401
|
+
* Tab completion that respects spaces in strings!
|
402
|
+
* Bashes' ESC-. to place the last argument!
|
403
|
+
* Syntax highlighting as you type!
|
404
|
+
* ^q quotes the word just behind your cursor
|
405
|
+
* I think this train might ACTUALLY get to Chicago on time!
|
406
|
+
|
407
|
+
== Bugs
|
408
|
+
|
409
|
+
Coolline deletes and reprints the line with every character you type. This is
|
410
|
+
great! We like this because it means we get syntax highlighting as we type.
|
411
|
+
We don't like this, however, because it means that if a program prints output
|
412
|
+
without a trailing newline, the last line of the output will be cut off by
|
413
|
+
chitin as soon as you start typing :(
|
414
|
+
|
data/TODO
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
FUTURE:
|
2
|
+
* add STDERR support
|
3
|
+
* fix it so that self.err isn't alone in the whole `if self.err` bit.
|
4
|
+
* set local variables in config, have them appear in shell
|
5
|
+
* getting the menu to NOT have leading quotes
|
6
|
+
* remove/edit history
|
7
|
+
-> important for removing passwords if accidentally typed
|
8
|
+
* 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
|
13
|
+
|
14
|
+
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
|
+
|
26
|
+
Questions:
|
27
|
+
* Why do you have to do @line = '' in Coolline in order to not affect the
|
28
|
+
history? History calls el.dup which creates a new object. It shouldn't
|
29
|
+
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?
|
32
|
+
|
data/bin/chitin
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# fuck, this isn't my method. i don't know where i got it. please don't hate me!
|
4
|
+
def follow_link(file)
|
5
|
+
file = File.expand_path(file)
|
6
|
+
while File.symlink?(file)
|
7
|
+
file = File.expand_path(File.readlink(file), File.dirname(file))
|
8
|
+
end
|
9
|
+
file
|
10
|
+
end
|
11
|
+
|
12
|
+
require File.join(File.dirname(follow_link(__FILE__)), "..", "lib", "chitin")
|
13
|
+
|
14
|
+
FileUtils
|
15
|
+
if ARGV[0]
|
16
|
+
rc = ARGV[0]
|
17
|
+
else
|
18
|
+
FileUtils.touch File.expand_path('~/.chitinrc')
|
19
|
+
rc = File.expand_path('~/.chitinrc')
|
20
|
+
end
|
21
|
+
|
22
|
+
Chitin::Builtins.class_eval File.read(rc)
|
23
|
+
|
24
|
+
SESSION = Chitin::Session.new Chitin::Builtins
|
25
|
+
SESSION.start
|
26
|
+
|
data/chitin.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "chitin/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
# Metadata
|
6
|
+
s.name = "chitin"
|
7
|
+
s.version = Chitin::VERSION
|
8
|
+
s.authors = ["Ari Brown"]
|
9
|
+
s.email = ["ari@aribrown.com"]
|
10
|
+
s.homepage = "http://bitbucket.org/seydar/chitin"
|
11
|
+
s.summary = %q{A shell! In Ruby!}
|
12
|
+
s.description = <<DESC
|
13
|
+
The point of Chitin is that you should be able to use Ruby in your shell. Bash
|
14
|
+
is too old. Time for the new wave of shell environments.
|
15
|
+
DESC
|
16
|
+
|
17
|
+
s.rubyforge_project = "chitin"
|
18
|
+
|
19
|
+
# Manifest
|
20
|
+
s.files = `hg manifest`.split("\n")
|
21
|
+
s.executables = ["chitin"]
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
# Dependencies
|
25
|
+
# specify any dependencies here; for example:
|
26
|
+
# s.add_development_dependency "rspec"
|
27
|
+
s.add_runtime_dependency "wirble"
|
28
|
+
s.add_runtime_dependency "coolline"
|
29
|
+
s.add_runtime_dependency "coderay"
|
30
|
+
end
|
31
|
+
|
data/chitinrc
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
###########################
|
2
|
+
# Place this in ~/.chitinrc
|
3
|
+
# This is mine. Feel free to screw with this as you please.
|
4
|
+
# - Ari Brown
|
5
|
+
###########################
|
6
|
+
include Math
|
7
|
+
|
8
|
+
module Aliases
|
9
|
+
def src; cd "#{ENV['HOME']}/src"; end
|
10
|
+
def school; cd "/Users/ari/School/Fall '11/"; end
|
11
|
+
def idea; vim '/Users/ari/src/IDEAS'; end
|
12
|
+
def ideas; less '/Users/ari/src/IDEAS'; end
|
13
|
+
def vpython(*args)
|
14
|
+
Executable.new '/Library/Frameworks/Python.framework/Versions/2.7/bin/python', *args
|
15
|
+
end
|
16
|
+
def fixit; vim '/Users/ari/.chitinrc'; end
|
17
|
+
def ouvrez(*args)
|
18
|
+
Executable.new '/usr/bin/open', *args
|
19
|
+
end
|
20
|
+
end
|
21
|
+
include Aliases
|
22
|
+
|
23
|
+
def normal_prompt
|
24
|
+
"#{ENV['USER'].cyan}: #{short_pwd.yellow} (... "
|
25
|
+
end
|
26
|
+
|
27
|
+
def prompt
|
28
|
+
normal_prompt
|
29
|
+
end
|
30
|
+
|
31
|
+
def relax
|
32
|
+
def prompt
|
33
|
+
normal_prompt
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def focus(string)
|
38
|
+
@todo = string
|
39
|
+
def prompt
|
40
|
+
@todo = @todo.to_s
|
41
|
+
"[ #{@todo.red} #{'-' * (`tput cols`.to_i - 4 - @todo.red.size)}]\n" +
|
42
|
+
"[ #{short_pwd.light_cyan} ] "
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
pre_process do |val|
|
47
|
+
val = val.strip == '.' ? 'exit' : val
|
48
|
+
val = val.strip == '..' ? 'cd ".."' : val
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sample usage of pre_process and post_process.
|
52
|
+
# This is taken from the lib/chitin/commands/builtins.rb
|
53
|
+
#
|
54
|
+
# pre_process do |val|
|
55
|
+
# # if there is an unclosed string, close it and run it again.
|
56
|
+
# # smart compilers are bad... but this ain't a compiler
|
57
|
+
# #
|
58
|
+
# # option: make it ask for confirmation first
|
59
|
+
# # settable in chitinrc, perjaps?
|
60
|
+
# if (e = syntax_error_for(val)) &&
|
61
|
+
# e.message =~ /unterminated string meets end of file/
|
62
|
+
#
|
63
|
+
# if syntax_error_for(val + '\'')
|
64
|
+
# unless syntax_error_for(val + '"')
|
65
|
+
# val << '"'
|
66
|
+
# end
|
67
|
+
# else
|
68
|
+
# val << '\''
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# val
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# # You can use error classes as a name and if the error comes up,
|
77
|
+
# # block of code will be run.
|
78
|
+
# #
|
79
|
+
# # post_process SyntaxError do |e, val|
|
80
|
+
# # # sample
|
81
|
+
# # end
|
82
|
+
#
|
83
|
+
# post_process :color do |val|
|
84
|
+
# Wirble::Colorize.colorize val
|
85
|
+
# end
|
86
|
+
|