shoes 4.0.0.pre11 → 4.0.0.pre12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/shoes-stub +8 -0
- data/lib/shoes/samples.rb +8 -0
- data/samples/README +122 -0
- data/samples/avatar.png +0 -0
- data/samples/blue-box.png +0 -0
- data/samples/class-book.yaml +387 -0
- data/samples/class_book.rb +46 -0
- data/samples/cy.png +0 -0
- data/samples/expert_definr.rb +24 -0
- data/samples/expert_funnies.rb +60 -0
- data/samples/expert_game_of_life.rb +224 -0
- data/samples/expert_irb.rb +109 -0
- data/samples/expert_minesweeper.rb +272 -0
- data/samples/expert_othello.rb +323 -0
- data/samples/expert_pong.rb +69 -0
- data/samples/expert_snake.rb +88 -0
- data/samples/expert_tankspank.rb +425 -0
- data/samples/expert_tetris.rb +322 -0
- data/samples/good_arc.rb +51 -0
- data/samples/good_bounce.rb +34 -0
- data/samples/good_clock.rb +55 -0
- data/samples/good_displace.rb +99 -0
- data/samples/good_follow.rb +27 -0
- data/samples/good_image_dl.rb +13 -0
- data/samples/good_potato_chopping.rb +23 -0
- data/samples/good_psychidelic_circles.rb +73 -0
- data/samples/good_reminder.rb +163 -0
- data/samples/good_vjot.rb +65 -0
- data/samples/lib/require_me.rb +6 -0
- data/samples/loogink.png +0 -0
- data/samples/menu-corner1.png +0 -0
- data/samples/menu-corner2.png +0 -0
- data/samples/menu-gray.png +0 -0
- data/samples/menu-left.png +0 -0
- data/samples/menu-right.png +0 -0
- data/samples/menu-top.png +0 -0
- data/samples/nks_booklist.rb +25 -0
- data/samples/nks_breadsticks.rb +8 -0
- data/samples/nks_dancing_circle.rb +14 -0
- data/samples/nks_dictionary.rb +24 -0
- data/samples/nks_edit_box.rb +5 -0
- data/samples/nks_edit_line.rb +7 -0
- data/samples/nks_notes.rb +16 -0
- data/samples/nks_poem.rb +23 -0
- data/samples/nks_self.rb +7 -0
- data/samples/nks_text_sizes.rb +11 -0
- data/samples/nks_trurl.rb +6 -0
- data/samples/potato_chopping/1258_s001.gif +0 -0
- data/samples/potato_chopping/1258_s002.gif +0 -0
- data/samples/potato_chopping/1258_s003.gif +0 -0
- data/samples/potato_chopping/1258_s004.gif +0 -0
- data/samples/potato_chopping/1258_s005.gif +0 -0
- data/samples/potato_chopping/1258_s006.gif +0 -0
- data/samples/potato_chopping/1258_s007.gif +0 -0
- data/samples/potato_chopping/1258_s008.gif +0 -0
- data/samples/potato_chopping/1258_s009.gif +0 -0
- data/samples/potato_chopping/1258_s010.gif +0 -0
- data/samples/potato_chopping/1258_s011.gif +0 -0
- data/samples/potato_chopping/1258_s012.gif +0 -0
- data/samples/potato_chopping/1258_s013.gif +0 -0
- data/samples/potato_chopping/1258_s014.gif +0 -0
- data/samples/potato_chopping/1258_s015.gif +0 -0
- data/samples/potato_chopping/1258_s016.gif +0 -0
- data/samples/potato_chopping/1258_s017.gif +0 -0
- data/samples/potato_chopping/1258_s018.gif +0 -0
- data/samples/potato_chopping/1258_s019.gif +0 -0
- data/samples/potato_chopping/1258_s020.gif +0 -0
- data/samples/potato_chopping/1258_s021.gif +0 -0
- data/samples/potato_chopping/1258_s022.gif +0 -0
- data/samples/potato_chopping/1258_s023.gif +0 -0
- data/samples/potato_chopping/1258_s024.gif +0 -0
- data/samples/potato_chopping/1258_s025.gif +0 -0
- data/samples/potato_chopping/1258_s026.gif +0 -0
- data/samples/potato_chopping/1258_s027.gif +0 -0
- data/samples/potato_chopping/1258_s028.gif +0 -0
- data/samples/potato_chopping/1258_s029.gif +0 -0
- data/samples/potato_chopping/1258_s030.gif +0 -0
- data/samples/potato_chopping/1258_s031.gif +0 -0
- data/samples/potato_chopping/1258_s032.gif +0 -0
- data/samples/potato_chopping/1258_s033.gif +0 -0
- data/samples/potato_chopping/1258_s034.gif +0 -0
- data/samples/potato_chopping/1258_s035.gif +0 -0
- data/samples/potato_chopping/1258_s036.gif +0 -0
- data/samples/potato_chopping/1258_s037.gif +0 -0
- data/samples/potato_chopping/1258_s038.gif +0 -0
- data/samples/potato_chopping/1258_s039.gif +0 -0
- data/samples/potato_chopping/1258_s040.gif +0 -0
- data/samples/potato_chopping/1258_s041.gif +0 -0
- data/samples/potato_chopping/1258_s042.gif +0 -0
- data/samples/potato_chopping/1258_s043.gif +0 -0
- data/samples/potato_chopping/1258_s044.gif +0 -0
- data/samples/potato_chopping/1258_s045.gif +0 -0
- data/samples/potato_chopping/1258_s046.gif +0 -0
- data/samples/potato_chopping/1258_s047.gif +0 -0
- data/samples/potato_chopping/1258_s048.gif +0 -0
- data/samples/potato_chopping/1258_s049.gif +0 -0
- data/samples/potato_chopping/1258_s050.gif +0 -0
- data/samples/potato_chopping/1258_s051.gif +0 -0
- data/samples/potato_chopping/1258_s052.gif +0 -0
- data/samples/potato_chopping/1258_s053.gif +0 -0
- data/samples/potato_chopping/1258_s054.gif +0 -0
- data/samples/potato_chopping/1258_s055.gif +0 -0
- data/samples/potato_chopping/1258_s056.gif +0 -0
- data/samples/potato_chopping/1258_s057.gif +0 -0
- data/samples/potato_chopping/1258_s058.gif +0 -0
- data/samples/potato_chopping/1258_s059.gif +0 -0
- data/samples/red-box.png +0 -0
- data/samples/shape_arc_to.rb +10 -0
- data/samples/simple-form.shy +0 -0
- data/samples/simple_accordion.rb +98 -0
- data/samples/simple_alert.rb +10 -0
- data/samples/simple_altered_para.rb +11 -0
- data/samples/simple_anim_shapes.rb +18 -0
- data/samples/simple_anim_text.rb +14 -0
- data/samples/simple_animate.rb +12 -0
- data/samples/simple_arc.rb +25 -0
- data/samples/simple_attach.rb +26 -0
- data/samples/simple_border_image.rb +9 -0
- data/samples/simple_borderless.rb +4 -0
- data/samples/simple_bounce.rb +27 -0
- data/samples/simple_breadsticks.rb +11 -0
- data/samples/simple_breadsticks2.rb +11 -0
- data/samples/simple_brightness_transitions.rb +16 -0
- data/samples/simple_button_animate.rb +17 -0
- data/samples/simple_buttons.rb +4 -0
- data/samples/simple_calc.rb +67 -0
- data/samples/simple_calc_2.rb +49 -0
- data/samples/simple_clipboard.rb +17 -0
- data/samples/simple_color_selector.rb +11 -0
- data/samples/simple_color_transitions.rb +12 -0
- data/samples/simple_concentric_circles.rb +9 -0
- data/samples/simple_console.rb +12 -0
- data/samples/simple_control_sizes.rb +25 -0
- data/samples/simple_count_and_draw.rb +19 -0
- data/samples/simple_curve.rb +34 -0
- data/samples/simple_dialogs.rb +33 -0
- data/samples/simple_dialogs_outside.rb +17 -0
- data/samples/simple_displace.rb +16 -0
- data/samples/simple_downloader.rb +29 -0
- data/samples/simple_draw.rb +16 -0
- data/samples/simple_editor.rb +30 -0
- data/samples/simple_face.rb +15 -0
- data/samples/simple_flashing.rb +22 -0
- data/samples/simple_flow_wrap.rb +12 -0
- data/samples/simple_font.rb +18 -0
- data/samples/simple_form.rb +30 -0
- data/samples/simple_fullscreen.rb +5 -0
- data/samples/simple_gradient_shapes.rb +23 -0
- data/samples/simple_guess_game.rb +30 -0
- data/samples/simple_image_as_stroke.rb +22 -0
- data/samples/simple_image_fill.rb +13 -0
- data/samples/simple_image_stroke.rb +13 -0
- data/samples/simple_info.rb +10 -0
- data/samples/simple_iterated_content.rb +8 -0
- data/samples/simple_keypress.rb +15 -0
- data/samples/simple_logo_display.rb +15 -0
- data/samples/simple_loogink_cy.rb +33 -0
- data/samples/simple_lorem_ipsum.rb +19 -0
- data/samples/simple_manual.rb +5 -0
- data/samples/simple_menu.rb +42 -0
- data/samples/simple_mouse_follow.rb +9 -0
- data/samples/simple_oval.rb +6 -0
- data/samples/simple_polygon_line.rb +19 -0
- data/samples/simple_position_as_we_go.rb +10 -0
- data/samples/simple_progress_bar.rb +15 -0
- data/samples/simple_random_bubbles.rb +15 -0
- data/samples/simple_require.rb +9 -0
- data/samples/simple_sample_executor.rb +7 -0
- data/samples/simple_sample_executor_all.rb +14 -0
- data/samples/simple_sesame_street_shoes.rb +6 -0
- data/samples/simple_shoes_intro.rb +22 -0
- data/samples/simple_slide.rb +57 -0
- data/samples/simple_stack_flow_buttons.rb +16 -0
- data/samples/simple_stripes.rb +9 -0
- data/samples/simple_system_background.rb +5 -0
- data/samples/simple_text_movement.rb +8 -0
- data/samples/simple_tictactoe.rb +224 -0
- data/samples/simple_timer.rb +16 -0
- data/samples/simple_translate.rb +10 -0
- data/samples/simple_visibility.rb +20 -0
- metadata +186 -7
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class Book < Shoes
|
5
|
+
url '/', :index
|
6
|
+
url '/incidents/(\d+)', :incident
|
7
|
+
|
8
|
+
def index
|
9
|
+
incident 0
|
10
|
+
end
|
11
|
+
|
12
|
+
INCIDENTS = YAML.load_file File.expand_path(File.join(__FILE__, '../class-book.yaml'))
|
13
|
+
|
14
|
+
def table_of_contents
|
15
|
+
toc = []
|
16
|
+
INCIDENTS.each_with_index do |(title, _story), i|
|
17
|
+
toc.push "(#{i + 1}) ",
|
18
|
+
link(title) { visit "/incidents/#{i}" },
|
19
|
+
" / "
|
20
|
+
end
|
21
|
+
toc[0...-1] << "\n" * 5
|
22
|
+
end
|
23
|
+
|
24
|
+
def incident(num)
|
25
|
+
self.scroll_top = 0
|
26
|
+
num = num.to_i
|
27
|
+
stack margin_left: 200 do
|
28
|
+
banner "Incident", margin: [0, 10, 0, 30]
|
29
|
+
para strong("No. #{num + 1}: #{INCIDENTS[num][0]}"), margin_bottom: 5
|
30
|
+
end
|
31
|
+
|
32
|
+
flow do
|
33
|
+
flow width: 180, margin_left: 10 do
|
34
|
+
para(*table_of_contents, size: 8)
|
35
|
+
end
|
36
|
+
|
37
|
+
stack width: width - 180, margin: [20, 0, 10, 0] do
|
38
|
+
INCIDENTS[num][1].split(/\n\n+/).each do |p|
|
39
|
+
para p
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Shoes.app width: 640, height: 700, title: "Incidents, a Book"
|
data/samples/cy.png
ADDED
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
Shoes.app title: "Dictionary, powered by Definr", width: 370, height: 320 do
|
3
|
+
stack do
|
4
|
+
background red, height: 60
|
5
|
+
flow margin: 20 do
|
6
|
+
caption "Define: ", stroke: white
|
7
|
+
@lookup = edit_line
|
8
|
+
button "Go" do
|
9
|
+
download "http://definr.com/definr/show/#{@lookup.text}" do |dl|
|
10
|
+
doc = dl.response.body.gsub(' ', ' ')
|
11
|
+
.gsub(%r{(</a>|<br />|<a href.+?>)}, '')
|
12
|
+
.gsub(%r{\(http://.+?\)}, '').strip
|
13
|
+
title, doc = doc.split(/\n+/, 2)
|
14
|
+
@deft.replace title
|
15
|
+
@defn.replace doc
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
stack margin: 20 do
|
20
|
+
@deft = subtitle "", margin: 10
|
21
|
+
@defn = para ""
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# This example tries Nokogiri (used in Shoes 4), but falls back to
|
3
|
+
# Hpricot for Shoes 3 compatibility
|
4
|
+
begin
|
5
|
+
require 'nokogiri'
|
6
|
+
rescue LoadError
|
7
|
+
require 'hpricot'
|
8
|
+
end
|
9
|
+
|
10
|
+
class Comic
|
11
|
+
attr_reader :rss, :title
|
12
|
+
|
13
|
+
def initialize(body)
|
14
|
+
@rss = defined?(Nokogiri) ? Nokogiri::XML(body) : Hpricot(body)
|
15
|
+
@title = @rss.at("//channel/title").inner_text
|
16
|
+
end
|
17
|
+
|
18
|
+
def items
|
19
|
+
@rss.search("//channel/item")
|
20
|
+
end
|
21
|
+
|
22
|
+
def latest_image
|
23
|
+
@rss.search("//channel/item").first.inner_html.scan(/src="([^"]+\.\w+)"/).first
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Shoes.app width: 800, height: 600 do
|
28
|
+
background "#555"
|
29
|
+
|
30
|
+
@title = "Web Funnies"
|
31
|
+
@feeds = [
|
32
|
+
"http://xkcd.com/rss.xml",
|
33
|
+
"http://www.smbc-comics.com/rss.php",
|
34
|
+
"http://www.daybydaycartoon.com/feed/",
|
35
|
+
"http://www.questionablecontent.net/QCRSS.xml",
|
36
|
+
"http://thisisindexed.com/feed/",
|
37
|
+
]
|
38
|
+
|
39
|
+
stack margin: 10 do
|
40
|
+
title strong(@title), align: "center", stroke: "#DFA", margin: 0
|
41
|
+
para "(loaded from RSS feeds)", align: "center", stroke: "#DFA", margin: 0
|
42
|
+
|
43
|
+
@feeds.each do |feed|
|
44
|
+
download feed do |dl|
|
45
|
+
# Fall back to Shoes 3 syntax if necessary
|
46
|
+
body = dl.respond_to?(:read) ? dl.read : dl.response.body
|
47
|
+
c = Comic.new body
|
48
|
+
if c.latest_image
|
49
|
+
stack width: "100%", margin: 10, border: 1 do
|
50
|
+
stack margin_right: gutter do
|
51
|
+
background "#333", curve: 4
|
52
|
+
caption c.title, stroke: "#CD9", margin: 4
|
53
|
+
end
|
54
|
+
image c.latest_image.first, margin: 8
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Simple Game of Life with Shoes
|
3
|
+
# by fuksito
|
4
|
+
# vitaliy@yanchuk.me
|
5
|
+
|
6
|
+
class Cell
|
7
|
+
WIDTH = 15
|
8
|
+
attr_accessor :live, :next_state, :y, :x, :neighbours, :live_neighbours, :app, :shoes_cell
|
9
|
+
|
10
|
+
def initialize(y, x, app, world)
|
11
|
+
@live = false
|
12
|
+
@next_state = false
|
13
|
+
@y = y
|
14
|
+
@x = x
|
15
|
+
@app = app
|
16
|
+
@world = world
|
17
|
+
@shoes_cell = @app.rect(left: WIDTH * y, top: WIDTH * x, width: WIDTH)
|
18
|
+
@shoes_cell.click { toggle_state }
|
19
|
+
end
|
20
|
+
|
21
|
+
def live?
|
22
|
+
@live
|
23
|
+
end
|
24
|
+
|
25
|
+
def dead?
|
26
|
+
!@live
|
27
|
+
end
|
28
|
+
|
29
|
+
def die!
|
30
|
+
@next_state = false
|
31
|
+
@world.changed_cells.push(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def alive!
|
35
|
+
@next_state = true
|
36
|
+
@world.changed_cells.push(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def toggle_state
|
40
|
+
@next_state = !@live
|
41
|
+
set_next_state
|
42
|
+
draw
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_next_state
|
46
|
+
@live = @next_state
|
47
|
+
if @live
|
48
|
+
@world.live_cells.push(self)
|
49
|
+
else
|
50
|
+
cell_index = @world.live_cells.index(self)
|
51
|
+
@world.live_cells.delete_at(cell_index) if cell_index
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def draw
|
56
|
+
@shoes_cell.style(fill: live? ? '#000' : '#fff')
|
57
|
+
end
|
58
|
+
|
59
|
+
def iterate
|
60
|
+
live_cells_count = @neighbours.count(&:live?)
|
61
|
+
if live? && live_cells_count < 2 || live_cells_count > 3
|
62
|
+
die!
|
63
|
+
elsif live_cells_count == 3
|
64
|
+
alive!
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class World
|
70
|
+
attr_accessor :board, :width, :height, :live_cells, :changed_cells
|
71
|
+
|
72
|
+
def initialize(width, height, app)
|
73
|
+
@board = []
|
74
|
+
@width = width
|
75
|
+
@height = height
|
76
|
+
@app = app
|
77
|
+
@live_cells = []
|
78
|
+
@changed_cells = []
|
79
|
+
create_board
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_board
|
83
|
+
@height.times do |y|
|
84
|
+
@board[y] = []
|
85
|
+
@width.times do |x|
|
86
|
+
@board[y][x] = Cell.new(y, x, @app, self)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
cells.each do |cell|
|
90
|
+
cell.neighbours = cell_neighbours(cell.y, cell.x)
|
91
|
+
end
|
92
|
+
draw
|
93
|
+
end
|
94
|
+
|
95
|
+
def cells
|
96
|
+
@cells ||= @board.flatten
|
97
|
+
end
|
98
|
+
|
99
|
+
def actual_cells
|
100
|
+
(@live_cells.map(&:neighbours).flatten + @live_cells).uniq
|
101
|
+
end
|
102
|
+
|
103
|
+
def draw
|
104
|
+
cells.each(&:draw)
|
105
|
+
end
|
106
|
+
|
107
|
+
def tick
|
108
|
+
@changed_cells = []
|
109
|
+
actual_cells.each(&:iterate).each(&:set_next_state)
|
110
|
+
@changed_cells.each(&:draw)
|
111
|
+
end
|
112
|
+
|
113
|
+
def clear
|
114
|
+
live_cells.each do |cell|
|
115
|
+
cell.live = false
|
116
|
+
cell.next_state = false
|
117
|
+
cell.draw
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def cell_neighbours(y, x)
|
122
|
+
result = []
|
123
|
+
top_row = y - 1
|
124
|
+
left_col = x - 1
|
125
|
+
right_col = x + 1
|
126
|
+
bottom_row = y + 1
|
127
|
+
|
128
|
+
result << @board[y - 1][x - 1] if top_row >= 0 && left_col >= 0
|
129
|
+
|
130
|
+
result << @board[y - 1][x] if top_row >= 0
|
131
|
+
|
132
|
+
result << @board[y - 1][x + 1] if top_row >= 0 && right_col < @width
|
133
|
+
|
134
|
+
result << @board[y][x - 1] if left_col >= 0
|
135
|
+
|
136
|
+
result << @board[y][x + 1] if right_col < @width
|
137
|
+
|
138
|
+
result << @board[y + 1][x - 1] if bottom_row < @height && left_col >= 0
|
139
|
+
|
140
|
+
result << @board[y + 1][x] if bottom_row < @height
|
141
|
+
|
142
|
+
result << @board[y + 1][x + 1] if bottom_row < @height && right_col < @width
|
143
|
+
|
144
|
+
result.compact
|
145
|
+
end
|
146
|
+
|
147
|
+
def add_species(*cells)
|
148
|
+
cells.each do |y, x|
|
149
|
+
@board[y][x].toggle_state
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def add_glider
|
154
|
+
add_species [4, 2], [4, 3], [4, 4], [3, 4], [2, 3]
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_spaceship
|
158
|
+
add_species [12, 3], [12, 6], [13, 7], [14, 3], [14, 7], [15, 4], [15, 5], [15, 6], [15, 7]
|
159
|
+
end
|
160
|
+
|
161
|
+
def add_diehard
|
162
|
+
add_species [18, 12], [12, 13], [13, 13], [13, 14], [17, 14], [18, 14], [19, 14]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
Shoes.app(title: "The Game of Life", width: 800, height: 620, resizable: false) do
|
167
|
+
background white
|
168
|
+
@running = false
|
169
|
+
stack(margin: 10) do
|
170
|
+
@new_world = World.new(40, 40, self)
|
171
|
+
animate(10) do
|
172
|
+
@new_world.tick if @running
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def run
|
177
|
+
@running = true
|
178
|
+
@run_stop_button.text = 'Stop'
|
179
|
+
end
|
180
|
+
|
181
|
+
def stop
|
182
|
+
@running = false
|
183
|
+
@run_stop_button.text = 'Run'
|
184
|
+
end
|
185
|
+
|
186
|
+
def toggle_run_stop
|
187
|
+
if @running
|
188
|
+
stop
|
189
|
+
else
|
190
|
+
run
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def clear
|
195
|
+
stop
|
196
|
+
@new_world.clear
|
197
|
+
end
|
198
|
+
|
199
|
+
flow(displace_left: 650) do
|
200
|
+
@run_stop_button = button('Run', displace_top: 0, width: 100) { toggle_run_stop }
|
201
|
+
end
|
202
|
+
|
203
|
+
stack(displace_left: 650) do
|
204
|
+
button('Clear', width: 100) do
|
205
|
+
clear
|
206
|
+
end
|
207
|
+
|
208
|
+
para "Species"
|
209
|
+
button('Glider', width: 100) do
|
210
|
+
clear
|
211
|
+
@new_world.add_glider
|
212
|
+
end
|
213
|
+
|
214
|
+
button('Spaceship', width: 100) do
|
215
|
+
clear
|
216
|
+
@new_world.add_spaceship
|
217
|
+
end
|
218
|
+
|
219
|
+
button('Diehard', width: 100) do
|
220
|
+
clear
|
221
|
+
@new_world.add_diehard
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'irb/ruby-lex'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
class MimickIRB < RubyLex
|
6
|
+
attr_accessor :started
|
7
|
+
|
8
|
+
class Continue < StandardError; end
|
9
|
+
class Empty < StandardError; end
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super
|
13
|
+
set_input(StringIO.new)
|
14
|
+
end
|
15
|
+
|
16
|
+
def run(str)
|
17
|
+
obj = nil
|
18
|
+
@io << str
|
19
|
+
@io.rewind
|
20
|
+
l = lex
|
21
|
+
if l
|
22
|
+
case l.strip
|
23
|
+
when "reset"
|
24
|
+
@line = ""
|
25
|
+
when "time"
|
26
|
+
@line = "puts %{You started \#{IRBalike.started.since} ago.}"
|
27
|
+
else
|
28
|
+
@line = @line + l + "\n"
|
29
|
+
raise Continue if @ltype || @continue || @indent.positive?
|
30
|
+
end
|
31
|
+
elsif @line == ''
|
32
|
+
raise Empty
|
33
|
+
end
|
34
|
+
obj = eval @line, TOPLEVEL_BINDING, "(irb)", @line_no unless @line.empty?
|
35
|
+
@line_no += @line.scan(/\n/).length
|
36
|
+
@line = ''
|
37
|
+
@exp_line_no = @line_no
|
38
|
+
|
39
|
+
@indent = 0
|
40
|
+
@indent_stack = []
|
41
|
+
|
42
|
+
$stdout.rewind
|
43
|
+
output = $stdout.read
|
44
|
+
$stdout.truncate(0)
|
45
|
+
$stdout.rewind
|
46
|
+
[output, obj]
|
47
|
+
rescue Object => e
|
48
|
+
@line = "" unless e.is_a?(Empty) || e.is_a?(Continue)
|
49
|
+
raise e
|
50
|
+
ensure
|
51
|
+
set_input(StringIO.new)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
CURSOR = ">>"
|
56
|
+
IRBalike = MimickIRB.new
|
57
|
+
$stdout = StringIO.new
|
58
|
+
|
59
|
+
Shoes.app do
|
60
|
+
@str = [CURSOR + " "]
|
61
|
+
@cmd = ""
|
62
|
+
stack width: 1.0, height: 1.0 do
|
63
|
+
background "#555"
|
64
|
+
stack width: 1.0, height: 50 do
|
65
|
+
para "Interactive Ruby ready.", fill: white, stroke: red
|
66
|
+
end
|
67
|
+
@scroll =
|
68
|
+
stack width: 1.0, height: -50, scroll: true do
|
69
|
+
background "#555"
|
70
|
+
@console = para(*@str, font: "Monospace 12px", stroke: "#dfa")
|
71
|
+
@console.cursor = -1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
keypress do |k|
|
75
|
+
case k
|
76
|
+
when "\n"
|
77
|
+
begin
|
78
|
+
out, obj = IRBalike.run(@cmd + ';')
|
79
|
+
@str += ["#{@cmd}\n",
|
80
|
+
span("#{out}=> #{obj.inspect}\n", stroke: "#fda"),
|
81
|
+
"#{CURSOR} "]
|
82
|
+
@cmd = ""
|
83
|
+
rescue MimickIRB::Empty
|
84
|
+
@cmd = ""
|
85
|
+
rescue MimickIRB::Continue
|
86
|
+
@str += ["#{@cmd}\n.. "]
|
87
|
+
@cmd = ""
|
88
|
+
rescue Object => e
|
89
|
+
@str += ["#{@cmd}\n", span("#{e.class}: #{e.message}\n", stroke: "#fcf"),
|
90
|
+
"#{CURSOR} "]
|
91
|
+
@cmd = ""
|
92
|
+
end
|
93
|
+
when String
|
94
|
+
@cmd += k
|
95
|
+
when :backspace
|
96
|
+
@cmd.slice!(-1)
|
97
|
+
when :tab
|
98
|
+
@cmd += " "
|
99
|
+
when :alt_q
|
100
|
+
quit
|
101
|
+
when :alt_c
|
102
|
+
self.clipboard = @cmd
|
103
|
+
when :alt_v
|
104
|
+
@cmd += clipboard
|
105
|
+
end
|
106
|
+
@console.replace(*(@str + [@cmd]))
|
107
|
+
@scroll.scroll_top = @scroll.scroll_max
|
108
|
+
end
|
109
|
+
end
|