twterm 2.2.0 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bce2d4276a631793204a44044b38afaa43f02d2c16bcc6daf68653288d1c5e12
4
- data.tar.gz: e1307f6b9623eb96f2659406377888283d5a912fd30caf0d20737852a62e9b9c
3
+ metadata.gz: d251a92afa7b450c2da0556f66fe431d6db851633b739601e0c47cb5ad45baa5
4
+ data.tar.gz: a014a40ac7b5d15859880b157375ebe372e011a4a76153fc93b66075ad3a594c
5
5
  SHA512:
6
- metadata.gz: 43c9cce69344a7e7cc8107793bc79f133ffe1ff134ec422eacbae4ae449661c0b57e7f6b15a241bb5d69db4c58d6bc22065badc9b85f1203bc29e130d8711fb9
7
- data.tar.gz: fdad1dfb3aff8e7f66a94d00db63e5bd3d1e274072c17664e23ebb3de0a38dc26ebc2f9229f8172b14e84c1d71971cea05aba7ca9133eb7f537f03c33dbc8508
6
+ metadata.gz: 5dc37cf71fa46b22cb7e69efc5a3ad09c2fd0a65ba8c77869e6d2a494159aace7691653fe0b001952edef57153a39f5be1715ca0447fc1aa04712130aabc40f5
7
+ data.tar.gz: de94a92f370e94e509063132cd69a8525df015d9825393e7570ba7d55c99466042aaab7d4261ac1e6559b4518703792ead41433a8c2ad1817115e01a7c3e7da3
data/bin/twterm CHANGED
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ if RUBY_VERSION >= '2.5.0'
4
+ Thread.report_on_exception = false
5
+ end
6
+
3
7
  if ARGV.count == 1 && (%w(-v --version).include?(ARGV.first))
4
8
  require 'twterm/version'
5
9
  puts 'twterm version %s' % Twterm::VERSION
data/lib/twterm/app.rb CHANGED
@@ -129,7 +129,7 @@ module Twterm
129
129
 
130
130
  status_repository.before_create do |tweet|
131
131
  tweet.hashtags.each do |hashtag|
132
- hashtag_repository.create(hashtag.text)
132
+ hashtag_repository.create(hashtag)
133
133
  end
134
134
  end
135
135
 
@@ -6,7 +6,7 @@ module Twterm
6
6
  def complete(query)
7
7
  if query.start_with?('#')
8
8
  app.hashtag_repository.all
9
- .map { |tag| "##{tag}" }
9
+ .map { |tag| "##{tag.text}" }
10
10
  .select { |tag| tag.start_with?(query) }
11
11
  elsif query.start_with?('@')
12
12
  app.user_repository.all
@@ -14,7 +14,7 @@ module Twterm
14
14
  operators
15
15
  elsif q.start_with?('#')
16
16
  app.hashtag_repository.all
17
- .map { |tag| "##{tag} " }
17
+ .map { |tag| "##{tag.text} " }
18
18
  .select { |tag| tag.start_with?(q) }
19
19
  elsif q.start_with?('@')
20
20
  app.user_repository.all
@@ -0,0 +1,9 @@
1
+ module Twterm
2
+ class Hashtag
3
+ attr_reader :text
4
+
5
+ def initialize(hashtag)
6
+ @text = hashtag.text
7
+ end
8
+ end
9
+ end
data/lib/twterm/image.rb CHANGED
@@ -36,8 +36,8 @@ class Twterm::Image
36
36
  BlankLine.new
37
37
  end
38
38
 
39
- def bold
40
- Bold.new(self)
39
+ def bold(on = true)
40
+ on ? Bold.new(self) : self
41
41
  end
42
42
 
43
43
  def brackets
@@ -0,0 +1,28 @@
1
+ require 'twterm/image'
2
+
3
+ module Twterm
4
+ module ImageBuilder
5
+ class UserNameImageBuilder
6
+ COLORS = [:red, :blue, :green, :cyan, :yellow, :magenta].freeze
7
+
8
+ # @param user [Twterm::User] user
9
+ def initialize(user)
10
+ @user = user
11
+ end
12
+
13
+ # @return [Twterm::Image] image for the given user
14
+ def build
15
+ !Image.string(user.name).color(color) - Image.whitespace - Image.string("@#{user.screen_name}").parens
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :user
21
+
22
+ # @return [Symbol] color for user
23
+ def color
24
+ COLORS[user.id % 6]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,4 @@
1
+ require 'twterm/hashtag'
1
2
  require 'twterm/repository/abstract_repository'
