wassup 0.1.1 → 0.3.0

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.gitignore +4 -0
  4. data/Gemfile.lock +19 -1
  5. data/README.md +45 -5
  6. data/bin/wassup +6 -1
  7. data/docs/.gitignore +20 -0
  8. data/docs/README.md +41 -0
  9. data/docs/babel.config.js +3 -0
  10. data/docs/blog/2021-12-09-welcome/index.md +8 -0
  11. data/docs/blog/authors.yml +5 -0
  12. data/docs/docs/Supfile-basics/_category_.json +4 -0
  13. data/docs/docs/Supfile-basics/understanding-the-supfile.md +50 -0
  14. data/docs/docs/intro.md +54 -0
  15. data/docs/docusaurus.config.js +110 -0
  16. data/docs/package-lock.json +21196 -0
  17. data/docs/package.json +43 -0
  18. data/docs/sidebars.js +31 -0
  19. data/docs/src/components/HomepageFeatures.module.css +10 -0
  20. data/docs/src/components/HomepageFeatures.tsx +60 -0
  21. data/docs/src/css/custom.css +28 -0
  22. data/docs/src/pages/index.module.css +36 -0
  23. data/docs/src/pages/index.tsx +39 -0
  24. data/docs/src/pages/markdown-page.md +7 -0
  25. data/docs/static/.nojekyll +0 -0
  26. data/docs/static/img/demo-supfile.png +0 -0
  27. data/docs/static/img/favicon.ico +0 -0
  28. data/docs/static/img/logo.svg +27 -0
  29. data/docs/static/img/tutorial/docsVersionDropdown.png +0 -0
  30. data/docs/static/img/tutorial/localeDropdown.png +0 -0
  31. data/docs/static/img/tutorial-intro-starter-screenshot.png +0 -0
  32. data/docs/static/img/undraw_docusaurus_mountain.svg +170 -0
  33. data/docs/static/img/undraw_docusaurus_react.svg +169 -0
  34. data/docs/static/img/undraw_docusaurus_tree.svg +1 -0
  35. data/docs/static/img/wassup-long.png +0 -0
  36. data/docs/static/img/wassup-screenshot.png +0 -0
  37. data/docs/static/img/wassup.png +0 -0
  38. data/docs/static/video/wassup-demo.mov +0 -0
  39. data/docs/tsconfig.json +7 -0
  40. data/examples/basic/Supfile +195 -0
  41. data/examples/debug/Supfile +131 -0
  42. data/examples/josh-fastlane/README.md +14 -0
  43. data/examples/josh-fastlane/Supfile +70 -109
  44. data/examples/josh-fastlane/demo.png +0 -0
  45. data/examples/simple/Supfile +17 -0
  46. data/examples/starter/Supfile +44 -0
  47. data/lib/wassup/app.rb +178 -10
  48. data/lib/wassup/color.rb +81 -0
  49. data/lib/wassup/helpers/circleci.rb +75 -0
  50. data/lib/wassup/helpers/github.rb +137 -0
  51. data/lib/wassup/helpers/netlify.rb +70 -0
  52. data/lib/wassup/helpers/shortcut.rb +114 -0
  53. data/lib/wassup/pane.rb +298 -90
  54. data/lib/wassup/pane_builder.rb +74 -3
  55. data/lib/wassup/version.rb +1 -1
  56. data/lib/wassup.rb +6 -0
  57. data/wassup.gemspec +1 -0
  58. metadata +61 -2
data/lib/wassup/pane.rb CHANGED
@@ -6,11 +6,12 @@ module Wassup
6
6
  class Pane
7
7
  attr_accessor :win
8
8
  attr_accessor :subwin
9
- attr_accessor :data_lines
10
- attr_accessor :data_objects
11
9
  attr_accessor :top
12
10
 
11
+ attr_accessor :contents
12
+
13
13
  attr_accessor :title
14
+ attr_accessor :description
14
15
 
15
16
  attr_accessor :focused
16
17
  attr_accessor :focus_number
@@ -27,21 +28,53 @@ module Wassup
27
28
  attr_accessor :interval
28
29
  attr_accessor :last_refreshed
29
30
  attr_accessor :content_block
30
- attr_accessor :selection_block
31
+ attr_accessor :selection_blocks
32
+ attr_accessor :selection_blocks_description
33
+
34
+ attr_accessor :caught_error
35
+
36
+ attr_accessor :content_thread
37
+ attr_accessor :show_refresh
31
38
 
