twterm 1.0.10 → 1.0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d067153f4c632aeba6108ea07201aff1db4790c
4
- data.tar.gz: d6ddac0119221c40646bae8bd53bf19081ddab1b
3
+ metadata.gz: 2572d3668fe0048eb79fa55c0b881a39fe130c7a
4
+ data.tar.gz: 8fc15104af2e69ee71861a1e903a056f3dda1f57
5
5
  SHA512:
6
- metadata.gz: dcd02ff35df547ca1383dfe70ac5a097c4ca0d91448ec0a79a4557084a84a14b24961c190697d30f428b1053db710fcd4030fcb9350a0a12111dd1c6eeec0dba
7
- data.tar.gz: d37de57e07ad39327df4864b961a141e146a00d6956f43391c2e9cf4843e5d4d80a78d4666204edfeb32c4fbc7dd0ab73692a6e847a3d060bb4a57271629848c
6
+ metadata.gz: c7f0770b2c858fee53746e64ee194218b565ff16d88d06fd336b5c3ad304716df9dc57e5a8fbd1f8eba5b377ba9ada1d97aaf580f9d68355090924de4a595451
7
+ data.tar.gz: 7ed7a151ce86516110461ea3426e742f271713d6b87038d5c331c78d4f06ed8995ed39b98d96257a2aab5d1eaff99e54ff3a106ff76699002df426ac8594519a
data/lib/twterm.rb CHANGED
@@ -20,6 +20,7 @@ require 'twterm/color_manager'
20
20
  require 'twterm/completion_mamanger'
21
21
  require 'twterm/config'
22
22
  require 'twterm/extensions/curses/window'
23
+ require 'twterm/extensions/enumerator/lazy'
23
24
  require 'twterm/extensions/integer'
24
25
  require 'twterm/extensions/string'
25
26
  require 'twterm/history/base'
@@ -37,7 +38,7 @@ require 'twterm/tab_manager'
37
38
  require 'twterm/tab/base'
38
39
  require 'twterm/tab/dumpable'
39
40
  require 'twterm/tab/exceptions'
40
- require 'twterm/tab/scroll_manager'
41
+ require 'twterm/tab/scrollable'
41
42
  require 'twterm/tab/statuses_tab'
42
43
  require 'twterm/tab/conversation_tab'
43
44
  require 'twterm/tab/key_assignments_cheatsheet'
@@ -57,6 +58,6 @@ require 'twterm/version'
57
58
 
58
59
  module Twterm
59
60
  class Conf
60
- REQUIRE_VERSION = '1.0.10'
61
+ REQUIRE_VERSION = '1.0.11'
61
62
  end
62
63
  end
data/lib/twterm/client.rb CHANGED
@@ -175,6 +175,12 @@ module Twterm
175
175
  end
176
176
  end
177
177
 
178
+ def saved_search
179
+ send_request do
180
+ yield rest_client.saved_searches
181
+ end
182
+ end
183
+
178
184
  def search(query)
179
185
  send_request do
180
186
  statuses = rest_client
@@ -0,0 +1,12 @@
1
+ class Enumerator
2
+ class Lazy
3
+ def scan(initial, sym = nil)
4
+ acc = initial
5
+
6
+ Enumerator::Lazy.new(self) do |y, x|
7
+ acc = sym.nil? ? yield(acc, x) : sym.to_proc.call(acc, x)
8
+ y << acc
9
+ end
10
+ end
11
+ end
12
+ end
@@ -39,7 +39,7 @@ module Twterm
39
39
  @status = status
40
40
 
41
41
  append(status)
42
- scroll_manager.move_to_top
42
+ scroller.move_to_top
43
43
  Thread.new { fetch_in_reply_to_status(status) }
44
44
  Thread.new { fetch_replies(status) }
45
45
  end
@@ -2,6 +2,7 @@ module Twterm
2
2
  module Tab
3
3
  class KeyAssignmentsCheatsheet
4
4
  include Base
5
+ include Scrollable
5
6
 
6
7
  def ==(other)
7
8
  other.is_a?(self.class)
@@ -38,20 +39,29 @@ module Twterm
38
39
  }
39
40
  }
40
41
 
42
+ def drawable_item_count
43
+ window.maxy - 3
44
+ end
45
+
46
+ def initialize
47
+ super
48
+ scroller.set_cursor_free!
49
+ end
50
+
41
51
  def respond_to_key(key)