2
3
 
3
4
  module Twterm
@@ -32,7 +33,7 @@ module Twterm
32
33
  end
33
34
 
34
35
  def type
35
- String
36
+ Hashtag
36
37
  end
37
38
  end
38
39
  end
data/lib/twterm/status.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'concurrent'
2
2
 
3
+ require 'twterm/hashtag'
4
+
3
5
  class Twitter::Tweet
4
6
  attr_reader :quoted_status_id
5
7
 
@@ -11,9 +13,9 @@ end
11
13
 
12
14
  module Twterm
13
15
  class Status
14
- attr_reader :created_at, :favorite_count, :favorited, :id,
16
+ attr_reader :created_at, :favorite_count, :favorited, :hashtags, :id,
15
17
  :in_reply_to_status_id, :media, :retweet_count, :retweeted,
16
- :quoted_status_id, :retweeted_status_id, :text, :url, :urls, :user_id
18
+ :quoted_status_id, :retweeted_status_id, :text, :url, :urls, :user_id, :user_mentions
17
19
  alias_method :favorited?, :favorited
18
20
  alias_method :retweeted?, :retweeted
19
21
 
@@ -50,7 +52,9 @@ module Twterm
50
52
  update!(tweet, is_retweeted_status)
51
53
 
52
54
  @media = tweet.media
55
+ @hashtags = tweet.hashtags.map { |tag| Hashtag.new(tag) }
53
56
  @urls = tweet.urls
57
+ @user_mentions = tweet.user_mentions
54
58
 
55
59
  @user_id = tweet.user.id
56
60
 
@@ -1,5 +1,6 @@
1
1
  require 'twterm/direct_message_composer'
2
2
  require 'twterm/event/direct_message/fetched'
3
+ require 'twterm/image_builder/user_name_image_builder'
3
4
  require 'twterm/subscriber'
4
5
  require 'twterm/tab/base'
5
6
  require 'twterm/tab/loadable'
@@ -29,8 +30,7 @@ module Twterm
29
30
  sender = app.user_repository.find(message.sender_id)
30
31
 
31
32
  header = [
32
- !Image.string(sender.name).color(sender.color),
33
- Image.string("@#{sender.screen_name}").parens,
33
+ ImageBuilder::UserNameImageBuilder.new(sender).build,
34
34
  Image.string(message.date.to_s).brackets,
35
35
  ].intersperse(Image.whitespace).reduce(Image.empty, :-)
36
36
 
@@ -1,5 +1,6 @@
1
1
  require 'twterm/direct_message_composer'
2
2
  require 'twterm/event/direct_message/fetched'
3
+ require 'twterm/image_builder/user_name_image_builder'
3
4
  require 'twterm/subscriber'
4
5
  require 'twterm/tab/base'
5
6
  require 'twterm/tab/loadable'
@@ -26,8 +27,7 @@ module Twterm
26
27
  collocutor = app.user_repository.find(conversation.collocutor_id)
27
28
 
28
29
  header = [
29
- !Image.string(collocutor.name).color(collocutor.color),
30
- Image.string("@#{collocutor.screen_name}").parens,
30
+ ImageBuilder::UserNameImageBuilder.new(collocutor).build,
31
31
  Image.string(conversation.updated_at.to_s).brackets,
32
32
  ].intersperse(Image.whitespace).reduce(Image.empty, :-)
33
33
 
@@ -73,9 +73,10 @@ module Twterm
73
73
  return Image.string(initially_loaded? ? 'No results found' : 'Loading...') if items.empty?
74
74
 
75
75
  drawable_items.map.with_index(0) do |list, i|
76
- cursor = Image.cursor(2, scroller.current_index?(i))
76
+ curr = scroller.current_index?(i)
77
+ cursor = Image.cursor(2, curr)
77
78
 
78
- summary = Image.string("#{list.full_name} (#{list.member_count} members / #{list.subscriber_count} subscribers)")
79
+ summary = Image.string("#{list.full_name} (#{list.member_count} members / #{list.subscriber_count} subscribers)").bold(curr)
79
80
  desc = Image.string(' ') - Image.string(list.description)
80
81
 
81
82
  cursor - Image.whitespace - (summary | desc)