32
39
  attr_accessor :selected_view_index
33
- attr_accessor :all_view_data_objects
34
40
 
35
41
  attr_accessor :win_height, :win_width, :win_top, :win_left
36
42
 
37
- def initialize(height, width, top, left, title: nil, highlight: true, focus_number: nil, interval:, content_block:, selection_block:)
38
- self.win_height = Curses.lines * height
39
- self.win_width = Curses.cols * width
40
- self.win_top = Curses.lines * top
41
- self.win_left = Curses.cols * left
43
+ class Content
44
+ class Row
45
+ attr_accessor :display
46
+ attr_accessor :object
42
47
 
43
- self.win = Curses::Window.new(self.win_height, self.win_width, self.win_top, self.win_left)
44
- self.setup_subwin()
48
+ def initialize(display, object)
49
+ @display = display
50
+ @object = object || display
51
+ end
52
+ end
53
+
54
+ attr_accessor :title
55
+ attr_accessor :data
56
+
57
+ def initialize(title = nil)
58
+ @title = title
59
+ @data = []
60
+ end
61
+
62
+ def add_row(display, object = nil)
63
+ @data << Row.new(display, object)
64
+ end
65
+ end
66
+
67
+ def initialize(height, width, top, left, title: nil, description: nil, highlight: true, focus_number: nil, interval:, show_refresh:, content_block:, selection_blocks:, selection_blocks_description:, debug: false)
68
+
69
+ if !debug
70
+ self.win_height = Curses.lines * height
71
+ self.win_width = Curses.cols * width
72
+ self.win_top = Curses.lines * top
73
+ self.win_left = Curses.cols * left
74
+
75
+ self.win = Curses::Window.new(self.win_height, self.win_width, self.win_top, self.win_left)
76
+ self.setup_subwin()
77
+ end
45
78
 
46
79
  self.focused = false
47
80
  self.focus_number = focus_number
@@ -50,20 +83,24 @@ module Wassup
50
83
  self.virtual_scroll = true
51
84
 
52
85
  self.top = 0
53
- self.data_lines = []
54
- self.data_objects = []
86
+
87
+ self.contents = []
88
+ self.show_refresh = show_refresh
55
89
 
56
90
  self.selected_view_index = 0
57
- self.all_view_data_objects = [] # Array of array
58
91
 
59
- self.win.refresh
60
- self.subwin.refresh
92
+ if !debug
93
+ self.win.refresh
94
+ self.subwin.refresh
95
+ end
61
96
 
62
97
  self.title = title
98
+ self.description = description
63
99
 
64
100
  self.interval = interval
65
101
  self.content_block = content_block
66
- self.selection_block = selection_block
102
+ self.selection_blocks = selection_blocks || {}
103
+ self.selection_blocks_description = selection_blocks_description || {}
67
104
  end
68
105
 
69
106
  def setup_subwin
@@ -75,16 +112,16 @@ module Wassup
75
112
  self.subwin = nil
76
113
  end
77
114
 
78
- if (@all_view_data_objects || []).size > 1
115
+ if (self.contents || []).size > 1
79
116
  top_bump = 4
80
117
 
81
- view_title = (self.all_view_data_objects[self.selected_view_index] || {})[:title]
118
+ view_title = self.contents[self.selected_view_index].title || "<No Title>"
82
119
  view_title += " " * 100
83
120
 
84
121
  self.win.setpos(2, 2)
85
122
  self.win.addstr(view_title[0...self.win.maxx()-3])
86
123
 
87
- subtitle = "(#{self.selected_view_index + 1} out of #{self.all_view_data_objects.size})"
124
+ subtitle = "(#{self.selected_view_index + 1} out of #{self.contents.size})"
88
125
  subtitle += " " * 100
89
126
  self.win.setpos(3, 2)
90
127
  self.win.addstr(subtitle[0...self.win.maxx()-3])
@@ -104,6 +141,16 @@ module Wassup
104
141
  self.subwin.scrollok(true)
105
142
  end
106
143
 
144
+ def close
145
+ unless self.subwin.nil?
146
+ self.subwin.clear
147
+ self.subwin.close
148
+ end
149
+
150
+ self.win.clear
151
+ self.win.close
152
+ end
153
+
107
154
  def needs_refresh?
