twterm 1.0.1 → 1.0.2

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
  SHA1:
3
- metadata.gz: 328dc78c5c22745104e0ea848f685dd24a38f023
4
- data.tar.gz: e9a4bcc86da9eec70a2fe4f7f97b243985ebecc6
3
+ metadata.gz: b83f1b22f92cf279b15fdb70358d86dca32a00d9
4
+ data.tar.gz: ea0d20227e837aa606fa27d73aaa0cad87e2d0ba
5
5
  SHA512:
6
- metadata.gz: 1e323c03dd2a056f0d0ec4465f06ed0aba8fec49b82fd4b3fe2e8b76134edaea3dc895991c1e00b8f23fcee0753e3288aa14aa5ea7c6d49dd5f5c702006aa3a6
7
- data.tar.gz: 7047e7dfa1e48612ed8be4e9df8c69ee0895dbf63915dbb754b66ac3e82c03b13d65f754580f1d1a56e15da59de15384c0e8711d9ad5d64f479da976686d86fc
6
+ metadata.gz: aad2fda4667c871c79b556360280a160ee4bbbced590bc5bb6e18938c9e0949bd2f454e65c2c97e5c1a99bc016ee80e348426544d8bc50ccc5276dee89784af7
7
+ data.tar.gz: e90142ebc46ec3c38ed1bb9e7a8ea5f09030b6c1306e2823865ae916aee5cca6c65a1a0fe9220aaa9c812d85fda982b4a22213de7056159059996e313f8f75d7
data/bin/twterm CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'twterm'
3
+ require './lib/twterm'
4
4
 
5
5
  Twterm::App.instance.run
@@ -36,6 +36,7 @@ require 'twterm/tab/mentions_tab'
36
36
  require 'twterm/tab/new/start'
37
37
  require 'twterm/tab/new/list'
38
38
  require 'twterm/tab/new/search'
39
+ require 'twterm/tab/new/user'
39
40
  require 'twterm/tab/search_tab'
40
41
  require 'twterm/tab/timeline_tab'
41
42
  require 'twterm/tab/user_tab'
@@ -46,6 +47,6 @@ require 'twterm/version'
46
47
 
47
48
  module Twterm
48
49
  class Conf
49
- REQUIRE_VERSION = '1.0.0'
50
+ REQUIRE_VERSION = '1.0.2'
50
51
  end
51
52
  end
@@ -25,6 +25,8 @@ module Twterm
25
25
  end
26
26
 
27
27
  def run
28
+ run_periodic_cleanup
29
+
28
30
  Screen.instance.wait
29
31
  Screen.instance.refresh
30
32
  end
@@ -41,5 +43,16 @@ module Twterm
41
43
  exit
42
44
  end
43
45
  end
46
+
47
+ private
48
+
49
+ def run_periodic_cleanup
50
+ Thread.new do
51
+ loop do
52
+ sleep 300
53
+ Status.cleanup
54
+ end
55
+ end
56
+ end
44
57
  end
45
58
  end
@@ -7,8 +7,13 @@ module Twterm
7
7
  site: 'https://api.twitter.com'
8
8
  )
9
9
  request_token = consumer.get_request_token
10
- Launchy.open request_token.authorize_url
11
- print 'input PIN: '
10
+ url = request_token.authorize_url
11
+ begin
12
+ Launchy.open(url)
13
+ rescue Launchy::CommandNotFoundError
14
+ puts "Open the following URL to authorize yourself: #{url}"
15
+ end
16
+ print 'Input PIN: '
12
17
  pin = (STDIN.gets || '').strip
13
18
  access_token = request_token.get_access_token(oauth_verifier: pin)
14
19
 
@@ -85,19 +85,19 @@ module Twterm
85
85
 
86
86
  def home_timeline
87
87
  send_request do
88
- yield @rest_client.home_timeline(count: 200).map(&CREATE_STATUS_PROC)
88
+ yield @rest_client.home_timeline(count: 100).map(&CREATE_STATUS_PROC)
89
89
  end
90
90
  end
91
91
 