@@ -100,7 +100,8 @@ module Twterm
100
100
  [
101
101
  *drawable_items
102
102
  .map.with_index(0) { |query, i|
103
- Image.cursor(1, scroller.current_index?(i)) - Image.whitespace - Image.string(query)
103
+ curr = scroller.current_index?(i)
104
+ Image.cursor(1, curr) - Image.whitespace - Image.string(query).bold(curr)
104
105
  },
105
106
  (Image.string(' Loading saved searches...') unless initially_loaded?),
106
107
  ]
@@ -55,7 +55,8 @@ module Twterm
55
55
  def image
56
56
  drawable_items
57
57
  .map.with_index(0) { |item, i|
58
- cursor = Image.cursor(1, scroller.current_index?(i))
58
+ curr = scroller.current_index?(i)
59
+ cursor = Image.cursor(1, curr)
59
60
 
60
61
  desc =
61
62
  case item
@@ -75,7 +76,7 @@ module Twterm
75
76
  'Preferences'
76
77
  end
77
78
 
78
- cursor - Image.whitespace - Image.string(desc)
79
+ cursor - Image.whitespace - Image.string(desc).bold(curr)
79
80
  }
80
81
  .intersperse(Image.blank_line)
81
82
  .reduce(Image.empty, :|)
@@ -21,14 +21,15 @@ module Twterm
21
21
 
22
22
  def image
23
23
  drawable_items.map.with_index do |item, i|
24
- cursor = Image.cursor(1, scroller.current_index?(i))
24
+ curr = scroller.current_index?(i)
25
+ cursor = Image.cursor(1, curr)
25
26
  desc =
26
27
  case item
27
28
  when :notification_backend
28
29
  'Notification backend preferences'
29
30
  end
30
31
 
31
- cursor - Image.whitespace - Image.string(desc)
32
+ cursor - Image.whitespace - Image.string(desc).bold(curr)
32
33
  end
33
34
  .intersperse(Image.blank_line)
34
35
  .reduce(Image.empty) { |acc, x| acc | x }
@@ -17,7 +17,8 @@ module Twterm
17
17
 
18
18
  def image
19
19
  drawable_items.map.with_index do |item, i|
20
- cursor = Image.cursor(1, scroller.current_index?(i))
20
+ curr = scroller.current_index?(i)
21
+ cursor = Image.cursor(1, curr)
21
22
  checkbox = Image.checkbox(app.preferences[:notification_backend, item])
22
23
  desc =
23
24
  case item
@@ -29,7 +30,7 @@ module Twterm
29
30
  'Terminal Notifier backend'
30
31
  end
31
32
 
32
- cursor - Image.whitespace - checkbox - Image.whitespace - Image.string(desc)
33
+ cursor - Image.whitespace - checkbox - Image.whitespace - Image.string(desc).bold(curr)
33
34
  end
34
35
  .intersperse(Image.blank_line)
35
36
  .reduce(Image.empty) { |acc, x| acc | x }