108
155
  return false if self.content_block.nil?
109
156
  return false if self.interval.nil?
@@ -111,61 +158,179 @@ module Wassup
111
158
  return Time.now - self.interval > self.last_refreshed
112
159
  end
113
160
 
114
- def refresh
115
- return unless needs_refresh?
161
+ class Ope
162
+ attr_accessor :error
163
+ def initialize(error)
164
+ @error = error
165
+ end
166
+ end
167
+
168
+ def data_lines
169
+ return [] if self.selected_view_index.nil?
170
+ content = (self.contents || [])[self.selected_view_index]
171
+
172
+ if content.nil?
173
+ return []
174
+ else
175
+ content.data.map(&:display)
176
+ end
177
+ end
178
+
179
+ def refreshing?
180
+ return !self.content_thread.nil?
181
+ end
116
182
 
117
- content = self.content_block.call()
183
+ def redraw
184
+ self.update_box
185
+ self.update_title
186
+ self.load_current_view()
187
+ end
118
188
 
119
- return unless content.is_a?(Array)
120
- return if content.first.nil?
189
+ def refresh(force: false)
190
+ if force
191
+ self.last_refreshed = nil
192
+ end
193
+
194
+ if !needs_refresh?
195
+ return
196
+ end
121
197
 
122
- if content.first.is_a?(Hash)
123
- self.all_view_data_objects = content
198
+ thread = self.content_thread
199
+ if !thread.nil?
200
+ if thread.status == "sleep" || thread.status == "run" || thread.status == "aborting"
201
+ self.update_refresh
202
+ return
203
+ elsif thread.status == nil
204
+ return
205
+ elsif thread.status == false
206
+ rtn = thread.value
207
+ if rtn.is_a?(Ope)
208
+ self.caught_error = rtn.error
209
+ content = Wassup::Pane::Content.new("Overview")
210
+ content.add_row("[fg=red]Error during refersh[fg=white]")
211
+ content.add_row("[fg=red]at #{Time.now}[fg=while]")
212
+ content.add_row("")
213
+ content.add_row("[fg=yellow]Will try again next interval[fg=white]")
214
+
215
+ content_directions = Wassup::Pane::Content.new("Directions")
216
+ content_directions.add_row("1. Press 'c' to copy the stacktrace")
217
+ content_directions.add_row("2. Debug pane content block with:")
218
+ content_directions.add_row(" $: wassup --debug")
219
+ content_directions.add_row("3. Stacktrace viewable in next page")
220
+
221
+ content_stacktrace = Wassup::Pane::Content.new("Stacktrace")
222
+ rtn.error.backtrace.each do |line|
223
+ content_stacktrace.add_row(line)
224
+ end
225
+
226
+ self.refresh_content([content, content_directions, content_stacktrace])
227
+ elsif rtn.is_a?(Wassup::PaneBuilder::ContentBuilder)
228
+ self.caught_error = nil
229
+ self.refresh_content(rtn.contents)
230
+ end
231
+
232
+ self.update_box
233
+ self.update_title
234
+ else
235
+ # This shouldn't happen
236
+ # TODO: also fix this
237
+ return
238
+ end
124
239
  else
125
- self.all_view_data_objects = [
126
- content
127
- ]
240
+ the_block = self.content_block
241
+ self.content_thread = Thread.new {
242
+ begin
243
+ builder = Wassup::PaneBuilder::ContentBuilder.new(self.contents)
244
+ content = the_block.call(builder)
245
+
246
+ builder
247
+ rescue => ex
248
+ next Ope.new(ex)
249
+ end
250
+ }
251
+ self.update_box
252
+ self.update_title
128
253
  end
254
+ end
129
255
 
130
- self.load_current_view()
256
+ def refresh_content(contents)
257
+ self.contents = contents
131
258
 
259
+ self.load_current_view()
132
260
  self.last_refreshed = Time.now
261
+
262
+ self.content_thread = nil
133
263
  end
134
264
 
135
265
  def load_current_view
136
266
  self.setup_subwin()
137
- view_content = self.all_view_data_objects[self.selected_view_index]
138
267
 
139
268
  # this might be bad
140
269
  self.highlighted_line = nil
270
+ self.virtual_reload()
271
+ end
141
272
 
