cheat 1.0.2

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.
Files changed (8) hide show
  1. data/LICENSE +18 -0
  2. data/README +16 -0
  3. data/bin/cheat +4 -0
  4. data/lib/cheat.rb +70 -0
  5. data/lib/site.rb +512 -0
  6. data/lib/wrap.rb +42 -0
  7. data/test/test_cheat.rb +50 -0
  8. metadata +53 -0
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2006 Chris Wanstrath
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,16 @@
1
+ == Cheat
2
+
3
+ Cheat is a simple command line reference utility. Use it to retrieve handy
4
+ information from the cheat sheet repository.
5
+
6
+ $ cheat sheets
7
+ $ cheat cheat
8
+ $ cheat recent
9
+
10
+ The Cheat Sheet Repository:
11
+ - http://cheat.errtheblog.com/
12
+
13
+ Enjoy.
14
+
15
+ >> Chris Wanstrath
16
+ => chris[at]ozmm[dot]org
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'cheat'
4
+ Cheat.sheets(ARGV)
@@ -0,0 +1,70 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ %w[rubygems fileutils net/http yaml open-uri wrap].each { |f| require f }
3
+
4
+ module Cheat
5
+ extend self
6
+
7
+ HOST = 'cheat.errtheblog.com'
8
+ PORT = 80
9
+ SUFFIX = ''
10
+
11
+ def sheets(args)
12
+ args = args.dup
13
+
14
+ return puts("Looking for help? Try http://cheat.errtheblog.com or `$ cheat cheat'") if args.empty?
15
+
16
+ if (i = args.index('--clear-cache') || i = args.index('--new'))
17
+ args.delete_at(i)
18
+ clear_cache
19
+ return if args.empty?
20
+ end
21
+
22
+ sheet = args.shift
23
+
24
+ cache_file = "#{cache_dir}/#{sheet}.yml" if cache_dir
25
+ FileUtils.mkdir(cache_dir) unless File.exists?(cache_dir) if cache_dir
26
+
27
+ host = HOST + ':' + PORT.to_s + SUFFIX
28
+ uri = "http://#{host}/y/"
29
+
30
+ if %w[sheets all recent].include? sheet
31
+ uri = uri.sub('/y/', sheet == 'recent' ? '/yr/' : '/ya/')
32
+ return open(uri) { |body| show(body.read) }
33
+ end
34
+
35
+ return show(File.read(cache_file)) if File.exists?(cache_file) rescue clear_cache if cache_file
36
+
37
+ open(uri += sheet) do |body|
38
+ sheet = body.read
39
+ File.open(cache_file, 'w') { |f| f.write(sheet) } if cache_file
40
+ show(sheet)
41
+ end
42
+ end
43
+
44
+ def show(sheet_yaml)
45
+ sheet = YAML.load(sheet_yaml).to_a.first
46
+ sheet[-1] = sheet.last.join("\n") if sheet[-1].is_a?(Array)
47
+ puts sheet.first + ':'
48
+ puts ' ' + sheet.last.gsub("\r",'').gsub("\n", "\n ").wrap(80)
49
+ end
50
+
51
+ def cache_dir
52
+ PLATFORM =~ /win32/ ? win32_cache_dir : File.join(File.expand_path("~"), ".cheat")
53
+ end
54
+
55
+ def win32_cache_dir
56
+ unless File.exists?(home = ENV['HOMEDRIVE'] + ENV['HOMEPATH'])
57
+ puts "No HOMEDRIVE or HOMEPATH environment variable. Set one to save a" +
58
+ "local cache of cheat sheets."
59
+ return false
60
+ else
61
+ return File.join(home, 'Cheat')
62
+ end
63
+ end
64
+
65
+ def clear_cache
66
+ FileUtils.rm_rf(cache_dir) if cache_dir
67
+ end
68
+ end
69
+
70
+ Cheat.sheets(ARGV) if __FILE__ == $0
@@ -0,0 +1,512 @@
1
+ #
2
+ # According to Wikipedia, Cheat can refer to:
3
+ # Cheating, to take advantage of a situation by the breaking of accepted rules
4
+ # or standards
5
+ # Cheating (casino)
6
+ # Cheating in poker
7
+ # Cheating in online games
8
+ # In relationships, to have an affair
9
+ # A cheat code, a hidden means of gaining an advantage in a video game
10
+ # Cheating, parasitic abuse of symbiotic relationships
11
+ # The Cheat, a character in the cartoon series Homestar Runner
12
+ # Cheat!, a television show on the G4 network
13
+ # The Cheat, a 1915 Cecil B. DeMille movie about a wealthy and domineering
14
+ # Asian gentleman taking advantage of an American female
15
+ # Cheats, a 2002 comedy, starring Matthew Lawrence and Mary Tyler Moore
16
+ # Cheat, a song by The Clash from the UK version of their album The Clash
17
+ # Bullshit, sometimes known as "Cheat," a card game
18
+ # An alternate term for defection in the prisoner's dilemma in game theory
19
+ # Cheat River, a tributary of the Monongahela River in Appalachia; the Cheat
20
+ # starts in West Virginia, and flows westward
21
+ # Cheat Lake, a nearby resevoir
22
+ # Cheat Mountain, one of the highest mountains in the Alleghenies
23
+ #
24
+ %w[rubygems camping camping/db erb acts_as_versioned wrap].each { |f| require f }
25
+ require_gem 'camping', '>=1.4.152'
26
+
27
+ Camping.goes :Cheat
28
+
29
+ URL = 'http://cheat.errtheblog.com' # need this to get around exposing :port in redirects
30
+ FEED = 'http://feeds.feedburner.com/cheatsheets' # rss feed
31
+
32
+ module Cheat::Models
33
+ class Sheet < Base
34
+ validates_uniqueness_of :title
35
+ validates_format_of :title, :with => /^[a-z]+[a-z0-9_]*$/i
36
+ validates_presence_of :title, :body
37
+ before_save { |r| r.title = r.title.gsub(' ', '_').underscore.downcase }
38
+ acts_as_versioned
39
+ end
40
+
41
+ class SetUpUsTheCheat < V 1.0
42
+ def self.up
43
+ create_table :cheat_sheets, :force => true do |t|
44
+ t.column :id, :integer, :null => false
45
+ t.column :title, :string, :null => false
46
+ t.column :body, :text
47
+ t.column :created_at, :datetime, :null => false
48
+ t.column :updated_at, :datetime, :null => false
49
+ end
50
+ Sheet.create_versioned_table
51
+ Sheet.reset_column_information
52
+ end
53
+ def self.down
54
+ drop_table :cheat_sheets
55
+ Sheet.drop_versioned_table
56
+ end
57
+ end
58
+ end
59
+
60
+ module Cheat::Controllers
61
+ class APIShow < R '/y/(\w+)'
62
+ def get(title)
63
+ @headers['Content-Type'] = 'text/plain'
64
+
65
+ sheet = Sheet.find_by_title(title)
66
+ return { 'Error!' => "Cheat sheet `#{title}' not found." }.to_yaml unless sheet
67
+
68
+ return { sheet.title => sheet.body }.to_yaml
69
+ end
70
+ end
71
+
72
+ class APIRecent < R '/yr'
73
+ def get
74
+ @headers['Content-Type'] = 'text/plain'
75
+
76
+ fake = Class.new.send(:include, Cheat::Helpers).new
77
+ return { 'Recent Cheat Sheets' => fake.recent_sheets.map(&:title) }.to_yaml
78
+ end
79
+ end
80
+
81
+ class APIAll < R '/ya'
82
+ def get
83
+ @headers['Content-Type'] = 'text/plain'
84
+
85
+ return { 'All Cheat Sheets' => Sheet.find(:all, :order => 'title ASC').map(&:title) }.to_yaml
86
+ end
87
+ end
88
+
89
+ class Feed < R '/f'
90
+ def get
91
+ @headers['Content-Type'] = 'application/xml'
92
+ return Cheat::Views.feed
93
+ end
94
+ end
95
+
96
+ class Index < R '/'
97
+ def get
98
+ render :index
99
+ end
100
+ end
101
+
102
+ class Add < R '/a'
103
+ def get
104
+ @sheet = Sheet.new
105
+ render :add
106
+ end
107
+ end
108
+
109
+ class Revert < R '/r/(\w+)/(\d+)'
110
+ def get(title, version)
111
+ current = Sheet.find_by_title(title)
112
+ old = current.find_version(version)
113
+ current.title, current.body = old.title, old.body
114
+ current.save
115
+ redirect "#{URL}/s/#{title}"
116
+ end
117
+ end
118
+
119
+ class Edit < R '/e/(\w+)/(\d+)', '/e/(\w+)'
120
+ def get(title, version = nil)
121
+ @sheet = Sheet.find_by_title(title)
122
+ unless @sheet
123
+ @error = "Cheat sheet not found."
124
+ return render(:error)
125
+ end
126
+ unless version.nil? || version == @sheet.version.to_s
127
+ @sheet = @sheet.find_version(version)
128
+ end
129
+ render :edit
130
+ end
131
+ end
132
+
133
+ class Write < R '/w', '/w/(\w+)'
134
+ def post(title = nil)
135
+ @sheet = title ? Sheet.find_by_title(title) : Sheet.new
136
+
137
+ @error = input.sheet_body =~ /<a\s*href=/
138
+
139
+ if !@error && @sheet.update_attributes(:title => input.sheet_title,
140
+ :body => input.sheet_body)
141
+ redirect "#{URL}/s/#{@sheet.title}"
142
+ else
143
+ @error = true
144
+ render title ? :edit : :add
145
+ end
146
+ end
147
+ end
148
+
149
+ class Browse < R '/b'
150
+ def get
151
+ @sheets = Sheet.find(:all, :order => 'created_at DESC')
152
+ render :browse
153
+ end
154
+ end
155
+
156
+ class Show < R '/s/(\w+)', '/s/(\w+)/(\d+)'
157
+ def get(title, version = nil)
158
+ @sheet = Sheet.find_by_title(title)
159
+ @sheet = @sheet.find_version(version) if version && @sheet
160
+ if @sheet
161
+ render :show
162
+ else
163
+ redirect "#{URL}/b/"
164
+ end
165
+ end
166
+ end
167
+
168
+ class History < R '/h/(\w+)'
169
+ def get(title)
170
+ @sheets = Sheet.find_by_title(title).find_versions(:order => 'version DESC')
171
+ render :history
172
+ end
173
+ end
174
+ end
175
+
176
+ module Cheat::Views
177
+ def layout
178
+ html {
179
+ head {
180
+ _style
181
+ link :href => FEED, :rel => "alternate", :title => "Recent Cheat Sheets", :type => "application/atom+xml"
182
+ title defined?(@page_title) ? "$ cheat #{@page_title}" : \
183
+ "$ command line ruby cheat sheets"
184
+ }
185
+ body {
186
+ #code "Hi this is defunkt. I'm messing around right now (8-9pm pst). Things will get normal soon. thx."
187
+ div.main {
188
+ div.header {
189
+ h1 { logo_link 'cheat sheets.' }
190
+ code.header defined?(@sheet_title) ? "$ cheat #{@sheet_title}" : \
191
+ "$ command line ruby cheat sheets"
192
+ }
193
+ div.content { self << yield }
194
+ div.side { _side }
195
+ div.clear { '' }
196
+ div.footer { _footer }
197
+ }
198
+ }
199
+ }
200
+ end
201
+
202
+ def error
203
+ @page_title = "error"
204
+ p "An error:"
205
+ code.version @error
206
+ p ":("
207
+ end
208
+
209
+ def show
210
+ @page_title = @sheet.title
211
+ @sheet_title = @sheet.title
212
+ #div.sheet { text h(sheet.body).gsub(/\n(\s+)/, '<br/>' + '&nbsp;' * '\1'.size).gsub(/\r/,'').gsub(/\n/,'<br/>') }
213
+ pre.sheet { text h(sheet.body.wrap(80)) }
214
+ div.version {
215
+ text "Version "
216
+ strong sheet.version
217
+ text ", updated "
218
+ text last_updated(@sheet)
219
+ text " ago. "
220
+ br
221
+ text ". o 0 ( "
222
+ a "edit", :href => R(Edit, @sheet.title)
223
+ if @sheet.version > 1
224
+ text " | "
225
+ a "previous", :href => R(Show, @sheet.title, @sheet.version - 1)
226
+ text " | "
227
+ a "history", :href => R(History, @sheet.title)
228
+ end
229
+ if @sheet.version != (current = current_sheet).version
230
+ text " | "
231
+ a "revert to", :href => R(Revert, @sheet.title, @sheet.version)
232
+ text " | "
233
+ a "current", :href => R(Show, @sheet.title, current.version)
234
+ end
235
+ text " )"
236
+ }
237
+ end
238
+
239
+ def browse
240
+ @page_title = "browse"
241
+ ul {
242
+ @sheets.each do |sheet|
243
+ li { sheet_link sheet.title }
244
+ end
245
+ }
246
+ p {
247
+ text "Are we missing a cheat sheet? Why don't you do the whole world a favor and "
248
+ a "add it", :href => R(Add)
249
+ text " yourself!"
250
+ }
251
+ end
252
+
253
+ def history
254
+ @page_title = "history"
255
+ @sheet_title = @sheets.first.title
256
+ h2 @sheets.first.title
257
+ ul {
258
+ @sheets.each_with_index do |sheet, i|
259
+ li {
260
+ a "version #{sheet.version}", :href => R(Show, sheet.title, sheet.version)
261
+ text " - created "
262
+ text last_updated(sheet)
263
+ text " ago"
264
+ strong " (current)" if i == 0
265
+ }
266
+ end
267
+ }
268
+ end
269
+
270
+ def add
271
+ @page_title = "add"
272
+ p {
273
+ text "Thanks for wanting to add a cheat sheet. If you need an example of
274
+ the standard cheat sheet format, check out the "
275
+ a "cheat", :href => R(Show, 'cheat')
276
+ text " cheat sheet. (There's really no standard format, though)."
277
+ }
278
+ _form
279
+ end
280
+
281
+ def edit
282
+ @page_title = "edit"
283
+ _form
284
+ end
285
+
286
+ def _form
287
+ if (@error = @error)
288
+ p.error {
289
+ strong "HEY! "
290
+ text "Something is wrong! You can't give your cheat sheet the same name
291
+ as another, alphanumeric titles only, and you need to make sure
292
+ you filled in all (two) of the fields. Okay?"
293
+ }
294
+ end
295
+ form :method => 'post', :action => R(Write, @sheet.title) do
296
+ p {
297
+ p {
298
+ text 'Cheat Sheet Title: '
299
+ input :value => @sheet.title, :name => 'sheet_title', :size => 30,
300
+ :type => 'text'
301
+ small " [ no_spaces_alphanumeric_only ]"
302
+ }
303
+ p {
304
+ text 'Cheat Sheet:'
305
+ br
306
+ textarea @sheet.body, :name => 'sheet_body', :cols => 80, :rows => 30
307
+ }
308
+ }
309
+ p "Your cheat sheet will be editable (fixable) by anyone. Each cheat
310
+ sheet is essentially a wiki page. It may also be used by millions of
311
+ people for reference purposes from the comfort of their command line.
312
+ If this is okay with you, please save."
313
+ input :value => "Save the Damn Thing!", :name => "save", :type => 'submit'
314
+ end
315
+ end
316
+
317
+ def index
318
+ p {
319
+ text "Welcome. You've reached the central repository for "
320
+ strong "cheat"
321
+ text ", the RubyGem which puts Ruby-centric cheat sheets right into your
322
+ terminal. The inaugural blog entry "
323
+ a "is here", :href => "http://errtheblog.com/post/23"
324
+ text "."
325
+ }
326
+ p "Get started:"
327
+ code "$ sudo gem install cheat --source require.errtheblog.com"
328
+ br
329
+ code "$ cheat strftime"
330
+ p "A magnificent cheat sheet for Ruby's strftime method will be printed to
331
+ your terminal."
332
+ p "To get some help on cheat itself:"
333
+ code "$ cheat cheat"
334
+ p "How meta."
335
+ p {
336
+ text "Cheat sheets are basically wiki pages accessible from the command
337
+ line. You can "
338
+ a 'browse', :href => R(Browse)
339
+ text ', '
340
+ a 'add', :href => R(Add)
341
+ text ', or '
342
+ a 'edit', :href => R(Edit, 'cheat')
343
+ text ' cheat sheets. Try to keep them concise. For a style guide, check
344
+ out the '
345
+ a 'cheat', :href => R(Edit, 'cheat')
346
+ text ' cheat sheet.'
347
+ }
348
+ p "To access a cheat sheet, simply pass the program the desired sheet's
349
+ name:"
350
+ code "$ cheat <sheet name>"
351
+ p
352
+ end
353
+
354
+ def self.feed
355
+ xml = Builder::XmlMarkup.new(:indent => 2)
356
+
357
+ xml.instruct!
358
+ xml.feed "xmlns"=>"http://www.w3.org/2005/Atom" do
359
+
360
+ xml.title "Recent Cheat Sheets"
361
+ xml.id URL + '/'
362
+ xml.link "rel" => "self", "href" => FEED
363
+
364
+ sheets = Cheat::Models::Sheet.find(:all, :order => 'created_at DESC', :limit => 30)
365
+ xml.updated sheets.first.created_at.xmlschema
366
+
367
+ sheets.each do |sheet|
368
+ xml.entry do
369
+ xml.id URL + '/s/' + sheet.title
370
+ xml.title sheet.title
371
+ xml.author { xml.name "An Anonymous Cheater" }
372
+ xml.updated sheet.updated_at.xmlschema
373
+ xml.link "rel" => "alternate", "href" => URL + '/s/' + sheet.title
374
+ xml.summary "A cheat sheet about #{sheet.title}. Run it: `$ cheat #{sheet.title}'"
375
+ end
376
+ end
377
+ end
378
+ end
379
+
380
+ def _side
381
+ text '( '
382
+ a 'add', :href => R(Add)
383
+ text ' | '
384
+ a 'browse', :href => R(Browse)
385
+ text ' )'
386
+ ul {
387
+ li { strong "recent cheat sheets" }
388
+ li do
389
+ a :href => FEED do
390
+ img(:alt => "Recent Cheat Sheets Feed", :src => "http://errtheblog.com/images/theme/feed.png")
391
+ end
392
+ end
393
+ recent_sheets.each do |sheet|
394
+ li { sheet_link sheet.title }
395
+ end
396
+ }
397
+ end
398
+
399
+ def _footer
400
+ text "Powered by "
401
+ a 'Camping', :href => "http://code.whytheluckystiff.net/camping"
402
+ text ", "
403
+ a 'Mongrel', :href => "http://mongrel.rubyforge.org/"
404
+ text " and, to a lesser extent, "
405
+ a 'Err the Blog', :href => "http://errtheblog.com/"
406
+ text "."
407
+ end
408
+
409
+ def _style
410
+ bg = "#fff"
411
+ h1 = "#4fa3da"
412
+ link = h1
413
+ hover = "#f65077"
414
+ dash = hover
415
+ version = "#fcf095"
416
+ style :type => "text/css" do
417
+ text %{
418
+ body { font-family: verdana, sans-serif; background-color: #{bg};
419
+ line-height: 20px; }
420
+ a:link, a:visited { color: #{link}; }
421
+ a:hover { text-decoration: none; color: #{hover}; }
422
+ div.header { border-bottom: 1px dashed #{dash}; }
423
+ code.header { margin-left: 30px; font-weight: bold;
424
+ background-color: #{version}; }
425
+ h1 { font-size: 5em; margin: 0; padding-left: 30px; color: #{h1};
426
+ clear: both; font-weight: bold; letter-spacing: -5px; }
427
+ div.main { float: left; width: 100%; }
428
+ div.content { float: left; width: 70%; padding: 15px 0 15px 30px;
429
+ line-height: 20px; }
430
+ div.side { float: left; padding: 10px; text-align: right;
431
+ width: 20%; }
432
+ div.footer { text-align: center; border-top: 1px dashed #{dash};
433
+ padding-top: 10px; font-size: small; }
434
+ div.sheet { font-size: .8em; line-height: 17px; padding: 5px;
435
+ font-family: courier, fixed-width; background-color: #e8e8e8; }
436
+ pre.sheet { line-height: 15px; }
437
+ li { list-style: none; }
438
+ div.version { background-color: #{version}; padding: 5px;
439
+ width: 450px; margin-top: 50px; }
440
+ p.error { background-color: #{version}; padding: 5px; }
441
+ div.clear { clear: both; }
442
+ div.clear_10 { clear: both; font-size: 10px; line-height: 10px; }
443
+ textarea { font-family: courier; }
444
+ code { background-color: #{version} }
445
+ }.gsub(/(\s{2,})/, '').gsub("\n", '')
446
+ end
447
+ end
448
+ end
449
+
450
+ module Cheat::Helpers
451
+ def logo_link(title)
452
+ ctr = Cheat::Controllers
453
+ if @sheet && !@sheet.new_record? && @sheet.version != current_sheet.version
454
+ a title, :href => R(ctr::Show, @sheet.title, current_sheet.version)
455
+ else
456
+ a title, :href => R(ctr::Index)
457
+ end
458
+ end
459
+
460
+ def current_sheet
461
+ @current_sheet ||= Cheat::Models::Sheet.find_by_title(@sheet.title)
462
+ end
463
+
464
+ def recent_sheets
465
+ Cheat::Models::Sheet.find(:all, :order => 'created_at DESC', :limit => 10)
466
+ end
467
+
468
+ def sheet_link(title, version = nil)
469
+ a title, :href => R(Cheat::Controllers::Show, title, version)
470
+ end
471
+
472
+ def last_updated(sheet)
473
+ from = sheet.updated_at.to_i
474
+ to = Time.now.to_i
475
+ from = from.to_time if from.respond_to?(:to_time)
476
+ to = to.to_time if to.respond_to?(:to_time)
477
+ distance = (((to - from).abs)/60).round
478
+ case distance
479
+ when 0..1 : return (distance==0) ? 'less than a minute' : '1 minute'
480
+ when 2..45 : "#{distance} minutes"
481
+ when 46..90 : 'about 1 hour'
482
+ when 90..1440 : "about #{(distance.to_f / 60.0).round} hours"
483
+ when 1441..2880: '1 day'
484
+ else "#{(distance / 1440).round} days"
485
+ end
486
+ end
487
+
488
+ def h(text)
489
+ ERB::Util::h(text)
490
+ end
491
+ end
492
+
493
+ def Cheat.create
494
+ Cheat::Models.create_schema
495
+ end
496
+
497
+ if __FILE__ == $0
498
+ begin
499
+ require 'mongrel/camping'
500
+ rescue LoadError => e
501
+ abort "** Try running `camping #$0' instead."
502
+ end
503
+
504
+ Cheat::Models::Base.establish_connection :adapter => 'mysql', :user => 'root', :database => 'camping', :host => 'localhost'
505
+ Cheat::Models::Base.logger = nil
506
+ Cheat::Models::Base.threaded_connections = false
507
+ Cheat.create
508
+
509
+ server = Mongrel::Camping.start("0.0.0.0", 3001, "/", Cheat)
510
+ puts "** Cheat is running at http://0.0.0.0:3001/"
511
+ server.run.join
512
+ end
@@ -0,0 +1,42 @@
1
+ # >> Evan Weaver
2
+ # => http://blog.evanweaver.com/articles/2006/09/03/smart-plaintext-wrapping
3
+ class String
4
+ def wrap(width, hanging_indent = 0, magic_lists = false)
5
+ lines = self.split(/\n/)
6
+
7
+ lines.collect! do |line|
8
+
9
+ if magic_lists
10
+ line =~ /^([\s\-\d\.\:]*\s)/
11
+ else
12
+ line =~ /^([\s]*\s)/
13
+ end
14
+
15
+ indent = $1.length + hanging_indent rescue hanging_indent
16
+
17
+ buffer = ""
18
+ first = true
19
+
20
+ while line.length > 0
21
+ first ? (i, first = 0, false) : i = indent
22
+ pos = width - i
23
+
24
+ if line.length > pos and line[0..pos] =~ /^(.+)\s/
25
+ subline = $1
26
+ else
27
+ subline = line[0..pos]
28
+ end
29
+ buffer += " " * i + subline + "\n"
30
+ line.tail!(subline.length)
31
+ end
32
+ buffer[0..-2]
33
+ end
34
+
35
+ lines.join("\n")
36
+ end
37
+
38
+ def tail!(pos)
39
+ self[0..pos] = ""
40
+ strip!
41
+ end
42
+ end
@@ -0,0 +1,50 @@
1
+ # eh. one day.
2
+ $:.unshift File.dirname(__FILE__) + "/..:lib"
3
+ require 'test/unit'
4
+ require 'fileutils'
5
+ require 'tempfile'
6
+ require 'cheat'
7
+
8
+ Sheets = Hash.new do |h,k|
9
+ k = k.to_s
10
+ h[k] = YAML.load(File.read("test/fixtures/#{k}.yml")) rescue nil
11
+ end
12
+
13
+ class CheatTest < Test::Unit::TestCase
14
+
15
+ def test_gets_from_host
16
+ end
17
+
18
+ def test_sets_to_cache
19
+ end
20
+
21
+ def test_gets_from_arbitrary_host
22
+ end
23
+
24
+ def test_gracefully_fail_if_host_bunk
25
+ end
26
+
27
+ def test_creates_cache_dir
28
+ end
29
+
30
+ def test_doesnt_create_cache_dir_if_exists
31
+ end
32
+
33
+ def test_loads_from_cache_if_exists
34
+ end
35
+
36
+ def test_gets_section_if_exists
37
+ end
38
+
39
+ def test_displays_everything_on_failed_section_search
40
+ end
41
+
42
+ def test_gets_recent_sheets
43
+ end
44
+
45
+ def test_gets_all_sheets
46
+ end
47
+
48
+ def test_uses_env_for_cache_dir
49
+ end
50
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: cheat
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.2
7
+ date: 2006-09-03 00:00:00 -07:00
8
+ summary: Cheat is a simple command line utility reference program.
9
+ require_paths:
10
+ - lib
11
+ email: chris@ozmm.org
12
+ homepage: http://cheat.errtheblog.com/
13
+ rubyforge_project:
14
+ description: Cheat is a simple command line utility reference program. Use it to, well, cheat.
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Chris Wanstrath
31
+ files:
32
+ - README
33
+ - LICENSE
34
+ - bin/cheat
35
+ - lib/cheat.rb
36
+ - lib/site.rb
37
+ - lib/wrap.rb
38
+ - test/fixtures
39
+ - test/test_cheat.rb
40
+ test_files: []
41
+
42
+ rdoc_options: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ executables:
47
+ - cheat
48
+ extensions: []
49
+
50
+ requirements: []
51
+
52
+ dependencies: []
53
+