@@ -0,0 +1,226 @@
1
+ require 'addressable/uri'
2
+
3
+ require 'twterm/event/open_uri'
4
+ require 'twterm/hashtag'
5
+ require 'twterm/image'
6
+ require 'twterm/image_builder/user_name_image_builder'
7
+ require 'twterm/publisher'
8
+ require 'twterm/tab/base'
9
+ require 'twterm/tab/dumpable'
10
+ require 'twterm/tab/loadable'
11
+ require 'twterm/tab/scrollable'
12
+
13
+ module Twterm
14
+ module Tab
15
+ class StatusTab < Tab::Base
16
+ include Dumpable
17
+ include Publisher
18
+ include Tab::Scrollable
19
+
20
+ def initialize(app, client, status_id)
21
+ super(app, client)
22
+
23
+ @status_id = status_id
24
+ end
25
+
26
+ def drawable_item_count
27
+ (window.maxy - status.text.split_by_width(window.maxx - 4).count - 6).div(2)
28
+ end
29
+
30
+ def dump
31
+ status_id
32
+ end
33
+
34
+ def image
35
+ if status.nil?
36
+ find_or_fetch_status(status_id).then { render }
37
+ return Image.string('Loading...')
38
+ end
39
+
40
+ if user.nil?
41
+ find_or_fetch_user(status.user_id).then { render }
42
+ return Image.string('Loading...')
43
+ end
44
+
45
+ header = [
46
+ ImageBuilder::UserNameImageBuilder.new(user).build,
47
+ Image.string(status.date.to_s).brackets,
48
+ (Image.whitespace.color(:black, :red) if status.favorited?),
49
+ (Image.whitespace.color(:black, :green) if status.retweeted?),
50
+ ((Image.number(status.favorite_count) - Image.plural(status.favorite_count, 'like')).color(:red) if status.favorite_count.positive?),
51
+ ((Image.number(status.retweet_count) - Image.plural(status.retweet_count, 'RT')).color(:green) if status.retweet_count.positive?),
52
+ ].compact.intersperse(Image.whitespace).reduce(Image.empty, :-)
53
+
54
+ [
55
+ header,
56
+ Image.blank_line,
57
+ *status.text.split_by_width(window.maxx - 4).map { |x| Image.string(x) },
58
+ Image.blank_line,
59
+ Image.blank_line,
60
+ *drawable_items.flat_map.with_index do |item, i|
61
+ curr = scroller.current_index?(i)
62
+ Image.cursor(1, curr) - Image.whitespace - image_for_item(item).bold(curr)
63
+ end.intersperse(Image.blank_line),
64
+ ].reduce(Image.empty) { |acc, x| acc | x }
65
+ end
66
+
67
+ def items
68
+ [
69
+ :reply,
70
+ :favorite,
71
+ :retweet,
72
+ :quote,
73
+ (:destroy if user.id == client.user_id),
74
+ :show_user,
75
+ :open_in_browser,
76
+ *status.media,
77
+ *status.urls,
78
+ *status.hashtags,
79
+ *status.user_mentions,
80
+ ].compact
81
+ end
82
+
83
+ def respond_to_key(key)
84
+ return true if scroller.respond_to_key(key)
85
+
86
+ case key
87
+ when 10
88
+ perform_selected_action
89
+ else
90
+ return false
91
+ end
92
+
93
+ true
94
+ end
95
+
96
+ def title
97
+ user.nil? ? 'Loading...' : "@#{user.screen_name}'s tweet"
98
+ end
99
+
100
+ private
101
+
102
+ attr_reader :status_id
103
+
104
+ def destroy!
105
+ client
106
+ .destroy_status(status)
107
+ .then { app.tab_manager.close }
108
+ end
109
+
110
+ def favorite!
111
+ if status.favorited?
112
+ client.unfavorite(status).then { status.unfavorite! }
113
+ else
114
+ client.favorite(status).then { status.favorite! }
115
+ end
116
+ .then { render }
117
+ end
118
+
119
+ def highlight_with_entity(text, entity)
120
+ starts, ends = entity.indices
121
+ Image.string(text[0...starts]) - Image.string(text[starts...ends]).bold - Image.string(text[y...text.length])
122
+ end
123
+
124
+ # @return [Twterm::Image]
125
+ def image_for_item(item)
126
+ case item
127
+ when :reply
128
+ Image.string('Reply to this tweet')
129
+ when :favorite
130
+ Image.string(status.favorited? ? 'Unlike this tweet' : 'Like this tweet')
131
+ when :retweet
132
+ Image.string(status.retweeted? ? 'Unretweet this tweet' : 'Retweet this tweet')
133
+ when :quote
134
+ Image.string('Quote this tweet')
135
+ when :destroy
136
+ Image.string('Delete this tweet')
137
+ when :show_user
138
+ Image.string("Show user (@#{user.screen_name})")
139
+ when :open_in_browser
140
+ Image.string("Open this tweet in browser (#{status.url})")
141
+ when Addressable::URI
142
+ Image.string(item.to_s)
143
+ when Hashtag
144
+ Image.string("[Hashtag] ##{item.text}")
145
+ when Twitter::Entity::UserMention
146
+ Image.string("[User] #{item.name} (@#{item.screen_name})")
147
+ when Twitter::Entity::URI
148
+ Image.string("[URL] #{item.expanded_url}")
149
+ when Twitter::Media::AnimatedGif
150
+ url = item.video_info.variants.max { |v| v.bitrate }.url
151
+ Image.string("[GIF] #{url}")
152
+ when Twitter::Media::Photo
153
+ Image.string("[Photo] #{item.media_url_https}")
154
+ when Twitter::Media::Video
155
+ url = item.video_info.variants.max { |v| v.bitrate }.url
156
+ Image.string("[Video] #{url}")
157
+ end
158
+ end
159
+
160
+ def perform_selected_action
161
+ item = scroller.current_item
162
+
163
+ case item
164
+ when :reply
165
+ reply!
166
+ when :favorite
167
+ favorite!
168
+ when :retweet
169
+ retweet!
170
+ when :quote
171
+ quote!
172
+ when :destroy
173
+ destroy!
174
+ when :show_user
175
+ show_user!
176
+ when :open_in_browser
177
+ publish(Event::OpenURI.new(status.url))
178
+ when Hashtag
179
+ tab = Tab::Statuses::Search.new(app, client, "##{item.text}")
180
+ app.tab_manager.add_and_show(tab)
181
+ when Twitter::Entity::UserMention
182
+ tab = Tab::UserTab.new(app, client, item.id)
183
+ app.tab_manager.add_and_show(tab)
184
+ when Twitter::Entity::URI
185
+ publish(Event::OpenURI.new(item.expanded_url))
186
+ when Twitter::Media::Photo
187
+ publish(Event::OpenURI.new(item.media_url_https))
188
+ when Twitter::Media::AnimatedGif, Twitter::Media::Video
189
+ url = item.video_info.variants.max { |v| v.bitrate }.url
190
+ publish(Event::OpenURI.new(url))
191
+ end
192
+ end
193
+
194
+ def quote!
195
+ app.tweetbox.quote(status)
196
+ end
197
+
198
+ def reply!
199
+ app.tweetbox.reply(status)
200
+ end
201
+
202
+ def retweet!
203
+ if status.retweeted?
204
+ client.unretweet(status).then { status.unretweet! }
205
+ else
206
+ client.retweet(status).then { status.retweet! }
207
+ end
208
+ .then { render }
209
+ end
210
+
211
+ def show_user!
212
+ user_id = status.user_id
213
+ user_tab = Tab::UserTab.new(app, client, user_id)
214
+ app.tab_manager.add_and_show(user_tab)
215
+ end
216
+
217
+ def status
218
+ app.status_repository.find(status_id)
219
+ end
220
+
221
+ def user
222
+ status.nil? ? nil : app.user_repository.find(status.user_id)
223
+ end
224
+ end
225
+ end
226
+ end
@@ -3,10 +3,12 @@ require 'concurrent'
3
3
  require 'twterm/event/open_uri'