142
- require 'pp'
143
- if view_content.is_a?(Hash) && view_content[:content]
144
- view_content = view_content[:content]
273
+ def title=(title)
274
+ @title = title
275
+ self.update_box()
276
+ self.update_title()
277
+ end
278
+
279
+ def highlight
280
+ if self.caught_error
281
+ return true
282
+ end
283
+ return @highlight
284
+ end
285
+
286
+ attr_accessor :refresh_char_count
287
+ def refresh_char
288
+ return "" unless self.show_refresh
289
+
290
+ if self.refresh_char_count.nil?
291
+ self.refresh_char_count = 0
145
292
  end
146
293
 
147
- @data_lines = []
148
- @data_objects = []
149
- view_content.each do |item|
150
- if item.is_a?(String)
151
- @data_objects << item
152
- self.add_line(item)
153
- elsif item.is_a?(Array)
154
- @data_objects << item[1]
155
- self.add_line(item[0])
294
+ if self.refreshing?
295
+ array = ['\\', '|', '/', '|']
296
+ rtn = array[self.refresh_char_count]
297
+
298
+ self.refresh_char_count += 1
299
+ if self.refresh_char_count >= array.size
300
+ self.refresh_char_count = 0
156
301
  end
302
+
303
+ return rtn
304
+ else
305
+ return ""
157
306
  end
158
307
  end
159
308
 
160
- def title=(title)
161
- @title = title
162
- self.update_box()
163
- self.update_title()
309
+ attr_accessor :last_refresh_char_at
310
+ def update_refresh
311
+ return unless self.should_box
312
+
313
+ self.last_refresh_char_at ||= Time.now
314
+
315
+ if Time.now - self.last_refresh_char_at >= 0.15
316
+ self.win.setpos(0, 1)
317
+ self.win.addstr(self.refresh_char)
318
+ self.win.refresh
319
+
320
+ self.last_refresh_char_at = Time.now
321
+ end
164
322
  end
165
323
 
166
324
  def update_title
325
+ return unless self.should_box
326
+
167
327
  title = self.title || "<No Title>"
168
- full_title = "#{self.focus_number} - #{title}"
328
+
329
+ if self.focus_number.nil?
330
+ full_title = title
331
+ else
332
+ full_title = "#{self.focus_number} - #{title}"
333
+ end
169
334
 
170
335
  self.win.setpos(0, 3)
171
336
  self.win.addstr(full_title)
@@ -182,21 +347,17 @@ module Wassup
182
347
  def update_box
183
348
  return unless self.should_box
184
349
 
185
- self.win.attron(self.focused ? Curses.color_pair(2) : Curses.color_pair(1))
186
- self.win.box()
187
- self.win.attron(Curses.color_pair(1))
350
+ show_focused = self.focused
188
351
 
189
- self.win.refresh
190
- end
352
+ if self.focus_number.nil?
353
+ show_focused = true
354
+ end
191
355
 
192
- def add_line(text)
193
- data_lines << text
356
+ self.win.attrset(show_focused ? Curses.color_pair(Wassup::Color::Pair::BORDER_FOCUS) : Curses.color_pair(Wassup::Color::Pair::BORDER))
357
+ self.win.box()
358
+ self.win.attrset(Curses.color_pair(Wassup::Color::Pair::NORMAL))
194
359
 
195
- if self.virtual_scroll
196
- self.virtual_reload
197
- else
198
- self.load_thing
199
- end
360
+ self.win.refresh
200
361
  end
201
362
 
202
363
  # Load the file into memory and
@@ -211,23 +372,59 @@ module Wassup
211
372
  end
212
373
 
213
374
  def virtual_reload
214
- return if self.data_lines.nil?
375
+ return if self.data_lines.nil? || self.data_lines.empty?
215
376
 
377
+ # TODO: This errored out but might be because thread stuff???
216
378
  self.data_lines[self.top..(self.top+self.subwin.maxy-1)].each_with_index do |line, idx|
217
379
 