42
52
  case key
43
53
  when ?d, 4
44
- 10.times { scroll_manager.move_down }
54
+ 10.times { scroller.move_down }
45
55
  when ?g
46
- scroll_manager.move_to_top
56
+ scroller.move_to_top
47
57
  when ?G
48
- scroll_manager.move_to_bottom
58
+ scroller.move_to_bottom
49
59
  when ?j, 14, Curses::Key::DOWN
50
- scroll_manager.move_down
60
+ scroller.move_down
51
61
  when ?k, 16, Curses::Key::UP
52
- scroll_manager.move_up
62
+ scroller.move_up
53
63
  when ?u, 21
54
- 10.times { scroll_manager.move_up }
64
+ 10.times { scroller.move_up }
55
65
  else
56
66
  return false
57
67
  end
@@ -63,51 +73,34 @@ module Twterm
63
73
  'Key assignments'.freeze
64
74
  end
65
75
 
66
- def update
67
- top = 2 # begin drawing from line 2
68
- draw_cond = -> line { top <= line && line <= window.maxy - top }
76
+ def total_item_count
77
+ @count ||= SHORTCUTS.count * 4 + SHORTCUTS.values.map(&:count).reduce(0, :+) + 1
78
+ end
69
79
 
70
- current_line = top - scroll_manager.offset
80
+ def update
81
+ offset = scroller.offset
82
+ line = 0
71
83
 
72
- window.setpos(current_line, 3)
73
- window.bold { window.addstr('Key assignments') } if draw_cond[current_line]
84
+ window.setpos(line - offset + 2, 3)
85
+ window.bold { window.addstr('Key assignments') } if scroller.nth_item_drawable?(line)
74
86
 
75
87
  SHORTCUTS.each do |category, shortcuts|
76
- current_line += 3
77
- window.setpos(current_line, 5)
78
- window.bold { window.addstr("<#{category}>") } if draw_cond[current_line]
79
- current_line += 1
88
+ line += 3
89
+ window.setpos(line - offset + 2, 5)
90
+ window.bold { window.addstr("<#{category}>") } if scroller.nth_item_drawable?(line)
91
+ line += 1
80
92
 
81
93
  shortcuts.each do |key, description|
82
- current_line += 1
83
- next unless draw_cond[current_line]
94
+ line += 1
95
+ next unless scroller.nth_item_drawable?(line)
84
96
 
85
- window.setpos(current_line, 7)
97
+ window.setpos(line - offset + 2, 7)
86
98
  window.bold { window.addstr(key.rjust(17)) }
87
- window.setpos(current_line, 25)
99
+ window.setpos(line - offset + 2, 25)
88
100
  window.addstr(": #{description}")
89
101
  end
90
102
  end
91
103
  end
92
-
93
- private
94
-
95
- def count
96
- @count ||= SHORTCUTS.count * 4 + SHORTCUTS.map(&:count).reduce(0, :+) + 1
97
- end
98
-
99
- def offset_from_bottom
100
- 0
101
- end
102
-
103
- def scroll_manager
104
- return @scroll_manager unless @scroll_manager.nil?
105
-
106
- @scroll_manager = ScrollManager.new
107
- @scroll_manager.delegate = self
108
- @scroll_manager.after_move { refresh }
109
- @scroll_manager
110
- end
111
104
  end
112
105
  end
113
106
  end
@@ -13,7 +13,7 @@ module Twterm
13
13
  @list = list
14
14
  @title = @list.full_name
15
15
  TabManager.instance.refresh_window
16
- fetch { scroll_manager.move_to_top }
16
+ fetch { scroller.move_to_top }
17
17
  @auto_reloader = Scheduler.new(300) { fetch }
18
18
  end
19
19
  end
@@ -28,7 +28,7 @@ module Twterm
28
28
 
29
29
  @title = 'Mentions'
30
30
 
31
- fetch { scroll_manager.move_to_top }
31
+ fetch { scroller.move_to_top }
32
32
  @auto_reloader = Scheduler.new(300) { fetch }
33
33
  end
34
34
  end
@@ -3,6 +3,7 @@ module Twterm
3
3
  module New
4
4
  class List
5
5
  include Base
6
+ include Scrollable
6
7
 
7
8
  @@lists = nil
8
9
 
@@ -10,6 +11,10 @@ module Twterm
10
11
  other.is_a?(self.class)
11
12
  end
12
13
 