92
92
  def mentions
93
93
  send_request do
94
- yield @rest_client.mentions(count: 200).map(&CREATE_STATUS_PROC)
94
+ yield @rest_client.mentions(count: 100).map(&CREATE_STATUS_PROC)
95
95
  end
96
96
  end
97
97
 
98
98
  def user_timeline(user_id)
99
99
  send_request do
100
- yield @rest_client.user_timeline(user_id, count: 200).map(&CREATE_STATUS_PROC)
100
+ yield @rest_client.user_timeline(user_id, count: 100).map(&CREATE_STATUS_PROC)
101
101
  end
102
102
  end
103
103
 
@@ -110,7 +110,7 @@ module Twterm
110
110
  def list(list)
111
111
  fail ArgumentError, 'argument must be an instance of List class' unless list.is_a? List
112
112
  send_request do
113
- yield @rest_client.list_timeline(list.id, count: 200).map(&CREATE_STATUS_PROC)
113
+ yield @rest_client.list_timeline(list.id, count: 100).map(&CREATE_STATUS_PROC)
114
114
  end
115
115
  end
116
116
 
@@ -126,6 +126,17 @@ module Twterm
126
126
  end
127
127
  end
128
128
 
129
+ def show_user(query)
130
+ send_request do
131
+ begin
132
+ user = User.new(@rest_client.user(query))
133
+ rescue Twitter::Error::NotFound
134
+ user = nil
135
+ end
136
+ yield user
137
+ end
138
+ end
139
+
129
140
  def favorite(status)
130
141
  return false unless status.is_a? Status
131
142
 
@@ -1,14 +1,15 @@
1
1
  module Twterm
2
2
  class Status
3
- attr_reader :id, :text, :created_at, :created_at_for_sort, :retweet_count, :favorite_count, :in_reply_to_status_id, :favorited, :retweeted, :user, :retweeted_by, :urls, :media
3
+ MAX_CACHED_STATUSES_COUNT = 1000
4
+
5
+ attr_reader :id, :text, :created_at, :created_at_for_sort, :retweet_count, :favorite_count, :in_reply_to_status_id, :favorited, :retweeted, :user, :retweeted_by, :urls, :media, :touched_at
4
6
  alias_method :favorited?, :favorited
5
7
  alias_method :retweeted?, :retweeted
6
8
 
7
- @@instances = []
9
+ @@instances = {}
8
10
 
9
11
  def self.new(tweet)
10
- detector = -> (instance) { instance.id == tweet.id }
11
- instance = @@instances.find(&detector)
12
+ instance = find(tweet.id)
12
13
  instance.nil? ? super : instance.update!(tweet)
13
14
  end
14
15
 
@@ -39,7 +40,9 @@ module Twterm
39
40
 
40
41
  expand_url!
41
42
 
42
- @@instances << self
43
+ @touched_at = Time.now
44
+
45
+ @@instances[id] = self
43
46
  end
44
47
 
45
48
  def update!(tweet)
@@ -79,24 +82,37 @@ module Twterm
79
82
  def in_reply_to_status(&block)
80
83
  block.call(nil) if @in_reply_to_status_id.nil?
81
84
 
82
- status = Status.find_by_in_reply_to_status_id(@in_reply_to_status_id)
85
+ status = Status.find(@in_reply_to_status_id)
83
86
  block.call(status) unless status.nil?
84
87
 
85
88
  Client.current.show_status(@in_reply_to_status_id, &block)
86
89
  end
87
90
 
91
+ def touch!
92
+ @touched_at = Time.now
93
+ end
94
+
88
95
  def ==(other)
89
96
  other.is_a?(self.class) && id == other.id
90
97
  end
91
98
 
92
99
  class << self
93
- def find_by_in_reply_to_status_id(in_reply_to_status_id)
94
- @@instances.find { |status| status.id == in_reply_to_status_id }
100
+ def find(id)
101
+ @@instances[id]
95
102
  end
96
103
 
97
104
  def parse_time(time)
98
105
  (time.is_a?(String) ? Time.parse(time) : time.dup).localtime