218
- if self.focused && self.highlight && (idx + self.top) == self.highlighted_line
219
- self.subwin.attron(Curses.color_pair(4))
220
- else
221
- self.subwin.attron(Curses.color_pair(1))
222
- end
223
-
224
- short_line = line[0...self.subwin.maxx()-3]
225
-
226
- self.subwin.setpos(idx, 0)
227
- self.subwin.addstr(short_line)
228
- self.subwin.clrtoeol()
229
-
230
- self.subwin.attron(Curses.color_pair(1))
380
+ write_full_line = false
381
+ should_highlight = self.focused && self.highlight && (idx + self.top) == self.highlighted_line
382
+
383
+ max_char = self.subwin.maxx()-3
384
+
385
+ self.subwin.attrset(Curses.color_pair(Wassup::Color::Pair::NORMAL))
386
+
387
+ splits = line.split(/\[.*?\]/) # returns ["hey something", "other thing", "okay"]
388
+ scans = line.scan(/\[.*?\]/) #returns ["red", "white"]
389
+ scans = scans.map do |str|
390
+ if str.start_with?('[fg=')
391
+ str = str.gsub('[fg=', '').gsub(']','')
392
+ Wassup::Color.new(str)
393
+ else
394
+ str
395
+ end
396
+ end
397
+
398
+ all_parts = splits.zip(scans).flatten.compact
399
+
400
+ char_count = 0
401
+
402
+ if should_highlight
403
+ self.subwin.attrset(Curses.color_pair(Wassup::Color::Pair::HIGHLIGHT))
404
+ end
405
+
406
+ all_parts.each do |part|
407
+ if part.is_a?(Wassup::Color)
408
+ #color = Curses.color_pair([1,2,3,4].sample)
409
+ if !should_highlight
410
+ self.subwin.attrset(Curses.color_pair(part.color_pair))
411
+ end
412
+ else
413
+ new_char_count = char_count + part.size
414
+ if new_char_count >= max_char
415
+ part = part[0...(max_char - char_count)]
416
+ end
417
+
418
+ self.subwin.setpos(idx, char_count)
419
+ self.subwin.addstr(part)
420
+
421
+ char_count += part.size
422
+ end
423
+
424
+ end
425
+
426
+ self.subwin.attrset(Curses.color_pair(Wassup::Color::Pair::NORMAL))
427
+ self.subwin.clrtoeol()
231
428
  end
232
429
  self.subwin.refresh
233
430
  end
@@ -289,7 +486,7 @@ module Wassup
289
486
  def scroll_left
290
487
  self.selected_view_index -= 1
291
488
  if self.selected_view_index < 0
292
- self.selected_view_index = self.all_view_data_objects.size - 1
489
+ self.selected_view_index = self.contents.size - 1
293
490
  end
294
491
 
295
492
  self.load_current_view
@@ -297,7 +494,7 @@ module Wassup
297
494
 
298
495
  def scroll_right
299
496
  self.selected_view_index += 1
300
- if self.selected_view_index >= self.all_view_data_objects.size
497
+ if self.selected_view_index >= self.contents.size
301
498
  self.selected_view_index = 0
302
499
  end
303
500
 
@@ -327,10 +524,10 @@ module Wassup
327
524
  self.top += 1
328
525
  str = self.data_lines[self.top + self.subwin.maxy - 1]
329
526
  if str
330
- self.subwin.attron(Curses.color_pair(1))
527
+ self.subwin.attrset(Curses.color_pair(Wassup::Color::Pair::NORMAL))
331
528
  self.subwin.setpos(self.subwin.maxy - 1, 0)
332
529
  self.subwin.addstr(str)
333
- self.subwin.attron(Curses.color_pair(1))
530
+ self.subwin.attrset(Curses.color_pair(Wassup::Color::Pair::NORMAL))
334
531
  end
335
532
  return true
336
533
  else
@@ -348,27 +545,38 @@ module Wassup
348
545
 
349
546
  if input == "j"
350
547
  if virtual_scroll
351
- virtual_scroll_down
548
+ self.virtual_scroll_down
352
549
  else
353
550
  scroll_down
354
551
  end
355
552
  elsif input == "k"
356
553
  if virtual_scroll
357
- virtual_scroll_up
554
+ self.virtual_scroll_up
358
555
  else
359
556
  scroll_up
360
557
  end
361
558
  elsif input == "h"
362
- scroll_left
559
+ self.scroll_left
363
560
  elsif input == "l"