14
+ def drawable_item_count
15
+ (window.maxy - 2).div(3)
16
+ end
17
+
13
18
  def initialize
14
19
  super
15
20
 
@@ -17,50 +22,52 @@ module Twterm
17
22
  refresh
18
23
  end
19
24
 
25
+ def items
26
+ @@lists
27
+ end
28
+
20
29
  def respond_to_key(key)
21
30
  case key
22
31
  when ?g
23
- scroll_manager.move_to_top
32
+ scroller.move_to_top
24
33
  when ?G
25
- scroll_manager.move_to_bottom
34
+ scroller.move_to_bottom
26
35
  when ?j, 14, Curses::Key::DOWN
27
- scroll_manager.move_down
36
+ scroller.move_down
28
37
  when 10
29
38
  return true if current_list.nil?
30
39
  list_tab = Tab::ListTab.new(current_list.id)
31
40
  TabManager.instance.switch(list_tab)
32
41
  when ?k, 16, Curses::Key::UP
33
- scroll_manager.move_up
42
+ scroller.move_up
34
43
  else
35
44
  return false
36
45
  end
37
46
  true
38
47
  end
39
48
 
40
- private
41
-
42
- def count
49
+ def total_item_count
43
50
  @@lists.nil? ? 0 : @@lists.count
44
51
  end
45
52
 
46
- def current_list
47
- @@lists.nil? ? nil : @@lists[scroll_manager.index]
48
- end
53
+ private
49
54
 
50
- def offset_from_bottom
51
- 0
55
+ def current_list
56
+ @@lists.nil? ? nil : @@lists[scroller.index]
52
57
  end
53
58
 
54
59
  def show_lists
55
60
  return if @@lists.nil?
56
61
 
57
- @@lists.each.with_index(0) do |list, i|
62
+ index, offset = scroller.index, scroller.offset
63
+
64
+ drawable_items.each.with_index(0) do |list, i|
58
65
  window.with_color(:black, :magenta) do
59
66
  window.setpos(i * 3 + 5, 4)
60
67
  window.addstr(' ')
61
68
  window.setpos(i * 3 + 6, 4)
62
69
  window.addstr(' ')
63
- end if i == scroll_manager.index
70
+ end if scroller.current_item?(i)
64
71
 
65
72
  window.setpos(i * 3 + 5, 6)
66
73
  window.addstr("#{list.full_name} (#{list.member_count} members / #{list.subscriber_count} subscribers)")
@@ -69,15 +76,6 @@ module Twterm
69
76
  end
70
77
  end
71
78
 
72
- def scroll_manager
73
- return @scroll_manager unless @scroll_manager.nil?
74
-
75
- @scroll_manager = ScrollManager.new
76
- @scroll_manager.delegate = self
77
- @scroll_manager.after_move { refresh }
78
- @scroll_manager
79
- end
80
-
81
79
  def update
82
80
  window.setpos(2, 3)
83
81
  window.bold { window.addstr('Open list tab') }
@@ -4,15 +4,24 @@ module Twterm
4
4
  class Search
5
5
  include Base
6
6
  include Readline
7
+ include Scrollable
8
+
9
+ @@queries = []
7
10
 
8
11
  def ==(other)
9
12
  other.is_a?(self.class)
10
13
  end
11
14
 
15
+ def drawable_item_count
16
+ (window.maxy - 2).div(3)
17
+ end
18
+
12
19
  def initialize
13
20
  super
14
21
 
15
22
  @title = 'New tab'
23
+
24
+ update_saved_search
16
25
  end
17
26
 
18
27
  def invoke_input
@@ -29,27 +38,96 @@ module Twterm
29
38
  query = (readline('> ') || '').strip
30
39
  resetter.call
31
40
 
32
- tab = query.nil? || query.empty? ? Tab::New::Start.new : Tab::SearchTab.new(query)
41
+ tab = query.nil? || query.empty? ? Tab::New::Search.new : Tab::SearchTab.new(query)
33
42
  TabManager.instance.switch(tab)
34
43
  end
35
44
 
36
45
  App.instance.register_interruption_handler do
37
46
  input_thread.kill
38
47
  resetter.call
39
- tab = Tab::New::Start.new
48
+ tab = Tab::New::Search.new
40
49
  TabManager.instance.switch(tab)
41
50
  end
42
51
 
43
52
  input_thread.join
44
53
  end
45
54
 