99
106
  end
107
+
108
+ def cleanup
109
+ count = MAX_CACHED_STATUSES_COUNT
110
+ return if @@instances.count < count
111
+
112
+ statuses = @@instances.values.sort_by(&:touched_at).take(count)
113
+ status_ids = statuses.map(&:id)
114
+ @@instances = status_ids.zip(statuses).to_h
115
+ end
100
116
  end
101
117
  end
102
118
  end
@@ -19,6 +19,10 @@ module Twterm
19
19
  tab = Tab::New::Search.new
20
20
  TabManager.instance.switch(tab)
21
21
  tab.invoke_input
22
+ when 'U'
23
+ tab = Tab::New::User.new
24
+ TabManager.instance.switch(tab)
25
+ tab.invoke_input
22
26
  else
23
27
  return false
24
28
  end
@@ -53,10 +57,17 @@ module Twterm
53
57
  @window.addstr('[S]')
54
58
  end
55
59
 
56
- @window.setpos(9, 3)
60
+ @window.setpos(8, 5)
61
+ @window.addstr('- [U] Open user tab')
62
+ @window.bold do
63
+ @window.setpos(8, 7)
64
+ @window.addstr('[U]')
65
+ end
66
+
67
+ @window.setpos(11, 3)
57
68
  @window.addstr('To cancel opening a new tab, just press [w] to close this tab.')
58
69
  @window.bold do
59
- @window.setpos(9, 43)
70
+ @window.setpos(11, 43)
60
71
  @window.addstr('[w]')
61
72
  end
62
73
  @window.refresh
@@ -0,0 +1,60 @@
1
+ module Twterm
2
+ module Tab
3
+ module New
4
+ class User
5
+ include Base
6
+ include Readline
7
+
8
+ def initialize
9
+ super
10
+
11
+ @title = 'New tab'
12
+ @window.refresh
13
+ end
14
+
15
+ def respond_to_key(_)
16
+ false
17
+ end
18
+
19
+ def invoke_input
20
+ resetter = proc do
21
+ reset_prog_mode
22
+ sleep 0.1
23
+ Screen.instance.refresh
24
+ end
25
+
26
+ input_thread = Thread.new do
27
+ close_screen
28
+ puts "\nSearch user"
29
+ screen_name = readline('> @').strip
30
+ resetter.call
31
+
32
+ Client.current.show_user(screen_name) do |user|
33
+ if screen_name.nil? || screen_name.empty? || user.nil?
34
+ Notifier.instance.show_error 'User not found' if user.nil?
35
+ tab = Tab::New::Start.new
36
+ else
37
+ tab = Tab::UserTab.new(user)
38
+ end
39
+
40
+ TabManager.instance.switch(tab)
41
+ end
42
+ end
43
+
44
+ App.instance.register_interruption_handler do
45
+ input_thread.kill
46
+ resetter.call
47
+ tab = Tab::New::Start.new
48
+ TabManager.instance.switch(tab)
49
+ end
50
+
51
+ input_thread.join
52
+ end
53
+
54
+ private
55
+
56
+ def update; end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -8,16 +8,30 @@ module Twterm
8
8
  def initialize
9
9
  super
10
10
 
11
- @statuses = []
11
+ @status_ids = []
12
+
13
+ Thread.new do
14
+ loop do
15
+ statuses.take(100).each(&:touch!)
16
+ sleep 60
17
+ end
18
+ end
19
+ end
20
+
21
+ def statuses
22
+ statuses = @status_ids.map { |id| Status.find(id) }.reject(&:nil?)
23
+ @status_ids = statuses.map(&:id)
24
+ statuses
12
25
  end
13
26
 
14
27
  def prepend(status)
15
28
  fail unless status.is_a? Status
16
29
 
17
- return if @statuses.any? { |s| s.id == status.id }
30
+ return if @status_ids.include?(status.id)
18
31
 
19
- @statuses << status
32
+ @status_ids << status.id
20
33
  status.split(@window.maxx - 4)
34
+ status.touch!
21
35
  item_prepended