364
- scroll_right
365
- elsif input == "q"
366
- # TODO: This needs to quit
367
- # Need to kill the loop or something
368
- elsif input == 10 # enter
369
- if !self.selection_block.nil? && !self.highlighted_line.nil?
370
- data = @data_objects[self.highlighted_line]
371
- self.selection_block.call(data)
561
+ self.scroll_right
562
+ elsif input == "r"
563
+ self.refresh(force: true)
564
+ elsif input == "c"
565
+ if !self.caught_error.nil?
566
+ text = self.caught_error.backtrace.join("\n")
567
+ if RUBY_PLATFORM.downcase =~ /win32/
568
+ IO.popen('clip', 'w') { |pipe| pipe.puts text }
569
+ else
570
+ IO.popen('pbcopy', 'w') { |pipe| pipe.puts text }
571
+ end
572
+ end
573
+ else
574
+ selection_block = self.selection_blocks[input]
575
+ if !selection_block.nil? && !self.highlighted_line.nil?
576
+ content = self.contents[self.selected_view_index]
577
+ row = content.data[self.highlighted_line]
578
+ data = row.object || row.display
579
+ selection_block.call(data)
372
580
  end
373
581
  end
374
582
  end
@@ -9,16 +9,87 @@ module Wassup
9
9
  attr_accessor :highlight
10
10
 
11
11
  attr_accessor :title
12
+ attr_accessor :description
13
+
14
+ attr_accessor :show_refresh
12
15
 
13
16
  attr_accessor :interval
14
17
  attr_accessor :content_block
15
- attr_accessor :selection_block
18
+ attr_accessor :selection_blocks
19
+ attr_accessor :selection_blocks_description
20
+
21
+ class ContentBuilder
22
+ attr_accessor :contents
23
+
24
+ def initialize(contents)
25
+ @contents = contents
26
+ @need_to_clear = true
27
+ @show_refresh = true
28
+ end
29
+
30
+ def clear=(clear)
31
+ @need_to_clear = clear
32
+ end
33
+
34
+ def add_row(display, object=nil, page:nil)
35
+ if @need_to_clear
36
+ @need_to_clear = false
37
+ self.contents = []
38
+ end
39
+
40
+ content = nil
41
+
42
+ # Create contents if none
43
+ if page.nil?
44
+ if self.contents.empty?
45
+ content = Pane::Content.new
46
+ self.contents << content
47
+ else
48
+ content = self.contents.first
49
+ end
50
+ elsif page.is_a?(String)
51
+ content = self.contents.find do |content|
52
+ content.title == page
53
+ end
54
+
55
+ if content.nil?
56
+ content = Pane::Content.new(page)
57
+ self.contents << content
58
+ end
59
+ end
60
+
61
+ content.add_row(display, object)
62
+ end
63
+ end
64
+
65
+ def initialize()
66
+ @height = 1
67
+ @weight = 1
68
+ @top = 0
69
+ @left = 0
70
+
71
+ @highlight = false
72
+ @interval = 60 * 5
73
+
74
+ @selection_blocks = {}
75
+ @selection_blocks_description = {}
76
+ end
16
77
 
17
78
  def content(&block)
18
79
  self.content_block = block
19
80
  end
20
- def selection(&block)
21
- self.selection_block = block
81
+ def selection(input=10, description=nil, &block)
82
+ if input.to_s.downcase == "enter"
83
+ input = 10
84
+ end
85
+
86
+ description_input = input
87
+ if input.to_s == "10"
88
+ description_input = "enter"
89
+ end
90
+
91
+ self.selection_blocks[input] = block
92
+ self.selection_blocks_description[description_input] = description
22
93
  end
23
94
  end
24
95
  end
@@ -1,3 +1,3 @@
1
1
  module Wassup
2
- VERSION = "0.1.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/wassup.rb CHANGED
@@ -1,8 +1,14 @@
1
1
  require "wassup/version"
2
2
  require "wassup/app"
3
+ require "wassup/color"
3
4
  require "wassup/pane"
4
5
  require "wassup/pane_builder"
5
6
 
7
+ require "wassup/helpers/circleci"
8
+ require "wassup/helpers/github"
9
+ require "wassup/helpers/netlify"
10
+ require "wassup/helpers/shortcut"
11
+
6
12
  module Wassup
7
13
  class Error < StandardError; end
8
14
  # Your code goes here...
data/wassup.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.metadata["source_code_uri"] = "https://github.com/joshdholtz/wassup"
17
17
 
18
18
  spec.add_runtime_dependency 'curses'
19
+ spec.add_runtime_dependency 'rest-client'
19
20
 
20
21
  # Specify which files should be added to the gem when it is released.
21
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.