46
- def respond_to_key(_)
47
- false
55
+ def items
56
+ ['<Input search query>'] + @@queries
57
+ end
58
+
59
+ def respond_to_key(key)
60
+ case key
61
+ when ?d, 4
62
+ 10.times { scroller.move_down }
63
+ when ?g
64
+ scroller.move_to_top
65
+ when ?G
66
+ scroller.move_to_bottom
67
+ when 10
68
+ open_search_tab_with_current_query
69
+ when ?j, 14, Curses::Key::DOWN
70
+ scroller.move_down
71
+ when ?k, 16, Curses::Key::UP
72
+ scroller.move_up
73
+ when ?u, 21
74
+ 10.times { scroller.move_up }
75
+ else
76
+ return false
77
+ end
78
+
79
+ true
80
+ end
81
+
82
+ def total_item_count
83
+ @@queries.count + 1
48
84
  end
49
85
 
50
86
  private
51
87
 
52
- def update; end
88
+ alias_method :count, :total_item_count
89
+
90
+ def open_search_tab_with_current_query
91
+ index = scroller.index
92
+
93
+ if index == 0
94
+ invoke_input
95
+ else
96
+ query = @@queries[index - 1]
97
+ tab = Tab::SearchTab.new(query)
98
+ TabManager.instance.switch(tab)
99
+ end
100
+ end
101
+
102
+ def update
103
+ offset = scroller.offset
104
+
105
+ window.setpos(2, 3)
106
+ window.bold { window.addstr('Open search tab') }
107
+
108
+ drawable_items.each.with_index(0) do |query, i|
109
+ line = 3 * i + 5
110
+
111
+ window.with_color(:black, :magenta) do
112
+ window.setpos(line, 4)
113
+ window.addstr(' ')
114
+ window.setpos(line + 1, 4)
115
+ window.addstr(' ')
116
+ end if scroller.current_item?(i)
117
+
118
+ window.setpos(line, 6)
119
+ window.addstr(query)
120
+ end
121
+ end
122
+
123
+ def update_saved_search
124
+ return unless @@queries.empty?
125
+
126
+ Client.current.saved_search do |searches|
127
+ @@queries = searches.map(&:query)
128
+ refresh
129
+ end
130
+ end
53
131
  end
54
132
  end
55
133
  end
@@ -22,15 +22,10 @@ module Twterm
22
22
  when 'S'
23
23
  tab = Tab::New::Search.new
24
24
  TabManager.instance.switch(tab)
25
- tab.invoke_input
26
25
  when 'U'
27
26
  tab = Tab::New::User.new
28
27
  TabManager.instance.switch(tab)
29
28
  tab.invoke_input
30
- when 'x'
31
- tab = Tab::New::Track.new
32
- TabManager.instance.switch(tab)
33
- tab.invoke_input
34
29
  else
35
30
  return false
36
31
  end
