twterm 1.0.8 → 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/twterm.rb +2 -1
- data/lib/twterm/app.rb +9 -6
- data/lib/twterm/client.rb +19 -12
- data/lib/twterm/list.rb +31 -0
- data/lib/twterm/screen.rb +1 -1
- data/lib/twterm/status.rb +19 -2
- data/lib/twterm/tab/base.rb +1 -1
- data/lib/twterm/tab/conversation_tab.rb +29 -11
- data/lib/twterm/tab/dumpable.rb +21 -0
- data/lib/twterm/tab/list_tab.rb +15 -9
- data/lib/twterm/tab/new/list.rb +1 -1
- data/lib/twterm/tab/new/search.rb +2 -1
- data/lib/twterm/tab/new/user.rb +11 -8
- data/lib/twterm/tab/scrollable.rb +1 -1
- data/lib/twterm/tab/search_tab.rb +11 -0
- data/lib/twterm/tab/statuses_tab.rb +4 -2
- data/lib/twterm/tab/user_tab.rb +14 -8
- data/lib/twterm/tab_manager.rb +24 -0
- data/lib/twterm/user.rb +7 -0
- data/lib/twterm/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b7f3f957fa6bb231072502fd2794d212db4547e
|
4
|
+
data.tar.gz: 83aecc6b84ed61620f52b69f6b65c91b6d1af67b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3b1748a40af7f4a32b93568422e0cd65dbe6a9e7a12818567e8aff5142639af6396df93febdffd0f93a19afd9020bf4ac5f86ad468f60b00c5e8cdb597ee5ee
|
7
|
+
data.tar.gz: 6df0822a5f0d59a9f1e2e260e2e43a2b5997a7a36426f5dc786f85283514c9d44ddd9ca74dc41fd7ff1fbc83085bf2eb84a6b4af8b12f33b3438a91ec7d3438c
|
data/lib/twterm.rb
CHANGED
@@ -34,6 +34,7 @@ require 'twterm/scheduler'
|
|
34
34
|
require 'twterm/status'
|
35
35
|
require 'twterm/tab_manager'
|
36
36
|
require 'twterm/tab/base'
|
37
|
+
require 'twterm/tab/dumpable'
|
37
38
|
require 'twterm/tab/exceptions'
|
38
39
|
require 'twterm/tab/scrollable'
|
39
40
|
require 'twterm/tab/statuses_tab'
|
@@ -54,6 +55,6 @@ require 'twterm/version'
|
|
54
55
|
|
55
56
|
module Twterm
|
56
57
|
class Conf
|
57
|
-
REQUIRE_VERSION = '1.0.
|
58
|
+
REQUIRE_VERSION = '1.0.9'
|
58
59
|
end
|
59
60
|
end
|
data/lib/twterm/app.rb
CHANGED
@@ -19,6 +19,7 @@ module Twterm
|
|
19
19
|
|
20
20
|
mentions_tab = Tab::MentionsTab.new(client)
|
21
21
|
TabManager.instance.add(mentions_tab)
|
22
|
+
TabManager.instance.recover_tabs
|
22
23
|
|
23
24
|
Screen.instance.refresh
|
24
25
|
|
@@ -37,15 +38,17 @@ module Twterm
|
|
37
38
|
|
38
39
|
def register_interruption_handler(&block)
|
39
40
|
fail ArgumentError, 'no block given' unless block_given?
|
40
|
-
Signal.trap(:INT)
|
41
|
-
block.call
|
42
|
-
end
|
41
|
+
Signal.trap(:INT) { block.call }
|
43
42
|
end
|
44
43
|
|
45
44
|
def reset_interruption_handler
|
46
|
-
Signal.trap(:INT)
|
47
|
-
|
48
|
-
|
45
|
+
Signal.trap(:INT) { App.instance.quit }
|
46
|
+
end
|
47
|
+
|
48
|
+
def quit
|
49
|
+
Curses.close_screen
|
50
|
+
TabManager.instance.dump_tabs
|
51
|
+
exit
|
49
52
|
end
|
50
53
|
|
51
54
|
private
|
data/lib/twterm/client.rb
CHANGED
@@ -43,9 +43,7 @@ module Twterm
|
|
43
43
|
|
44
44
|
def stream
|
45
45
|
@stream_client.on_friends do
|
46
|
-
|
47
|
-
|
48
|
-
Notifier.instance.show_message 'Connection established'
|
46
|
+
Notifier.instance.show_message 'Connection established' unless @stream_connected
|
49
47
|
@stream_connected = true
|
50
48
|
end
|
51
49
|
|
@@ -117,13 +115,19 @@ module Twterm
|
|
117
115
|
end
|
118
116
|
end
|
119
117
|
|
118
|
+
def list(list_id)
|
119
|
+
send_request do
|
120
|
+
yield List.new(@rest_client.list(list_id))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
120
124
|
def lists
|
121
125
|
send_request do
|
122
126
|
yield @rest_client.lists.map { |list| List.new(list) }
|
123
127
|
end
|
124
128
|
end
|
125
129
|
|
126
|
-
def
|
130
|
+
def list_timeline(list)
|
127
131
|
fail ArgumentError, 'argument must be an instance of List class' unless list.is_a? List
|
128
132
|
send_request do
|
129
133
|
yield @rest_client.list_timeline(list.id, count: 100).select(&@mute_filter).map(&CREATE_STATUS_PROC)
|
@@ -144,11 +148,12 @@ module Twterm
|
|
144
148
|
|
145
149
|
def show_user(query)
|
146
150
|
send_request do
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
151
|
+
user =
|
152
|
+
begin
|
153
|
+
User.new(@rest_client.user(query))
|
154
|
+
rescue Twitter::Error::NotFound
|
155
|
+
nil
|
156
|
+
end
|
152
157
|
yield user
|
153
158
|
end
|
154
159
|
end
|
@@ -249,9 +254,11 @@ module Twterm
|
|
249
254
|
begin
|
250
255
|
block.call
|
251
256
|
rescue Twitter::Error => e
|
252
|
-
Notifier.instance.show_error
|
253
|
-
|
254
|
-
|
257
|
+
Notifier.instance.show_error "Failed to send request: #{e.message}"
|
258
|
+
if e.message == 'getaddrinfo: nodename nor servname provided, or not known'
|
259
|
+
sleep 10
|
260
|
+
retry
|
261
|
+
end
|
255
262
|
end
|
256
263
|
end
|
257
264
|
end
|
data/lib/twterm/list.rb
CHANGED
@@ -2,8 +2,17 @@ module Twterm
|
|
2
2
|
class List
|
3
3
|
attr_reader :id, :name, :slug, :full_name, :mode, :description, :member_count, :subscriber_count
|
4
4
|
|
5
|
+
@@instances = {}
|
6
|
+
|
5
7
|
def initialize(list)
|
6
8
|
@id = list.id
|
9
|
+
update!(list)
|
10
|
+
|
11
|
+
@@instances[@id] = self
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def update!(list)
|
7
16
|
@name = list.name
|
8
17
|
@slug = list.slug
|
9
18
|
@full_name = list.full_name
|
@@ -11,10 +20,32 @@ module Twterm
|
|
11
20
|
@description = list.description.is_a?(Twitter::NullObject) ? '' : list.description
|
12
21
|
@member_count = list.member_count
|
13
22
|
@subscriber_count = list.subscriber_count
|
23
|
+
|
24
|
+
self
|
14
25
|
end
|
15
26
|
|
16
27
|
def ==(other)
|
17
28
|
other.is_a?(self.class) && id == other.id
|
18
29
|
end
|
30
|
+
|
31
|
+
def self.new(list)
|
32
|
+
instance = find(list.id)
|
33
|
+
instance.nil? ? super : instance.update!(list)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find(id)
|
37
|
+
@@instances[id]
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.find_or_fetch(id)
|
41
|
+
instance = find(id)
|
42
|
+
(yield(instance) && return) if instance
|
43
|
+
|
44
|
+
Client.current.list(id) { |list| yield list }
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.all
|
48
|
+
@@instances.values
|
49
|
+
end
|
19
50
|
end
|
20
51
|
end
|
data/lib/twterm/screen.rb
CHANGED
data/lib/twterm/status.rb
CHANGED
@@ -89,14 +89,24 @@ module Twterm
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def in_reply_to_status(&block)
|
92
|
-
|
92
|
+
if @in_reply_to_status_id.nil?
|
93
|
+
block.call(nil)
|
94
|
+
return
|
95
|
+
end
|
93
96
|
|
94
97
|
status = Status.find(@in_reply_to_status_id)
|
95
|
-
|
98
|
+
unless status.nil?
|
99
|
+
block.call(status)
|
100
|
+
return
|
101
|
+
end
|
96
102
|
|
97
103
|
Client.current.show_status(@in_reply_to_status_id, &block)
|
98
104
|
end
|
99
105
|
|
106
|
+
def replies
|
107
|
+
Status.all.select { |s| s.in_reply_to_status_id == id }
|
108
|
+
end
|
109
|
+
|
100
110
|
def retweeted_by
|
101
111
|
User.find(@retweeted_by_user_id)
|
102
112
|
end
|
@@ -122,6 +132,13 @@ module Twterm
|
|
122
132
|
@@instances[id]
|
123
133
|
end
|
124
134
|
|
135
|
+
def find_or_fetch(id)
|
136
|
+
instance = find(id)
|
137
|
+
(yield(instance) && return) if instance
|
138
|
+
|
139
|
+
Client.current.show_status(id) { |status| yield status }
|
140
|
+
end
|
141
|
+
|
125
142
|
def parse_time(time)
|
126
143
|
(time.is_a?(String) ? Time.parse(time) : time.dup).localtime
|
127
144
|
end
|
data/lib/twterm/tab/base.rb
CHANGED
@@ -2,30 +2,48 @@ module Twterm
|
|
2
2
|
module Tab
|
3
3
|
class ConversationTab
|
4
4
|
include StatusesTab
|
5
|
+
include Dumpable
|
5
6
|
|
6
7
|
attr_reader :status
|
7
8
|
|
8
|
-
def initialize(
|
9
|
-
fail ArgumentError, 'argument must be an instance of Status class' unless status.is_a? Status
|
10
|
-
|
9
|
+
def initialize(status_id)
|
11
10
|
@title = 'Conversation'
|
12
|
-
|
13
11
|
super()
|
14
|
-
|
15
|
-
|
12
|
+
|
13
|
+
Status.find_or_fetch(status_id) do |status|
|
14
|
+
@status = status
|
15
|
+
|
16
|
+
append(status)
|
17
|
+
move_to_top
|
18
|
+
Thread.new { fetch_in_reply_to_status(status) }
|
19
|
+
Thread.new { fetch_replies(status) }
|
20
|
+
end
|
16
21
|
end
|
17
22
|
|
18
|
-
def
|
19
|
-
status.in_reply_to_status do |
|
20
|
-
return if
|
21
|
-
append(
|
22
|
-
|
23
|
+
def fetch_in_reply_to_status(status)
|
24
|
+
status.in_reply_to_status do |in_reply_to|
|
25
|
+
return if in_reply_to.nil?
|
26
|
+
append(in_reply_to)
|
27
|
+
sort
|
28
|
+
Thread.new { fetch_in_reply_to_status(in_reply_to) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def fetch_replies(status)
|
33
|
+
status.replies.each do |reply|
|
34
|
+
prepend(reply)
|
35
|
+
sort
|
36
|
+
Thread.new { fetch_replies(reply) }
|
23
37
|
end
|
24
38
|
end
|
25
39
|
|
26
40
|
def ==(other)
|
27
41
|
other.is_a?(self.class) && status == other.status
|
28
42
|
end
|
43
|
+
|
44
|
+
def dump
|
45
|
+
@status.id
|
46
|
+
end
|
29
47
|
end
|
30
48
|
end
|
31
49
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Twterm
|
2
|
+
module Tab
|
3
|
+
module Dumpable
|
4
|
+
def dump
|
5
|
+
fail NotImplementedError 'dump method must be implemented'
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.included(klass)
|
9
|
+
klass.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def recover(title, arg)
|
14
|
+
tab = new(arg)
|
15
|
+
tab.title = title
|
16
|
+
tab
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/twterm/tab/list_tab.rb
CHANGED
@@ -2,23 +2,25 @@ module Twterm
|
|
2
2
|
module Tab
|
3
3
|
class ListTab
|
4
4
|
include StatusesTab
|
5
|
+
include Dumpable
|
5
6
|
|
6
7
|
attr_reader :list
|
7
8
|
|
8
|
-
def initialize(
|
9
|
-
fail ArgumentError, 'argument must be an instance of List class' unless list.is_a? List
|
10
|
-
|
9
|
+
def initialize(list_id)
|
11
10
|
super()
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
List.find_or_fetch(list_id) do |list|
|
13
|
+
@list = list
|
14
|
+
@title = @list.full_name
|
15
|
+
TabManager.instance.refresh_window
|
16
|
+
fetch { move_to_top }
|
17
|
+
@auto_reloader = Scheduler.new(300) { fetch }
|
18
|
+
end
|
17
19
|
end
|
18
20
|
|
19
21
|
def fetch
|
20
22
|
client = Client.current
|
21
|
-
client.
|
23
|
+
client.list_timeline(@list) do |statuses|
|
22
24
|
statuses.reverse.each(&method(:prepend))
|
23
25
|
sort
|
24
26
|
yield if block_given?
|
@@ -26,13 +28,17 @@ module Twterm
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def close
|
29
|
-
@auto_reloader.kill
|
31
|
+
@auto_reloader.kill if @auto_reloader
|
30
32
|
super
|
31
33
|
end
|
32
34
|
|
33
35
|
def ==(other)
|
34
36
|
other.is_a?(self.class) && list == other.list
|
35
37
|
end
|
38
|
+
|
39
|
+
def dump
|
40
|
+
@list.id
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
data/lib/twterm/tab/new/list.rb
CHANGED
@@ -25,8 +25,9 @@ module Twterm
|
|
25
25
|
|
26
26
|
input_thread = Thread.new do
|
27
27
|
close_screen
|
28
|
+
CompletionManager.instance.set_default_mode!
|
28
29
|
puts "\ninput search query"
|
29
|
-
query = (readline('
|
30
|
+
query = (readline('> ') || '').strip
|
30
31
|
resetter.call
|
31
32
|
|
32
33
|
tab = query.nil? || query.empty? ? Tab::New::Start.new : Tab::SearchTab.new(query)
|
data/lib/twterm/tab/new/user.rb
CHANGED
@@ -31,15 +31,18 @@ module Twterm
|
|
31
31
|
screen_name = (readline('> @') || '').strip
|
32
32
|
resetter.call
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
if screen_name.nil? || screen_name.empty?
|
35
|
+
TabManager.instance.switch(Tab::New::Start.new)
|
36
|
+
else
|
37
|
+
Client.current.show_user(screen_name) do |user|
|
38
|
+
if user.nil?
|
39
|
+
Notifier.instance.show_error 'User not found'
|
40
|
+
tab = Tab::New::Start.new
|
41
|
+
else
|
42
|
+
tab = Tab::UserTab.new(user.id)
|
43
|
+
end
|
44
|
+
TabManager.instance.switch(tab)
|
40
45
|
end
|
41
|
-
|
42
|
-
TabManager.instance.switch(tab)
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
@@ -2,6 +2,7 @@ module Twterm
|
|
2
2
|
module Tab
|
3
3
|
class SearchTab
|
4
4
|
include StatusesTab
|
5
|
+
include Dumpable
|
5
6
|
|
6
7
|
attr_reader :query
|
7
8
|
|
@@ -12,6 +13,7 @@ module Twterm
|
|
12
13
|
@title = "\"#{@query}\""
|
13
14
|
|
14
15
|
fetch { move_to_top }
|
16
|
+
@auto_reloader = Scheduler.new(300) { fetch }
|
15
17
|
end
|
16
18
|
|
17
19
|
def fetch
|
@@ -21,9 +23,18 @@ module Twterm
|
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
26
|
+
def close
|
27
|
+
@auto_reloader.kill if @auto_reloader
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
24
31
|
def ==(other)
|
25
32
|
other.is_a?(self.class) && query == other.query
|
26
33
|
end
|
34
|
+
|
35
|
+
def dump
|
36
|
+
@query
|
37
|
+
end
|
27
38
|
end
|
28
39
|
end
|
29
40
|
end
|
@@ -82,7 +82,7 @@ module Twterm
|
|
82
82
|
def show_user
|
83
83
|
return if highlighted_status.nil?
|
84
84
|
user = highlighted_status.user
|
85
|
-
user_tab = Tab::UserTab.new(user)
|
85
|
+
user_tab = Tab::UserTab.new(user.id)
|
86
86
|
TabManager.instance.add_and_show(user_tab)
|
87
87
|
end
|
88
88
|
|
@@ -95,7 +95,7 @@ module Twterm
|
|
95
95
|
|
96
96
|
def show_conversation
|
97
97
|
return if highlighted_status.nil?
|
98
|
-
tab = Tab::ConversationTab.new(highlighted_status)
|
98
|
+
tab = Tab::ConversationTab.new(highlighted_status.id)
|
99
99
|
TabManager.instance.add_and_show(tab)
|
100
100
|
end
|
101
101
|
|
@@ -112,6 +112,8 @@ module Twterm
|
|
112
112
|
|
113
113
|
@window.clear
|
114
114
|
|
115
|
+
return if offset < 0
|
116
|
+
|
115
117
|
statuses.reverse.drop(offset).each.with_index(offset) do |status, i|
|
116
118
|
formatted_lines = status.split(@window.maxx - 4).count
|
117
119
|
if current_line + formatted_lines + 2 > @window.maxy
|
data/lib/twterm/tab/user_tab.rb
CHANGED
@@ -2,19 +2,21 @@ module Twterm
|
|
2
2
|
module Tab
|
3
3
|
class UserTab
|
4
4
|
include StatusesTab
|
5
|
+
include Dumpable
|
5
6
|
|
6
7
|
attr_reader :user
|
7
8
|
|
8
|
-
def initialize(
|
9
|
-
fail ArgumentError, 'argument must be an instance of User class' unless user.is_a? User
|
10
|
-
|
9
|
+
def initialize(user_id)
|
11
10
|
super()
|
12
11
|
|
13
|
-
|
14
|
-
|
12
|
+
User.find_or_fetch(user_id) do |user|
|
13
|
+
@user = user
|
14
|
+
@title = "@#{@user.screen_name}"
|
15
|
+
TabManager.instance.refresh_window
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
fetch { move_to_top }
|
18
|
+
@auto_reloader = Scheduler.new(120) { fetch }
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
22
|
def fetch
|
@@ -26,13 +28,17 @@ module Twterm
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def close
|
29
|
-
@auto_reloader.kill
|
31
|
+
@auto_reloader.kill if @auto_reloader
|
30
32
|
super
|
31
33
|
end
|
32
34
|
|
33
35
|
def ==(other)
|
34
36
|
other.is_a?(self.class) && user == other.user
|
35
37
|
end
|
38
|
+
|
39
|
+
def dump
|
40
|
+
@user.id
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
data/lib/twterm/tab_manager.rb
CHANGED
@@ -3,6 +3,8 @@ module Twterm
|
|
3
3
|
include Singleton
|
4
4
|
include Curses
|
5
5
|
|
6
|
+
DUMPED_TABS_FILE = "#{ENV['HOME']}/.twterm/dumped_tabs"
|
7
|
+
|
6
8
|
def initialize
|
7
9
|
@tabs = []
|
8
10
|
@index = 0
|
@@ -78,6 +80,28 @@ module Twterm
|
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
83
|
+
def recover_tabs
|
84
|
+
return unless File.exist? DUMPED_TABS_FILE
|
85
|
+
|
86
|
+
data = YAML.load(File.read(DUMPED_TABS_FILE))
|
87
|
+
data.each do |klass, title, arg|
|
88
|
+
tab = klass.recover(title, arg)
|
89
|
+
add(tab)
|
90
|
+
end
|
91
|
+
rescue
|
92
|
+
Notifier.instance.show_error 'Failed to recover tabs'
|
93
|
+
end
|
94
|
+
|
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
|
+
|
81
105
|
def refresh_window
|
82
106
|
@window.clear
|
83
107
|
current_tab_id = current_tab.object_id
|
data/lib/twterm/user.rb
CHANGED
@@ -57,6 +57,13 @@ module Twterm
|
|
57
57
|
@@instances[id]
|
58
58
|
end
|
59
59
|
|
60
|
+
def self.find_or_fetch(id)
|
61
|
+
instance = find(id)
|
62
|
+
(yield(instance) && return) if instance
|
63
|
+
|
64
|
+
Client.current.show_user(id) { |user| yield user }
|
65
|
+
end
|
66
|
+
|
60
67
|
def self.cleanup
|
61
68
|
referenced_users = Status.all.map(&:user)
|
62
69
|
referenced_users.each(&:touch!)
|
data/lib/twterm/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twterm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryota Kameoka
|
@@ -159,6 +159,7 @@ files:
|
|
159
159
|
- lib/twterm/status.rb
|
160
160
|
- lib/twterm/tab/base.rb
|
161
161
|
- lib/twterm/tab/conversation_tab.rb
|
162
|
+
- lib/twterm/tab/dumpable.rb
|
162
163
|
- lib/twterm/tab/exceptions.rb
|
163
164
|
- lib/twterm/tab/favorites.rb
|
164
165
|
- lib/twterm/tab/list_tab.rb
|