cheat 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+