@@ -0,0 +1,138 @@
1
+ module Twterm
2
+ module Tab
3
+ module Scrollable
4
+ extend Forwardable
5
+
6
+ attr_reader :scroller
7
+ def_delegators :scroller, :drawable_items
8
+
9
+ def scroller
10
+ return @scroller unless @scroller.nil?
11
+
12
+ @scroller = Scroller.new
13
+ @scroller.delegate = self
14
+ @scroller.after_move { refresh }
15
+ @scroller
16
+ end
17
+
18
+ private
19
+
20
+ class Scroller
21
+ extend Forwardable
22
+
23
+ attr_reader :index, :offset
24
+
25
+ attr_accessor :delegate
26
+ def_delegators :delegate, :items, :total_item_count, :drawable_item_count
27
+
28
+ def after_move(&block)
29
+ add_hook(:after_move, &block)
30
+ end
31
+
32
+ def current_item?(i)
33
+ index == offset + i
34
+ end
35
+
36
+ def cursor_free?
37
+ !!@cursor_free
38
+ end
39
+
40
+ def initialize
41
+ @index = 0
42
+ @offset = 0
43
+ @cursor_free_mode = false
44
+ end
45
+
46
+ def drawable_items
47
+ items.drop(offset).take(drawable_item_count)
48
+ end
49
+
50
+ def item_appended!
51
+ @index -= 1
52
+ @offset -= 1 if @offset > 0
53
+ end
54
+
55
+ def item_prepended!
56
+ @index += 1
57
+ @offset += 1
58
+ end
59
+
60
+ def move_down
61
+ return if count == 0 || index == count - 1
62
+ # return when there are no items or cursor is at the bottom
63
+
64
+ @index += 1
65
+ @offset += 1 if (cursor_free? || cursor_on_the_downside?) && !last_item_shown?
66
+
67
+ hook :after_move
68
+ end
69
+
70
+ def move_to_bottom
71
+ return if count == 0 || index == count - 1
72
+
73
+ @index = count - 1
74
+ @offset = [count - drawable_item_count + 1, 0].max
75
+
76
+ @offset += 1 until last_item_shown?
77
+
78
+ hook :after_move
79
+ end
80
+
81
+ def move_to_top
82
+ return if count.zero? || index.zero?
83
+
84
+ @index = 0
85
+ @offset = 0
86
+
87
+ hook :after_move
88
+ end
89
+
90
+ def move_up
91
+ return if count.zero? || index.zero?
92
+
93
+ @index -= 1
94
+ @offset -= 1 if cursor_on_the_upside? && !first_item_shown?
95
+
96
+ hook :after_move
97
+ end
98
+
99
+ def nth_item_drawable?(n)
100
+ n.between?(offset, offset + drawable_item_count)
101
+ end
102
+
103
+ def set_cursor_free!
104
+ @cursor_free = true
105
+ end
106
+
107
+ private
108
+
109
+ alias_method :count, :total_item_count
110
+
111
+ def add_hook(name, &block)
112
+ @hooks ||= {}
113
+ @hooks[name] = block
114
+ end
115
+
116
+ def cursor_on_the_downside?
117
+ drawable_item_count + offset - index < 4
118
+ end
119
+
120
+ def cursor_on_the_upside?
121
+ index - offset < 4
122
+ end
123
+
124
+ def first_item_shown?
125
+ offset.zero?
126
+ end
127
+
128
+ def last_item_shown?
129
+ total_item_count <= offset + drawable_item_count
130
+ end
131
+
132
+ def hook(name)
133
+ @hooks[name].call unless @hooks[name].nil?
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -32,7 +32,7 @@ module Twterm
32
32
  @query = query
33
33
  @title = "\"#{@query}\""
34
34
 
35
- fetch { scroll_manager.move_to_top }
35
+ fetch { scroller.move_to_top }
36
36
  @auto_reloader = Scheduler.new(300) { fetch }
37
37
  end
38
38
  end
@@ -2,6 +2,7 @@ module Twterm
2
2
  module Tab
3
3
  module StatusesTab
4
4
  include Base
5
+ include Scrollable
5
6
 
6
7
  def append(status)
7
8
  fail ArgumentError,
@@ -12,14 +13,10 @@ module Twterm
12
13
  @status_ids.unshift(status.id)
13
14
  status.split(window.maxx - 4)
14
15
  status.touch!
15
- scroll_manager.item_appended!
16
+ scroller.item_appended!
16
17
  refresh
17
18
  end
18
19
 
19
- def count
20
- grep_query.empty? ? @status_ids.count : statuses.count
21
- end
22
-
23
20
  def delete(status_id)
24
21
  @status_ids.delete(status_id)
25
22
  refresh
@@ -34,6 +31,14 @@ module Twterm
34
31
  end
35
32
  end
36
33
 
34
+ def drawable_item_count
35
+ statuses.reverse.drop(scroller.offset).lazy
36
+ .map { |s| s.split(window.maxx - 4).count + 2 }
37
+ .scan(0, :+)
38
+ .select { |l| l < window.maxy }
39
+ .count
40
+ end
41
+
37
42
  def favorite
38
43
  return if highlighted_status.nil?
39
44
 
@@ -56,26 +61,26 @@ module Twterm
56
61
 
57
62
  if grep_query.empty?
58
63
  reset_grep
59
- elsif count == 0
64
+ elsif total_item_count == 0
60
65
  Notifier.instance.show_error "No matches found: \"#{grep_query}\""
61
66
  reset_grep
62
67
  else
63
- Notifier.instance.show_message "#{count} statuses found: \"#{grep_query}\""
64
- scroll_manager.move_to_top
68
+ Notifier.instance.show_message "#{total_item_count} statuses found: \"#{grep_query}\""
69
+ scroller.move_to_top
65
70
  refresh
66
71
  end
67
72
  end
68
73
 
69
- def grep_query
70
- @grep_query || ''
71
- end
72
-
73
74
  def initialize
