twterm 1.0.9 → 1.0.10
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.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +24 -2
- data/lib/twterm/app.rb +14 -4
- data/lib/twterm/auth.rb +5 -5
- data/lib/twterm/client.rb +185 -142
- data/lib/twterm/color_manager.rb +15 -11
- data/lib/twterm/config.rb +22 -17
- data/lib/twterm/list.rb +9 -9
- data/lib/twterm/notifier.rb +7 -22
- data/lib/twterm/scheduler.rb +5 -8
- data/lib/twterm/screen.rb +25 -20
- data/lib/twterm/status.rb +84 -79
- data/lib/twterm/tab/base.rb +26 -11
- data/lib/twterm/tab/conversation_tab.rb +16 -16
- data/lib/twterm/tab/key_assignments_cheatsheet.rb +113 -0
- data/lib/twterm/tab/list_tab.rb +1 -1
- data/lib/twterm/tab/mentions_tab.rb +13 -13
- data/lib/twterm/tab/new/list.rb +51 -40
- data/lib/twterm/tab/new/search.rb +8 -5
- data/lib/twterm/tab/new/start.rb +26 -35
- data/lib/twterm/tab/new/user.rb +8 -5
- data/lib/twterm/tab/scroll_manager.rb +84 -0
- data/lib/twterm/tab/search_tab.rb +16 -16
- data/lib/twterm/tab/statuses_tab.rb +177 -128
- data/lib/twterm/tab/timeline_tab.rb +13 -15
- data/lib/twterm/tab/user_tab.rb +18 -18
- data/lib/twterm/tab_manager.rb +49 -44
- data/lib/twterm/tweetbox.rb +51 -25
- data/lib/twterm/user.rb +5 -8
- data/lib/twterm/version.rb +1 -1
- data/lib/twterm.rb +4 -2
- data/spec/resources/config +4 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/twterm/config_spec.rb +34 -0
- data/twterm.gemspec +2 -0
- metadata +25 -6
- data/lib/twterm/tab/scrollable.rb +0 -130
@@ -2,7 +2,73 @@ module Twterm
|
|
2
2
|
module Tab
|
3
3
|
module StatusesTab
|
4
4
|
include Base
|
5
|
-
|
5
|
+
|
6
|
+
def append(status)
|
7
|
+
fail ArgumentError,
|
8
|
+
'argument must be an instance of Status class' unless status.is_a? Status
|
9
|
+
|
10
|
+
return if @status_ids.include?(status.id)
|
11
|
+
|
12
|
+
@status_ids.unshift(status.id)
|
13
|
+
status.split(window.maxx - 4)
|
14
|
+
status.touch!
|
15
|
+
scroll_manager.item_appended!
|
16
|
+
refresh
|
17
|
+
end
|
18
|
+
|
19
|
+
def count
|
20
|
+
grep_query.empty? ? @status_ids.count : statuses.count
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete(status_id)
|
24
|
+
@status_ids.delete(status_id)
|
25
|
+
refresh
|
26
|
+
end
|
27
|
+
|
28
|
+
def destroy_status
|
29
|
+
status = highlighted_status
|
30
|
+
|
31
|
+
Client.current.destroy_status(status) do
|
32
|
+
delete(status.id)
|
33
|
+
refresh
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def favorite
|
38
|
+
return if highlighted_status.nil?
|
39
|
+
|
40
|
+
method_name = highlighted_status.favorited ? :unfavorite : :favorite
|
41
|
+
Client.current.method(method_name).call(highlighted_status) { refresh }
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch
|
45
|
+
fail NotImplementedError, 'fetch method must be implemented'
|
46
|
+
end
|
47
|
+
|
48
|
+
def grep
|
49
|
+
reset_grep
|
50
|
+
|
51
|
+
Curses.echo
|
52
|
+
Curses.setpos(stdscr.maxy - 1, 0)
|
53
|
+
Curses.stdscr.addch '/'
|
54
|
+
@grep_query = Curses.getstr.chomp
|
55
|
+
Curses.noecho
|
56
|
+
|
57
|
+
if grep_query.empty?
|
58
|
+
reset_grep
|
59
|
+
elsif count == 0
|
60
|
+
Notifier.instance.show_error "No matches found: \"#{grep_query}\""
|
61
|
+
reset_grep
|
62
|
+
else
|
63
|
+
Notifier.instance.show_message "#{count} statuses found: \"#{grep_query}\""
|
64
|
+
scroll_manager.move_to_top
|
65
|
+
refresh
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def grep_query
|
70
|
+
@grep_query || ''
|
71
|
+
end
|
6
72
|
|
7
73
|
def initialize
|
8
74
|
super
|
@@ -10,10 +76,12 @@ module Twterm
|
|
10
76
|
@status_ids = []
|
11
77
|
end
|
12
78
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
79
|
+
def open_link
|
80
|
+
return if highlighted_status.nil?
|
81
|
+
|
82
|
+
status = highlighted_status
|
83
|
+
urls = status.urls.map(&:expanded_url) + status.media.map(&:expanded_url)
|
84
|
+
urls.each(&Launchy.method(:open))
|
17
85
|
end
|
18
86
|
|
19
87
|
def prepend(status)
|
@@ -22,21 +90,9 @@ module Twterm
|
|
22
90
|
return if @status_ids.include?(status.id)
|
23
91
|
|
24
92
|
@status_ids << status.id
|
25
|
-
status.split(
|
26
|
-
status.touch!
|
27
|
-
item_prepended
|
28
|
-
refresh
|
29
|
-
end
|
30
|
-
|
31
|
-
def append(status)
|
32
|
-
fail ArgumentError, 'argument must be an instance of Status class' unless status.is_a? Status
|
33
|
-
|
34
|
-
return if @status_ids.include?(status.id)
|
35
|
-
|
36
|
-
@status_ids.unshift(status.id)
|
37
|
-
status.split(@window.maxx - 4)
|
93
|
+
status.split(window.maxx - 4)
|
38
94
|
status.touch!
|
39
|
-
|
95
|
+
scroll_manager.item_prepended!
|
40
96
|
refresh
|
41
97
|
end
|
42
98
|
|
@@ -45,17 +101,53 @@ module Twterm
|
|
45
101
|
Tweetbox.instance.compose(highlighted_status)
|
46
102
|
end
|
47
103
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
104
|
+
def reset_grep
|
105
|
+
# TODO: replace with more general way (issue #170)
|
106
|
+
stdscr.clear
|
107
|
+
Screen.instance.refresh
|
108
|
+
|
109
|
+
@grep_query = ''
|
110
|
+
refresh
|
111
|
+
end
|
112
|
+
|
113
|
+
def respond_to_key(key)
|
114
|
+
case key
|
115
|
+
when ?c
|
116
|
+
show_conversation
|
117
|
+
when ?d, 4
|
118
|
+
10.times { scroll_manager.move_down }
|
119
|
+
when ?D
|
120
|
+
destroy_status
|
121
|
+
when ?F
|
122
|
+
favorite
|
123
|
+
when ?g
|
124
|
+
scroll_manager.move_to_top
|
125
|
+
when ?G
|
126
|
+
scroll_manager.move_to_bottom
|
127
|
+
when ?j, 14, Curses::Key::DOWN
|
128
|
+
scroll_manager.move_down
|
129
|
+
when ?k, 16, Curses::Key::UP
|
130
|
+
scroll_manager.move_up
|
131
|
+
when ?o
|
132
|
+
open_link
|
133
|
+
when ?r
|
134
|
+
reply
|
135
|
+
when ?R
|
136
|
+
retweet
|
137
|
+
when 18
|
138
|
+
fetch
|
139
|
+
when ?u, 21
|
140
|
+
10.times { scroll_manager.move_up }
|
141
|
+
when ?U
|
142
|
+
show_user
|
143
|
+
when ?/
|
144
|
+
grep
|
145
|
+
when ?q
|
146
|
+
reset_grep
|
54
147
|
else
|
55
|
-
|
56
|
-
refresh
|
57
|
-
end
|
148
|
+
return false
|
58
149
|
end
|
150
|
+
true
|
59
151
|
end
|
60
152
|
|
61
153
|
def retweet
|
@@ -65,18 +157,10 @@ module Twterm
|
|
65
157
|
end
|
66
158
|
end
|
67
159
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
delete(status.id)
|
73
|
-
refresh
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def delete(status_id)
|
78
|
-
@status_ids.delete(status_id)
|
79
|
-
refresh
|
160
|
+
def show_conversation
|
161
|
+
return if highlighted_status.nil?
|
162
|
+
tab = Tab::ConversationTab.new(highlighted_status.id)
|
163
|
+
TabManager.instance.add_and_show(tab)
|
80
164
|
end
|
81
165
|
|
82
166
|
def show_user
|
@@ -86,21 +170,15 @@ module Twterm
|
|
86
170
|
TabManager.instance.add_and_show(user_tab)
|
87
171
|
end
|
88
172
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
urls = status.urls.map(&:expanded_url) + status.media.map(&:expanded_url)
|
93
|
-
urls.each(&Launchy.method(:open))
|
94
|
-
end
|
95
|
-
|
96
|
-
def show_conversation
|
97
|
-
return if highlighted_status.nil?
|
98
|
-
tab = Tab::ConversationTab.new(highlighted_status.id)
|
99
|
-
TabManager.instance.add_and_show(tab)
|
100
|
-
end
|
173
|
+
def statuses
|
174
|
+
statuses = @status_ids.map { |id| Status.find(id) }.reject(&:nil?)
|
175
|
+
@status_ids = statuses.map(&:id)
|
101
176
|
|
102
|
-
|
103
|
-
|
177
|
+
if grep_query.empty?
|
178
|
+
statuses
|
179
|
+
else
|
180
|
+
statuses.select { |s| s.grepped_with?(grep_query) }
|
181
|
+
end
|
104
182
|
end
|
105
183
|
|
106
184
|
def touch_statuses
|
@@ -110,136 +188,102 @@ module Twterm
|
|
110
188
|
def update
|
111
189
|
current_line = 0
|
112
190
|
|
113
|
-
|
191
|
+
offset = scroll_manager.offset
|
192
|
+
index = scroll_manager.index
|
114
193
|
|
115
194
|
return if offset < 0
|
116
195
|
|
117
196
|
statuses.reverse.drop(offset).each.with_index(offset) do |status, i|
|
118
|
-
formatted_lines = status.split(
|
119
|
-
if current_line + formatted_lines + 2 >
|
120
|
-
|
197
|
+
formatted_lines = status.split(window.maxx - 4).count
|
198
|
+
if current_line + formatted_lines + 2 > window.maxy
|
199
|
+
scroll_manager.last = i
|
121
200
|
break
|
122
201
|
end
|
123
202
|
|
124
203
|
posy = current_line
|
125
204
|
|
126
205
|
if index == i
|
127
|
-
|
206
|
+
window.with_color(:black, :magenta) do
|
128
207
|
(formatted_lines + 1).times do |j|
|
129
|
-
|
130
|
-
|
208
|
+
window.setpos(posy + j, 0)
|
209
|
+
window.addch(' ')
|
131
210
|
end
|
132
211
|
end
|
133
212
|
end
|
134
213
|
|
135
|
-
|
214
|
+
window.setpos(current_line, 2)
|
136
215
|
|
137
|
-
|
138
|
-
|
139
|
-
|
216
|
+
window.bold do
|
217
|
+
window.with_color(status.user.color) do
|
218
|
+
window.addstr(status.user.name)
|
140
219
|
end
|
141
220
|
end
|
142
221
|
|
143
|
-
|
222
|
+
window.addstr(" (@#{status.user.screen_name}) [#{status.date}] ")
|
144
223
|
|
145
224
|
unless status.retweeted_by.nil?
|
146
|
-
|
147
|
-
|
148
|
-
|
225
|
+
window.addstr('(retweeted by ')
|
226
|
+
window.bold do
|
227
|
+
window.addstr("@#{status.retweeted_by.screen_name}")
|
149
228
|
end
|
150
|
-
|
229
|
+
window.addstr(') ')
|
151
230
|
end
|
152
231
|
|
153
232
|
if status.favorited?
|
154
|
-
|
155
|
-
|
233
|
+
window.with_color(:black, :yellow) do
|
234
|
+
window.addch(' ')
|
156
235
|
end
|
157
236
|
|
158
|
-
|
237
|
+
window.addch(' ')
|
159
238
|
end
|
160
239
|
|
161
240
|
if status.retweeted?
|
162
|
-
|
163
|
-
|
241
|
+
window.with_color(:black, :green) do
|
242
|
+
window.addch(' ')
|
164
243
|
end
|
165
|
-
|
244
|
+
window.addch(' ')
|
166
245
|
end
|
167
246
|
|
168
247
|
if status.favorite_count > 0
|
169
|
-
|
170
|
-
|
248
|
+
window.with_color(:yellow) do
|
249
|
+
window.addstr("#{status.favorite_count}fav#{status.favorite_count > 1 ? 's' : ''}")
|
171
250
|
end
|
172
|
-
|
251
|
+
window.addch(' ')
|
173
252
|
end
|
174
253
|
|
175
254
|
if status.retweet_count > 0
|
176
|
-
|
177
|
-
|
255
|
+
window.with_color(:green) do
|
256
|
+
window.addstr("#{status.retweet_count}RT#{status.retweet_count > 1 ? 's' : ''}")
|
178
257
|
end
|
179
|
-
|
258
|
+
window.addch(' ')
|
180
259
|
end
|
181
260
|
|
182
|
-
status.split(
|
261
|
+
status.split(window.maxx - 4).each do |line|
|
183
262
|
current_line += 1
|
184
|
-
|
185
|
-
|
263
|
+
window.setpos(current_line, 2)
|
264
|
+
window.addstr(line)
|
186
265
|
end
|
187
266
|
|
188
267
|
current_line += 2
|
189
268
|
end
|
190
269
|
|
191
|
-
draw_scroll_bar
|
192
|
-
|
193
|
-
@window.refresh
|
194
|
-
|
195
270
|
UserWindow.instance.update(highlighted_status.user) unless highlighted_status.nil?
|
196
|
-
show_help
|
197
|
-
end
|
198
|
-
|
199
|
-
def respond_to_key(key)
|
200
|
-
return true if super
|
201
|
-
|
202
|
-
case key
|
203
|
-
when 'c'
|
204
|
-
show_conversation
|
205
|
-
when 'D'
|
206
|
-
destroy_status
|
207
|
-
when 'F'
|
208
|
-
favorite
|
209
|
-
when 'o'
|
210
|
-
open_link
|
211
|
-
when 'r'
|
212
|
-
reply
|
213
|
-
when 'R'
|
214
|
-
retweet
|
215
|
-
when 18
|
216
|
-
fetch
|
217
|
-
when 'U'
|
218
|
-
show_user
|
219
|
-
else
|
220
|
-
return false
|
221
|
-
end
|
222
|
-
true
|
223
271
|
end
|
224
272
|
|
225
273
|
private
|
226
274
|
|
227
275
|
def highlighted_status
|
228
|
-
id = @status_ids[count - index - 1]
|
276
|
+
id = @status_ids[scroll_manager.count - scroll_manager.index - 1]
|
229
277
|
Status.find(id)
|
230
278
|
end
|
231
279
|
|
232
|
-
def count
|
233
|
-
@status_ids.count
|
234
|
-
end
|
235
|
-
|
236
280
|
def offset_from_bottom
|
237
281
|
return @offset_from_bottom unless @offset_from_bottom.nil?
|
238
282
|
|
239
283
|
height = 0
|
240
284
|
statuses.each.with_index(-1) do |status, i|
|
241
|
-
height += status.split(
|
242
|
-
if height >=
|
285
|
+
height += status.split(window.maxx - 4).count + 2
|
286
|
+
if height >= window.maxy
|
243
287
|
@offset_from_bottom = i
|
244
288
|
return i
|
245
289
|
end
|
@@ -247,13 +291,18 @@ module Twterm
|
|
247
291
|
count
|
248
292
|
end
|
249
293
|
|
250
|
-
def
|
251
|
-
@
|
252
|
-
|
294
|
+
def scroll_manager
|
295
|
+
return @scroll_manager unless @scroll_manager.nil?
|
296
|
+
|
297
|
+
@scroll_manager = ScrollManager.new
|
298
|
+
@scroll_manager.delegate = self
|
299
|
+
@scroll_manager.after_move { refresh }
|
300
|
+
@scroll_manager
|
253
301
|
end
|
254
302
|
|
255
|
-
def
|
256
|
-
|
303
|
+
def sort
|
304
|
+
@status_ids &= Status.all.map(&:id)
|
305
|
+
@status_ids.sort_by! { |id| Status.find(id).appeared_at }
|
257
306
|
end
|
258
307
|
end
|
259
308
|
end
|
@@ -3,6 +3,18 @@ module Twterm
|
|
3
3
|
class TimelineTab
|
4
4
|
include StatusesTab
|
5
5
|
|
6
|
+
def close
|
7
|
+
fail NotClosableError
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch
|
11
|
+
@client.home_timeline do |statuses|
|
12
|
+
statuses.each(&method(:prepend))
|
13
|
+
sort
|
14
|
+
yield if block_given?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
6
18
|
def initialize(client)
|
7
19
|
fail ArgumentError, 'argument must be an instance of Client class' unless client.is_a? Client
|
8
20
|
|
@@ -11,23 +23,9 @@ module Twterm
|
|
11
23
|
@client.on_timeline_status(&method(:prepend))
|
12
24
|
@title = 'Timeline'
|
13
25
|
|
14
|
-
fetch { move_to_top }
|
26
|
+
fetch { scroll_manager.move_to_top }
|
15
27
|
@auto_reloader = Scheduler.new(180) { fetch }
|
16
28
|
end
|
17
|
-
|
18
|
-
def fetch
|
19
|
-
Thread.new do
|
20
|
-
@client.home_timeline do |statuses|
|
21
|
-
statuses.each(&method(:prepend))
|
22
|
-
sort
|
23
|
-
yield if block_given?
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def close
|
29
|
-
fail NotClosableError
|
30
|
-
end
|
31
29
|
end
|
32
30
|
end
|
33
31
|
end
|
data/lib/twterm/tab/user_tab.rb
CHANGED
@@ -6,17 +6,17 @@ module Twterm
|
|
6
6
|
|
7
7
|
attr_reader :user
|
8
8
|
|
9
|
-
def
|
10
|
-
|
9
|
+
def ==(other)
|
10
|
+
other.is_a?(self.class) && user == other.user
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def close
|
14
|
+
@auto_reloader.kill if @auto_reloader
|
15
|
+
super
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
18
|
+
def dump
|
19
|
+
@user.id
|
20
20
|
end
|
21
21
|
|
22
22
|
def fetch
|
@@ -27,17 +27,17 @@ module Twterm
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
|
32
|
-
super
|
33
|
-
end
|
30
|
+
def initialize(user_id)
|
31
|
+
super()
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
User.find_or_fetch(user_id) do |user|
|
34
|
+
@user = user
|
35
|
+
@title = "@#{@user.screen_name}"
|
36
|
+
TabManager.instance.refresh_window
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
fetch { scroll_manager.move_to_top }
|
39
|
+
@auto_reloader = Scheduler.new(120) { fetch }
|
40
|
+
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
data/lib/twterm/tab_manager.rb
CHANGED
@@ -5,16 +5,9 @@ module Twterm
|
|
5
5
|
|
6
6
|
DUMPED_TABS_FILE = "#{ENV['HOME']}/.twterm/dumped_tabs"
|
7
7
|
|
8
|
-
def initialize
|
9
|
-
@tabs = []
|
10
|
-
@index = 0
|
11
|
-
@history = []
|
12
|
-
|
13
|
-
@window = stdscr.subwin(3, stdscr.maxx - 30, 0, 0)
|
14
|
-
end
|
15
|
-
|
16
8
|
def add(tab_to_add)
|
17
9
|
fail ArgumentError, 'argument must be an instance of Tab::Base' unless tab_to_add.is_a? Tab::Base
|
10
|
+
|
18
11
|
@tabs.each.with_index do |tab, i|
|
19
12
|
next unless tab == tab_to_add
|
20
13
|
@index = i
|
@@ -35,28 +28,6 @@ module Twterm
|
|
35
28
|
result
|
36
29
|
end
|
37
30
|
|
38
|
-
def current_tab
|
39
|
-
@history.unshift(@index).uniq!
|
40
|
-
@tabs[@index]
|
41
|
-
end
|
42
|
-
|
43
|
-
def show_next
|
44
|
-
@index = (@index + 1) % @tabs.count
|
45
|
-
current_tab.refresh
|
46
|
-
refresh_window
|
47
|
-
end
|
48
|
-
|
49
|
-
def show_previous
|
50
|
-
@index = (@index - 1) % @tabs.count
|
51
|
-
current_tab.refresh
|
52
|
-
refresh_window
|
53
|
-
end
|
54
|
-
|
55
|
-
def open_new
|
56
|
-
tab = Tab::New::Start.new
|
57
|
-
add_and_show(tab)
|
58
|
-
end
|
59
|
-
|
60
31
|
def close
|
61
32
|
current_tab.close
|
62
33
|
@tabs.delete_at(@index)
|
@@ -69,9 +40,19 @@ module Twterm
|
|
69
40
|
Notifier.instance.show_error 'This tab cannot be closed'
|
70
41
|
end
|
71
42
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
43
|
+
def current_tab
|
44
|
+
@history.unshift(@index).uniq!
|
45
|
+
@tabs[@index]
|
46
|
+
end
|
47
|
+
|
48
|
+
def dump_tabs
|
49
|
+
data = @tabs.each_with_object([]) do |tab, arr|
|
50
|
+
next unless tab.is_a? Tab::Dumpable
|
51
|
+
arr << [tab.class, tab.title, tab.dump]
|
52
|
+
end
|
53
|
+
File.open(DUMPED_TABS_FILE, 'w', 0600) do |f|
|
54
|
+
f.write data.to_yaml
|
55
|
+
end
|
75
56
|
end
|
76
57
|
|
77
58
|
def each_tab(&block)
|
@@ -80,8 +61,25 @@ module Twterm
|
|
80
61
|
end
|
81
62
|
end
|
82
63
|
|
64
|
+
def initialize
|
65
|
+
@tabs = []
|
66
|
+
@index = 0
|
67
|
+
@history = []
|
68
|
+
|
69
|
+
@window = stdscr.subwin(3, stdscr.maxx - 30, 0, 0)
|
70
|
+
end
|
71
|
+
|
72
|
+
def open_new
|
73
|
+
tab = Tab::New::Start.new
|
74
|
+
add_and_show(tab)
|
75
|
+
end
|
76
|
+
|
83
77
|
def recover_tabs
|
84
|
-
|
78
|
+
unless File.exist? DUMPED_TABS_FILE
|
79
|
+
tab = Tab::KeyAssignmentsCheatsheet.new
|
80
|
+
add(tab)
|
81
|
+
return
|
82
|
+
end
|
85
83
|
|
86
84
|
data = YAML.load(File.read(DUMPED_TABS_FILE))
|
87
85
|
data.each do |klass, title, arg|
|
@@ -92,16 +90,6 @@ module Twterm
|
|
92
90
|
Notifier.instance.show_error 'Failed to recover tabs'
|
93
91
|
end
|
94
92
|
|
95
|
-
def dump_tabs
|
96
|
-
data = @tabs.each_with_object([]) do |tab, arr|
|
97
|
-
next unless tab.is_a? Tab::Dumpable
|
98
|
-
arr << [tab.class, tab.title, tab.dump]
|
99
|
-
end
|
100
|
-
File.open(DUMPED_TABS_FILE, 'w', 0600) do |f|
|
101
|
-
f.write data.to_yaml
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
93
|
def refresh_window
|
106
94
|
@window.clear
|
107
95
|
current_tab_id = current_tab.object_id
|
@@ -137,5 +125,22 @@ module Twterm
|
|
137
125
|
end
|
138
126
|
true
|
139
127
|
end
|
128
|
+
|
129
|
+
def show_next
|
130
|
+
@index = (@index + 1) % @tabs.count
|
131
|
+
current_tab.refresh
|
132
|
+
refresh_window
|
133
|
+
end
|
134
|
+
|
135
|
+
def show_previous
|
136
|
+
@index = (@index - 1) % @tabs.count
|
137
|
+
current_tab.refresh
|
138
|
+
refresh_window
|
139
|
+
end
|
140
|
+
|
141
|
+
def switch(tab)
|
142
|
+
close
|
143
|
+
add_and_show(tab)
|
144
|
+
end
|
140
145
|
end
|
141
146
|
end
|