22
36
  refresh
23
37
  end
@@ -25,10 +39,11 @@ module Twterm
25
39
  def append(status)
26
40
  fail ArgumentError, 'argument must be an instance of Status class' unless status.is_a? Status
27
41
 
28
- return if @statuses.any? { |s| s == status }
42
+ return if @status_ids.include?(status.id)
29
43
 
30
- @statuses.unshift(status)
44
+ @status_ids.unshift(status.id)
31
45
  status.split(@window.maxx - 4)
46
+ status.touch!
32
47
  item_appended
33
48
  refresh
34
49
  end
@@ -59,8 +74,7 @@ module Twterm
59
74
  end
60
75
 
61
76
  def delete_status(status_id)
62
- detector = -> (status) { status.id == status_id }
63
- @statuses.delete_if(&detector)
77
+ @status_ids.delete(status_id)
64
78
  refresh
65
79
  end
66
80
 
@@ -93,7 +107,7 @@ module Twterm
93
107
 
94
108
  @window.clear
95
109
 
96
- @statuses.reverse.drop(offset).each.with_index(offset) do |status, i|
110
+ statuses.reverse.drop(offset).each.with_index(offset) do |status, i|
97
111
  formatted_lines = status.split(@window.maxx - 4).count
98
112
  if current_line + formatted_lines + 2 > @window.maxy
99
113
  @scrollable_last = i
@@ -202,18 +216,19 @@ module Twterm
202
216
  private
203
217
 
204
218
  def highlighted_status
205
- @statuses[count - index - 1]
219
+ id = @status_ids[count - index - 1]
220
+ Status.find(id)
206
221
  end
207
222
 
208
223
  def count
209
- @statuses.count
224
+ @status_ids.count
210
225
  end
211
226
 
212
227
  def offset_from_bottom
213
228
  return @offset_from_bottom unless @offset_from_bottom.nil?
214
229
 
215
230
  height = 0
216
- @statuses.each.with_index(-1) do |status, i|
231
+ statuses.each.with_index(-1) do |status, i|
217
232
  height += status.split(@window.maxx - 4).count + 2
218
233
  if height >= @window.maxy
219
234
  @offset_from_bottom = i
@@ -224,7 +239,7 @@ module Twterm
224
239
  end
225
240
 
226
241
  def sort
227
- @statuses.sort_by!(&:created_at_for_sort)
242
+ @status_ids.sort_by! { |id| Status.find(id).created_at_for_sort }
228
243
  end
229
244
 
230
245
  def show_help
@@ -24,6 +24,10 @@ module Twterm
24
24
  yield if block_given?
25
25
  end
26
26
  end
27
+
28
+ def ==(other)
29
+ other.is_a?(self.class) && user == other.user
30
+ end
27
31
  end
28
32
  end
29
33
  end
@@ -23,7 +23,11 @@ module Twterm
23
23
 
24
24
  thread = Thread.new do
25
25
  close_screen
26
- puts "\ncompose new tweet:"
26
+ if @in_reply_to.nil?
27
+ puts "\nCompose new tweet:"
28
+ else
29
+ puts "\nReply to @#{@in_reply_to.user.screen_name}'s tweet: \"#{@in_reply_to.text}\""
30
+ end
27
31
  @status = readline(@in_reply_to.nil? ? '> ' : " @#{in_reply_to.user.screen_name} ", true)
28
32
  resetter.call
29
33
  post
@@ -1,3 +1,3 @@
1
1
  module Twterm
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  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: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryota Kameoka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-16 00:00:00.000000000 Z
11
+ date: 2015-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -146,6 +146,7 @@ files:
146
146
  - lib/twterm/tab/new/list.rb
147
147
  - lib/twterm/tab/new/search.rb
148
148
  - lib/twterm/tab/new/start.rb
149
+ - lib/twterm/tab/new/user.rb
149
150
  - lib/twterm/tab/scrollable.rb
150
151
  - lib/twterm/tab/search_tab.rb
151
152
  - lib/twterm/tab/statuses_tab.rb