74
75
  super
75
76
 
76
77
  @status_ids = []
77
78
  end
78
79
 
80
+ def items
81
+ statuses.reverse
82
+ end
83
+
79
84
  def open_link
80
85
  return if highlighted_status.nil?
81
86
 
@@ -92,7 +97,7 @@ module Twterm
92
97
  @status_ids << status.id
93
98
  status.split(window.maxx - 4)
94
99
  status.touch!
95
- scroll_manager.item_prepended!
100
+ scroller.item_prepended!
96
101
  refresh
97
102
  end
98
103
 
@@ -115,19 +120,19 @@ module Twterm
115
120
  when ?c
116
121
  show_conversation
117
122
  when ?d, 4
118
- 10.times { scroll_manager.move_down }
123
+ 10.times { scroller.move_down }
119
124
  when ?D
120
125
  destroy_status
121
126
  when ?F
122
127
  favorite
123
128
  when ?g
124
- scroll_manager.move_to_top
129
+ scroller.move_to_top
125
130
  when ?G
126
- scroll_manager.move_to_bottom
131
+ scroller.move_to_bottom
127
132
  when ?j, 14, Curses::Key::DOWN
128
- scroll_manager.move_down
133
+ scroller.move_down
129
134
  when ?k, 16, Curses::Key::UP
130
- scroll_manager.move_up
135
+ scroller.move_up
131
136
  when ?o
132
137
  open_link
133
138
  when ?r
@@ -137,7 +142,7 @@ module Twterm
137
142
  when 18
138
143
  fetch
139
144
  when ?u, 21
140
- 10.times { scroll_manager.move_up }
145
+ 10.times { scroller.move_up }
141
146
  when ?U
142
147
  show_user
143
148
  when ?/
@@ -185,33 +190,23 @@ module Twterm
185
190
  statuses.reverse.take(100).each(&:touch!)
186
191
  end
187
192
 
188
- def update
189
- current_line = 0
190
-
191
- offset = scroll_manager.offset
192
- index = scroll_manager.index
193
+ def total_item_count
194
+ grep_query.empty? ? @status_ids.count : statuses.count
195
+ end
193
196
 
194
- return if offset < 0
197
+ def update
198
+ line = 0
195
199
 
196
- statuses.reverse.drop(offset).each.with_index(offset) do |status, i|
200
+ scroller.drawable_items.each.with_index(0) do |status, i|
197
201
  formatted_lines = status.split(window.maxx - 4).count
198
- if current_line + formatted_lines + 2 > window.maxy
199
- scroll_manager.last = i
200
- break
201
- end
202
-
203
- posy = current_line
204
-
205
- if index == i
206
- window.with_color(:black, :magenta) do
207
- (formatted_lines + 1).times do |j|
208
- window.setpos(posy + j, 0)
209
- window.addch(' ')
210
- end
202
+ window.with_color(:black, :magenta) do
203
+ (formatted_lines + 1).times do |j|
204
+ window.setpos(line + j, 0)
205
+ window.addch(' ')
211
206
  end
212
- end
207
+ end if scroller.current_item?(i)
213
208
 
214
- window.setpos(current_line, 2)
209
+ window.setpos(line, 2)
215
210
 
216
211
  window.bold do
217
212
  window.with_color(status.user.color) do
@@ -258,46 +253,24 @@ module Twterm
258
253
  window.addch(' ')
259
254
  end
260
255
 
261
- status.split(window.maxx - 4).each do |line|
262
- current_line += 1
263
- window.setpos(current_line, 2)
264
- window.addstr(line)
256
+ status.split(window.maxx - 4).each do |str|
257
+ line += 1
258
+ window.setpos(line, 2)
259
+ window.addstr(str)
265
260
  end
266
261
 
267
- current_line += 2
262
+ line += 2
268
263
  end
269
-
270
- UserWindow.instance.update(highlighted_status.user) unless highlighted_status.nil?
271
264
  end
272
265
 
273
266
  private
274
267
 
275
- def highlighted_status
276
- id = @status_ids[scroll_manager.count - scroll_manager.index - 1]
277
- Status.find(id)
278
- end
279
-
280
- def offset_from_bottom
281
- return @offset_from_bottom unless @offset_from_bottom.nil?
282
-
283
- height = 0
284
- statuses.each.with_index(-1) do |status, i|
285
- height += status.split(window.maxx - 4).count + 2
286
- if height >= window.maxy
287
- @offset_from_bottom = i
288
- return i
289
- end
290
- end
291
- count
268
+ def grep_query
269
+ @grep_query || ''
292
270
  end