4
4
  require 'twterm/event/status/delete'
5
5
  require 'twterm/event/status_garbage_collected'
6
+ require 'twterm/image_builder/user_name_image_builder'
6
7
  require 'twterm/publisher'
7
8
  require 'twterm/subscriber'
8
9
  require 'twterm/tab/base'
9
10
  require 'twterm/tab/loadable'
11
+ require 'twterm/tab/status_tab'
10
12
  require 'twterm/utils'
11
13
 
12
14
  module Twterm
@@ -134,6 +136,8 @@ module Twterm
134
136
  k = KeyMapper.instance
135
137
 
136
138
  case key
139
+ when 10
140
+ open_status_tab
137
141
  when k[:status, :conversation]
138
142
  show_conversation
139
143
  when k[:status, :destroy]
@@ -221,8 +225,7 @@ module Twterm
221
225
  retweeted_by = app.user_repository.find(status.user_id)
222
226
 
223
227
  header = [
224
- !Image.string(user.name).color(user.color),
225
- Image.string("@#{user.screen_name}").parens,
228
+ ImageBuilder::UserNameImageBuilder.new(user).build,
226
229
  Image.string(original.date.to_s).brackets,
227
230
  (Image.whitespace.color(:black, :red) if original.favorited?),
228
231
  (Image.whitespace.color(:black, :green) if original.retweeted?),
@@ -244,6 +247,15 @@ module Twterm
244
247
  .reduce(Image.empty, :|)
245
248
  end
246
249
 
250
+ def open_status_tab
251
+ status = highlighted_original_status
252
+
253
+ return if status.nil?
254
+
255
+ tab = Tab::StatusTab.new(app, client, highlighted_original_status.id)
256
+ app.tab_manager.add_and_show(tab)
257
+ end
258
+
247
259
  def reload
248
260
  fetch.then do |statuses|
249
261
  statuses.each { |s| append(s) }
@@ -46,9 +46,10 @@ module Twterm
46
46
  return Image.string(initially_loaded? ? 'No lists found' : 'Loading...') if items.empty?
47
47
 
48
48
  drawable_items.map.with_index do |list, i|
49
- cursor = Image.cursor(2, scroller.current_index?(i))
49
+ curr = scroller.current_index?(i)
50
+ cursor = Image.cursor(2, curr)
50
51
 
51
- summary = Image.checkbox(@list_ids.include?(list.id)) - Image.whitespace - Image.string(list.full_name)
52
+ summary = Image.checkbox(@list_ids.include?(list.id)) - Image.whitespace - Image.string(list.full_name).bold(curr)
52
53
  description = Image.string(' ') - Image.string(list.description)
53
54
 
54
55
  cursor - Image.whitespace - (summary | description)
@@ -1,5 +1,6 @@
1
1
  require 'twterm/event/open_uri'
2
2
  require 'twterm/publisher'
3
+ require 'twterm/image_builder/user_name_image_builder'
3
4
  require 'twterm/tab/base'
4
5
  require 'twterm/tab/user_list_management'
5
6
 
@@ -233,7 +234,7 @@ module Twterm
233
234
  return Image.empty
234
235
  end
235
236
 
236
- name = !Image.string(user.name) - Image.whitespace - Image.string("@#{user.screen_name}").parens
237
+ name = ImageBuilder::UserNameImageBuilder.new(user).build
237
238
 
238
239
  badges = [
239
240
  (Image.string('protected').brackets.color(:yellow) if user.protected?),
@@ -264,8 +265,9 @@ module Twterm
264
265
 
265
266
  location = Image.string("Location: #{user.location}")
266
267
 
267
- foo = drawable_items.map.with_index(0) do |item, i|
268
- Image.cursor(1, scroller.current_index?(i)) - Image.whitespace -
268
+ actions = drawable_items.map.with_index(0) do |item, i|
269
+ curr = scroller.current_index?(i)
270
+ Image.cursor(1, curr) - Image.whitespace -
269
271
  case item
270
272
  when :compose_direct_message
271
273
  Image.string('Compose direct message')
@@ -302,11 +304,12 @@ module Twterm
302
304
  when :manage_lists
303
305
  Image.string('Add to / Remove from lists')
304
306
  end
307
+ .bold(curr)
305
308
  end
306
309
  .intersperse(Image.blank_line)
307
310
  .reduce(Image.empty, :|)
308
311
 
309
- [name, badges, status, description, location, foo]
312
+ [name, badges, status, description, location, Image.blank_line | actions]
310
313
  .compact
311
314
  .intersperse(Image.blank_line)
312
315
  .reduce(Image.empty, :|)
@@ -1,6 +1,7 @@
1
1
  require 'concurrent'
2
2
 
3
3
  require 'twterm/event/user_garbage_collected'
4
+ require 'twterm/image_builder/user_name_image_builder'
4
5
  require 'twterm/tab/base'
5
6
  require 'twterm/tab/loadable'
6
7
 
@@ -74,8 +75,7 @@ module Twterm
74
75
  cursor = Image.cursor(2, scroller.current_index?(i))
75
76
 
76
77
  header = [
77
- !Image.string(user.name).color(user.color),
78
- Image.string("@#{user.screen_name}"),
78
+ ImageBuilder::UserNameImageBuilder.new(user).build,
79
79
  (Image.string('protected').brackets.color(:yellow) if user.protected?),
80
80
  (Image.string('verified').brackets.color(:cyan) if user.verified?),
81
81
  ].compact.intersperse(Image.whitespace).reduce(Image.empty, :-)
@@ -45,7 +45,7 @@ module Twterm
45
45
  current_tab.render
46
46
  refresh_window
47
47
  rescue Tab::NotClosableError
48
- publish(Event::Message::Warning.new('this tab cannot be closed', 'this tab cannot be closed'))
48
+ publish(Event::Message::Warning.new('this tab cannot be closed'))
49
49
  end
50
50
 
51
51
  def current_tab
data/lib/twterm/user.rb CHANGED
@@ -1,17 +1,14 @@
1
1
  module Twterm
2
2
  class User
3
- attr_reader :color, :description, :favorites_count, :followers_count,
3
+ attr_reader :description, :favorites_count, :followers_count,
4
4
  :friends_count, :id, :location, :name, :protected,
5
5
  :screen_name, :statuses_count, :url, :verified, :website
6
6
  alias_method :protected?, :protected
7
7
  alias_method :verified?, :verified
8
8
 
9
- COLORS = [:red, :blue, :green, :cyan, :yellow, :magenta]
10
-
11
9
  def initialize(user)
12
10
  @id = user.id
13
11
  update!(user)
14
- @color = COLORS[@id % 6]
15
12
  end
16
13
 
17
14
  def update!(user)
@@ -1,3 +1,3 @@
1
1
  module Twterm
2
- VERSION = '2.2.0'
2
+ VERSION = '2.3.0'
3
3
  end
@@ -0,0 +1,28 @@
1
+ require 'twterm/image_builder/user_name_image_builder'
2
+
3
+ RSpec.describe Twterm::ImageBuilder::UserNameImageBuilder do
4
+
5
+ describe '#build' do
6
+ let(:json) {
7
+ json = JSON.parse(fixture('user.json'), symbolize_names: true)
8
+
9
+ json[:screen_name] = screen_name
10
+ json[:name] = name
11
+
12
+ json
13
+ }
14
+ let(:user) { Twterm::User.new(Twitter::User.new(json)) }
15
+ let(:builder) { described_class.new(user) }
16
+ let(:image) { builder.build }
17
+ let(:screen_name) { 'alice42' }
18
+ let(:name) { 'Alice' }
19
+
20
+ it "builds an image containing user's screen name" do
21
+ expect(image.to_s).to include screen_name
22
+ end
23
+
24
+ it "builds an image containing user's name" do
25
+ expect(image.to_s).to include name
26
+ end
27
+ end
28
+ end
data/twterm.gemspec CHANGED
@@ -32,4 +32,5 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'rake', '~> 12.0'
33
33
  spec.add_development_dependency 'rspec', '~> 3.7.0'
34
34
  spec.add_development_dependency 'rubocop', '~> 0.51.0'
35
+ spec.add_development_dependency 'yard', '~> 0.9.12'
35
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twterm
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryota Kameoka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-20 00:00:00.000000000 Z
11
+ date: 2018-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
194
  version: 0.51.0
195
+ - !ruby/object:Gem::Dependency
196
+ name: yard
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: 0.9.12
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: 0.9.12
195
209
  description: A full-featured TUI Twitter client
196
210
  email:
197
211
  - kameoka.ryota@gmail.com
@@ -253,6 +267,7 @@ files:
253
267
  - lib/twterm/extensions/enumerator/lazy.rb
254
268
  - lib/twterm/extensions/string.rb
255
269
  - lib/twterm/friendship.rb
270
+ - lib/twterm/hashtag.rb
256
271
  - lib/twterm/image.rb
257
272
  - lib/twterm/image/between.rb
258
273
  - lib/twterm/image/blank_line.rb
@@ -264,6 +279,7 @@ files:
264
279
  - lib/twterm/image/parens.rb
265
280
  - lib/twterm/image/string_image.rb
266
281
  - lib/twterm/image/vertical_sequential_image.rb
282
+ - lib/twterm/image_builder/user_name_image_builder.rb
267
283
  - lib/twterm/key_mapper.rb
268
284
  - lib/twterm/key_mapper/abstract_key_mapper.rb
269
285
  - lib/twterm/key_mapper/app_key_mapper.rb
@@ -316,6 +332,7 @@ files:
316
332
  - lib/twterm/tab/rate_limit_status.rb
317
333
  - lib/twterm/tab/scrollable.rb
318
334
  - lib/twterm/tab/searchable.rb
335
+ - lib/twterm/tab/status_tab.rb
319
336
  - lib/twterm/tab/statuses/base.rb
320
337
  - lib/twterm/tab/statuses/cacheable.rb
321
338
  - lib/twterm/tab/statuses/conversation.rb
@@ -357,6 +374,7 @@ files:
357
374
  - spec/twterm/image/parens_spec.rb
358
375
  - spec/twterm/image/string_image_spec.rb
359
376
  - spec/twterm/image/vertical_sequential_image_spec.rb
377
+ - spec/twterm/image_builder/user_name_image_builder_spec.rb
360
378
  - spec/twterm/image_spec.rb
361
379
  - spec/twterm/key_mapper/abstract_key_mapper_spec.rb
362
380
  - spec/twterm/key_mapper/app_key_mapper_spec.rb
@@ -386,7 +404,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
386
404
  version: '0'
387
405
  requirements: []
388
406
  rubyforge_project:
389
- rubygems_version: 2.7.4
407
+ rubygems_version: 2.7.6
390
408
  signing_key:
391
409
  specification_version: 4
392
410
  summary: A full-featured TUI Twitter client