293
271
 
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
272
+ def highlighted_status
273
+ statuses[scroller.count - scroller.index - 1]
301
274
  end
302
275
 
303
276
  def sort
@@ -23,7 +23,7 @@ module Twterm
23
23
  @client.on_timeline_status(&method(:prepend))
24
24
  @title = 'Timeline'
25
25
 
26
- fetch { scroll_manager.move_to_top }
26
+ fetch { scroller.move_to_top }
27
27
  @auto_reloader = Scheduler.new(180) { fetch }
28
28
  end
29
29
  end
@@ -35,7 +35,7 @@ module Twterm
35
35
  @title = "@#{@user.screen_name}"
36
36
  TabManager.instance.refresh_window
37
37
 
38
- fetch { scroll_manager.move_to_top }
38
+ fetch { scroller.move_to_top }
39
39
  @auto_reloader = Scheduler.new(120) { fetch }
40
40
  end
41
41
  end
@@ -1,3 +1,3 @@
1
1
  module Twterm
2
- VERSION = '1.0.10'
2
+ VERSION = '1.0.11'
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.10
4
+ version: 1.0.11
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-07-07 00:00:00.000000000 Z
11
+ date: 2015-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -159,6 +159,7 @@ files:
159
159
  - lib/twterm/completion_mamanger.rb
160
160
  - lib/twterm/config.rb
161
161
  - lib/twterm/extensions/curses/window.rb
162
+ - lib/twterm/extensions/enumerator/lazy.rb
162
163
  - lib/twterm/extensions/integer.rb
163
164
  - lib/twterm/extensions/string.rb
164
165
  - lib/twterm/history/base.rb
@@ -184,7 +185,7 @@ files:
184
185
  - lib/twterm/tab/new/search.rb
185
186
  - lib/twterm/tab/new/start.rb
186
187
  - lib/twterm/tab/new/user.rb
187
- - lib/twterm/tab/scroll_manager.rb
188
+ - lib/twterm/tab/scrollable.rb
188
189
  - lib/twterm/tab/search_tab.rb
189
190
  - lib/twterm/tab/statuses_tab.rb
190
191
  - lib/twterm/tab/timeline_tab.rb
@@ -1,84 +0,0 @@
1
- module Twterm
2
- module Tab
3
- class ScrollManager
4
- extend Forwardable
5
-
6
- attr_reader :index, :offset
7
- attr_accessor :last
8
-
9
- attr_accessor :delegate
10
- def_delegators :delegate, :count, :offset_from_bottom
11
-
12
- def after_move(&block)
13
- add_hook(:after_move, &block)
14
- end
15
-
16
- def initialize
17
- @index = 0
18
- @offset = 0
19
- @last = 0
20
- end
21
-
22
- def item_appended!
23
- @index -= 1
24
- @offset -= 1 if @offset > 0
25
- end
26
-
27
- def item_prepended!
28
- @index += 1
29
- @offset += 1
30
- end
31
-
32
- def move_down
33
- return if count == 0 || index == count - 1
34
-
35
- @index = [index + 1, count - 1].min
36
- @offset = [
37
- offset + 1,
38
- count - 1,
39
- count - offset_from_bottom
40
- ].min if index > last - 4
41
-
42
- hook :after_move
43
- end
44
-
45
- def move_to_bottom
46
- return if count == 0 || index == count - 1
47
-
48
- @index = count - 1
49
- @offset = count - 1 - offset_from_bottom
50
-
51
- hook :after_move
52
- end
53
-
54
- def move_to_top
55
- return if count == 0 || index == 0
56
-
57
- @index = 0
58
- @offset = 0
59
-
60
- hook :after_move
61
- end
62
-
63
- def move_up
64
- return if count == 0 || index == 0
65
-
66
- @index = [index - 1, 0].max
67
- @offset = [offset - 1, 0].max if index - 4 < offset
68
-
69
- hook :after_move
70
- end
71
-
72
- private
73
-
74
- def add_hook(name, &block)
75
- @hooks ||= {}
76
- @hooks[name] = block
77
- end
78
-
79
- def hook(name)
80
- @hooks[name].call unless @hooks[name].nil?
81
- end
82
- end
83
- end
84
- end