twterm 2.9.0 → 2.10.0

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
  SHA256:
3
- metadata.gz: b30c12f62dabee87d10f7f5973e2464230e9ffdce5edf90e36b82c07a639beb5
4
- data.tar.gz: b7d3a6493e676da015cb69ad6a9a4f8c48cf321f30604f99220bc28948f0e109
3
+ metadata.gz: 457bad615e0cd1430c0a60a50e5fa87eca2cabb2bb49632db62c50f41e38f152
4
+ data.tar.gz: '08c9ab2b0cc67791264bfbb1f0bcd3a3f6a1c4a570c152de43d135d72297acd1'
5
5
  SHA512:
6
- metadata.gz: 0a913981e4c174915e6bb8909cb56bcb7d4bb6aea0ca4679482bf7d0b15c5ca1c71e3b9a127eab566164b1a507f5eea05a8f7efe4757540394746972b8e3c353
7
- data.tar.gz: e3dbe12e43379553fd3059bddb4f69f5afccabb2e7e1652b65b1cc097e5b4a998deba14a96193efb93888c6652446488ec3a999d06937fb794a8372840fef962
6
+ metadata.gz: dbfa53b1f51f469f78bf9301bbe87faa44894506be4a2ab17da11bcb87af471810be121cdb6941f3ae74f34383a8de3c33331335b317b8bfa8afaabaca7437a2
7
+ data.tar.gz: 59c32de0182c59ab17c3c96dd14d4de180d86b9d59de0491d5e6a693405aeb273a83718f59193522a2b9d8ec78d75453df09fd38547c7416cfdfda92d7165f49
data/Makefile CHANGED
@@ -9,10 +9,13 @@ Gemfile.lock: Gemfile twterm.gemspec
9
9
  gemset.nix: Gemfile Gemfile.lock twterm.gemspec
10
10
  nix-shell -p bundix --run 'bundix --lock'
11
11
 
12
- nix/Gemfile.lock: Gemfile.lock
13
- cp -f Gemfile.lock nix/Gemfile.lock
12
+ nix/Gemfile.lock: nix/Gemfile
13
+ nix-shell -p bundix --run 'bundix --lock --gemfile=nix/Gemfile'
14
14
 
15
15
  nix/gemset.nix: nix/Gemfile.lock
16
16
  nix-shell -p bundix --run 'bundix --gemfile=nix/Gemfile --gemset=nix/gemset.nix --lockfile=nix/Gemfile.lock'
17
17
 
18
- prerelease: nix/Gemfile.lock nix/gemset.nix
18
+ postrelease: nix/Gemfile.lock nix/gemset.nix
19
+
20
+ test:
21
+ nix-shell --run 'bundle exec rspec'
data/README.md CHANGED
@@ -6,25 +6,45 @@ A full-featured TUI Twitter client
6
6
 
7
7
  ## Installation
8
8
 
9
- ### With [Nix](https://nixos.org/) (Recommended)
9
+ <details>
10
+ <summary>:snowflake: Nix (Recommended)</summary>
10
11
 
12
+ ```sh
13
+ $ nix-channel --add https://github.com/ryota-ka/twterm/archive/master.tar.gz
14
+ $ nix-env -iA twterm
11
15
  ```
12
- $ nix-env --install --file https://github.com/ryota-ka/twterm/archive/master.tar.gz
16
+
17
+ :warning:
18
+ If you have `BUNDLE_PATH` configured in `~/.bundle/config`, `twterm` may fail due to `Bundler::GemNotFound`.
19
+ See [NixOS/nixpkgs#85989](https://github.com/NixOS/nixpkgs/issues/85989) for details.
20
+
21
+ </details>
22
+
23
+ <details>
24
+ <summary>:beer: Homebrew</summary>
25
+
26
+ ```sh
27
+ $ brew install ryota-ka/twterm/twterm
13
28
  ```
14
29
 
15
- ### With [RubyGems](https://rubygems.org/)
30
+ </details>
31
+
32
+ <details>
33
+ <summary>:gem: RubyGems</summary>
16
34
 
17
- #### Requirements
35
+ You also have to install the following dependencies manually.
18
36
 
19
- - Ruby (>= 2.5, < 3, compiled with ncurses and Readline)
20
- - ncurses
21
- - Readline
37
+ - [Ruby](https://www.ruby-lang.org/) (>= 2.5, < 3, compiled with ncurses and Readline)
38
+ - [ncurses](https://invisible-island.net/ncurses/)
39
+ - [GNU Readline](https://tiswww.case.edu/php/chet/readline/rltop.html)
22
40
  - [GNU Libidn](https://www.gnu.org/software/libidn/)
23
41
 
24
- ```
42
+ ```sh
25
43
  $ gem install twterm
26
44
  ```
27
45
 
46
+ </details>
47
+
28
48
  ## Usage
29
49
 
30
50
  To launch twterm, just type in your console:
data/gemset.nix CHANGED
@@ -4632,161 +4632,12 @@
4632
4632
  twterm = {
4633
4633
  dependencies = ["concurrent-ruby" "curses" "launchy" "oauth" "terminal-notifier" "toml-rb" "twitter" "twitter-text"];
4634
4634
  groups = ["default"];
4635
- platforms = [{
4636
- engine = "maglev";
4637
- } {
4638
- engine = "maglev";
4639
- } {
4640
- engine = "maglev";
4641
- version = "1.8";
4642
- } {
4643
- engine = "maglev";
4644
- version = "1.8";
4645
- } {
4646
- engine = "maglev";
4647
- version = "1.9";
4648
- } {
4649
- engine = "maglev";
4650
- version = "1.9";
4651
- } {
4652
- engine = "maglev";
4653
- version = "2.0";
4654
- } {
4655
- engine = "maglev";
4656
- version = "2.0";
4657
- } {
4658
- engine = "maglev";
4659
- version = "2.1";
4660
- } {
4661
- engine = "maglev";
4662
- version = "2.1";
4663
- } {
4664
- engine = "maglev";
4665
- version = "2.2";
4666
- } {
4667
- engine = "maglev";
4668
- version = "2.2";
4669
- } {
4670
- engine = "maglev";
4671
- version = "2.3";
4672
- } {
4673
- engine = "maglev";
4674
- version = "2.3";
4675
- } {
4676
- engine = "maglev";
4677
- version = "2.4";
4678
- } {
4679
- engine = "maglev";
4680
- version = "2.4";
4681
- } {
4682
- engine = "maglev";
4683
- version = "2.5";
4684
- } {
4685
- engine = "maglev";
4686
- version = "2.5";
4687
- } {
4688
- engine = "maglev";
4689
- version = "2.6";
4690
- } {
4691
- engine = "maglev";
4692
- version = "2.6";
4693
- } {
4694
- engine = "rbx";
4695
- } {
4696
- engine = "rbx";
4697
- } {
4698
- engine = "rbx";
4699
- version = "1.8";
4700
- } {
4701
- engine = "rbx";
4702
- version = "1.9";
4703
- } {
4704
- engine = "rbx";
4705
- version = "2.0";
4706
- } {
4707
- engine = "rbx";
4708
- version = "2.1";
4709
- } {
4710
- engine = "rbx";
4711
- version = "2.2";
4712
- } {
4713
- engine = "rbx";
4714
- version = "2.3";
4715
- } {
4716
- engine = "rbx";
4717
- version = "2.4";
4718
- } {
4719
- engine = "rbx";
4720
- version = "2.5";
4721
- } {
4722
- engine = "rbx";
4723
- version = "2.6";
4724
- } {
4725
- engine = "ruby";
4726
- } {
4727
- engine = "ruby";
4728
- } {
4729
- engine = "ruby";
4730
- } {
4731
- engine = "ruby";
4732
- version = "1.8";
4733
- } {
4734
- engine = "ruby";
4735
- version = "1.8";
4736
- } {
4737
- engine = "ruby";
4738
- version = "1.9";
4739
- } {
4740
- engine = "ruby";
4741
- version = "1.9";
4742
- } {
4743
- engine = "ruby";
4744
- version = "2.0";
4745
- } {
4746
- engine = "ruby";
4747
- version = "2.0";
4748
- } {
4749
- engine = "ruby";
4750
- version = "2.1";
4751
- } {
4752
- engine = "ruby";
4753
- version = "2.1";
4754
- } {
4755
- engine = "ruby";
4756
- version = "2.2";
4757
- } {
4758
- engine = "ruby";
4759
- version = "2.2";
4760
- } {
4761
- engine = "ruby";
4762
- version = "2.3";
4763
- } {
4764
- engine = "ruby";
4765
- version = "2.3";
4766
- } {
4767
- engine = "ruby";
4768
- version = "2.4";
4769
- } {
4770
- engine = "ruby";
4771
- version = "2.4";
4772
- } {
4773
- engine = "ruby";
4774
- version = "2.5";
4775
- } {
4776
- engine = "ruby";
4777
- version = "2.5";
4778
- } {
4779
- engine = "ruby";
4780
- version = "2.6";
4781
- } {
4782
- engine = "ruby";
4783
- version = "2.6";
4784
- }];
4635
+ platforms = [];
4785
4636
  source = {
4786
4637
  path = ./.;
4787
4638
  type = "path";
4788
4639
  };
4789
- version = "2.9.0";
4640
+ version = "2.10.0";
4790
4641
  };
4791
4642
  unf = {
4792
4643
  dependencies = ["unf_ext"];
data/lib/twterm/app.rb CHANGED
@@ -3,7 +3,6 @@ require 'curses'
3
3
  require 'twterm/completion_manager'
4
4
  require 'twterm/environment'
5
5
  require 'twterm/event/screen/refresh'
6
- require 'twterm/event/screen/resize'
7
6
  require 'twterm/message_window'
8
7
  require 'twterm/notification_dispatcher'
9
8
  require 'twterm/persistable_configuration_proxy'
@@ -24,6 +23,12 @@ module Twterm
24
23
 
25
24
  attr_reader :environment, :preferences, :screen
26
25
 
26
+ # return [Twterm::MessageWindow]
27
+ attr_reader :message_window
28
+
29
+ # return [Twterm::SearchQueryWindow]
30
+ attr_reader :search_query_window
31
+
27
32
  DATA_DIR = "#{ENV['HOME']}/.twterm".freeze
28
33
 
29
34
  def initialize
@@ -63,8 +68,8 @@ module Twterm
63
68
 
64
69
  @screen = Screen.new(self, client)
65
70
 
66
- SearchQueryWindow.instance
67
- MessageWindow.instance
71
+ @search_query_window = SearchQueryWindow.new(screen.search_query_window_window)
72
+ @message_window = MessageWindow.new(screen.message_window_window)
68
73
 
69
74
  @notification_dispatcher = NotificationDispatcher.new(preferences)
70
75
  @photo_viewer = PhotoViewer.new(preferences)
@@ -143,7 +148,7 @@ module Twterm
143
148
  end
144
149
 
145
150
  def tab_manager
146
- @tab_manager ||= TabManager.new(self, client)
151
+ @tab_manager ||= TabManager.new(self, client, screen.tab_manager_window)
147
152
  end
148
153
 
149
154
  def tweetbox
@@ -177,11 +182,11 @@ module Twterm
177
182
  end
178
183
 
179
184
  def on_resize
180
- return if Curses.closed?
185
+ lines, cols = `stty size`.split(' ').map(&:to_i)
186
+
187
+ Readline.set_screen_size(lines, cols)
181
188
 
182
- lines = `tput lines`.to_i
183
- cols = `tput cols`.to_i
184
- publish(Event::Screen::Resize.new(lines, cols))
189
+ screen.resize(lines, cols) unless Curses.closed?
185
190
  end
186
191
  end
187
192
  end
data/lib/twterm/image.rb CHANGED
@@ -3,6 +3,7 @@ require 'twterm/image/blank_line'
3
3
  require 'twterm/image/bold'
4
4
  require 'twterm/image/brackets'
5
5
  require 'twterm/image/color'
6
+ require 'twterm/image/dim'
6
7
  require 'twterm/image/empty'
7
8
  require 'twterm/image/horizontal_sequential_image'
8
9
  require 'twterm/image/parens'
@@ -49,6 +50,10 @@ class Twterm::Image
49
50
  Brackets.new(self)
50
51
  end
51
52
 
53
+ def dim(on = true)
54
+ on ? Dim.new(self) : self
55
+ end
56
+
52
57
  def self.checkbox(checked)
53
58
  string(checked ? '*' : ' ').brackets
54
59
  end
@@ -0,0 +1,42 @@
1
+ require 'twterm/image'
2
+
3
+ class Twterm::Image::Attr < Twterm::Image
4
+ # @param image [Twterm::Image]
5
+ def initialize(image)
6
+ super()
7
+
8
+ @image = image
9
+ end
10
+
11
+ def height
12
+ image.height
13
+ end
14
+
15
+ def render(window)
16
+ image, attr =
17
+ if image.is_a?(self.class) # fuse attributes when possible
18
+ [image.image, self.attr | image.attr]
19
+ else
20
+ [self.image, self.attr]
21
+ end
22
+
23
+ window.attron(attr)
24
+ image.at(line, column).render(window)
25
+ window.attroff(attr)
26
+ end
27
+
28
+ def width
29
+ image.width
30
+ end
31
+
32
+ protected
33
+
34
+ attr_reader :image
35
+
36
+ # @abstract
37
+ #
38
+ # @return [Integer]
39
+ def attr
40
+ raise NotImplementedError, '`attr` must be implemented'
41
+ end
42
+ end
@@ -1,31 +1,17 @@
1
+ require 'twterm/image/attr'
2
+
1
3
  module Twterm
2
4
  class Image
3
- class Bold < Twterm::Image
4
- def initialize(image)
5
- @image = image
6
- end
7
-
8
- def height
9
- image.height
10
- end
11
-
12
- def render(window)
13
- window.attron(Curses::A_BOLD)
14
- image.at(line, column).render(window)
15
- window.attroff(Curses::A_BOLD)
16
- end
17
-
5
+ class Bold < Twterm::Image::Attr
18
6
  def to_s
19
7
  "\e[1m#{image}\e[0m"
20
8
  end
21
9
 
22
- def width
23
- image.width
24
- end
10
+ protected
25
11
 
26
- private
27
-
28
- attr_reader :image
12
+ def attr
13
+ Curses::A_BOLD
14
+ end
29
15
  end
30
16
  end
31
17
  end
@@ -1,18 +1,12 @@
1
+ require 'twterm/image/attr'
2
+
1
3
  module Twterm
2
4
  class Image
3
- class Color < Twterm::Image
5
+ class Color < Twterm::Image::Attr
4
6
  def initialize(image, fg, bg = :transparent)
5
- @image, @fg, @bg = image, fg, bg
6
- end
7
-
8
- def height
9
- image.height
10
- end
7
+ super(image)
11
8
 
12
- def render(window)
13
- window.attron(Curses.color_pair(color_pair_index))
14
- image.at(line, column).render(window)
15
- window.attroff(Curses.color_pair(color_pair_index))
9
+ @fg, @bg = fg, bg
16
10
  end
17
11
 
18
12
  def to_s
@@ -29,14 +23,14 @@ module Twterm
29
23
  @bg == :transparent ? str : "\e[#{bg_colors[@bg]}m#{str}"
30
24
  end
31
25
 
32
- def width
33
- image.width
26
+ protected
27
+
28
+ def attr
29
+ Curses.color_pair(color_pair_index)
34
30
  end
35
31
 
36
32
  private
37
33
 
38
- attr_reader :image
39
-
40
34
  def color_pair_index
41
35
  Twterm::ColorManager.instance.get_color_pair_index(@fg, @bg)
42
36
  end
@@ -0,0 +1,13 @@
1
+ require 'twterm/image/attr'
2
+
3
+ class Twterm::Image::Dim < Twterm::Image::Attr
4
+ def to_s
5
+ "\e[2m#{image}\e[0m"
6
+ end
7
+
8
+ protected
9
+
10
+ def attr
11
+ Curses::A_DIM
12
+ end
13
+ end
@@ -1,31 +1,17 @@
1
+ require 'twterm/image/attr'
2
+
1
3
  module Twterm
2
4
  class Image
3
- class Underlined < Twterm::Image
4
- def initialize(image)
5
- @image = image
6
- end
7
-
8
- def height
9
- image.height
10
- end
11
-
12
- def render(window)
13
- window.attron(Curses::A_UNDERLINE)
14
- image.at(line, column).render(window)
15
- window.attroff(Curses::A_UNDERLINE)
16
- end
17
-
5
+ class Underlined < Twterm::Image::Attr
18
6
  def to_s
19
7
  "\e[4m#{image}\e[0m"
20
8
  end
21
9
 
22
- def width
23
- image.width
24
- end
10
+ protected
25
11
 
26
- private
27
-
28
- attr_reader :image
12
+ def attr
13
+ Curses::A_UNDERLINE
14
+ end
29
15
  end
30
16
  end
31
17
  end
@@ -1,22 +1,19 @@
1
1
  require 'twterm/subscriber'
2
2
  require 'twterm/event/message/abstract_message'
3
- require 'twterm/event/screen/resize'
4
3
 
5
4
  module Twterm
6
5
  class MessageWindow
7
- include Singleton
8
6
  include Subscriber
9
7
 
10
- def initialize
11
- @window = Curses.stdscr.subwin(1, Curses.stdscr.maxx, Curses.stdscr.maxy - 1, 0)
8
+ # @param window [Curses::Window]
9
+ def initialize(window)
10
+ @window = window
12
11
  @queue = Queue.new
13
12
 
14
13
  subscribe(Event::Message::AbstractMessage) do |e|
15
14
  queue(e)
16
15
  end
17
16
 
18
- subscribe(Event::Screen::Resize, :resize)
19
-
20
17
  Thread.new do
21
18
  while message = @queue.pop # rubocop:disable Lint/AssignmentInCondition:
22
19
  show(message)
@@ -71,10 +68,5 @@ module Twterm
71
68
  @queue.push(message)
72
69
  self
73
70
  end
74
-
75
- def resize(_event)
76
- @window.resize(1, Curses.stdscr.maxx)
77
- @window.move(Curses.stdscr.maxy - 1, 0)
78
- end
79
71
  end
80
72
  end
data/lib/twterm/screen.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'twterm/event/screen/refresh'
2
- require 'twterm/event/screen/resize'
3
2
  require 'twterm/key_mapper'
4
3
  require 'twterm/subscriber'
5
4
 
@@ -7,10 +6,35 @@ module Twterm
7
6
  class Screen
8
7
  include Subscriber
9
8
 
9
+ # @todo Make private
10
+ # @return [Curses::Window]
11
+ attr_reader :tab_manager_window
12
+
13
+ # @todo Make private
14
+ # @return [Curses::Window]
15
+ attr_reader :tab_window
16
+
17
+ # @todo Make private
18
+ # @return [Curses::Window]
19
+ attr_reader :message_window_window
20
+
21
+ # @todo Make private
22
+ # @return [Curses::Window]
23
+ attr_reader :search_query_window_window
24
+
10
25
  def initialize(app, client)
11
26
  @app, @client = app, client
12
27
 
13
- @screen = Curses.init_screen
28
+ @stdscr = Curses.init_screen
29
+
30
+ width = @stdscr.maxx
31
+ height = @stdscr.maxy
32
+
33
+ @tab_manager_window = @stdscr.subwin(1, width, 0, 0)
34
+ @tab_window = @stdscr.subwin(height - 3, width, 2, 0)
35
+ @message_window_window = @stdscr.subwin(1, width, height - 1, 0)
36
+ @search_query_window_window = @stdscr.subwin(1, width, height - 1, 0)
37
+
14
38
  Curses.noecho
15
39
  Curses.raw
16
40
  Curses.curs_set(0)
@@ -20,7 +44,31 @@ module Twterm
20
44
  Curses.mousemask(Curses::BUTTON1_CLICKED | 65536 | 2097152)
21
45
 
22
46
  subscribe(Event::Screen::Refresh) { refresh }
23
- subscribe(Event::Screen::Resize, :resize)
47
+ end
48
+
49
+ def resize(lines, cols)
50
+ return if Curses.closed?
51
+
52
+ Curses.resizeterm(lines, cols)
53
+ @stdscr.resize(lines, cols)
54
+
55
+ tab_manager_window.move(0, 0)
56
+ tab_manager_window.resize(1, cols)
57
+ tab_manager_window.refresh
58
+
59
+ tab_window.move(2, 0)
60
+ tab_window.resize(lines - 3, cols)
61
+ tab_window.refresh
62
+
63
+ message_window_window.move(cols - 1, 0)
64
+ message_window_window.resize(1, cols)
65
+ message_window_window.refresh
66
+
67
+ search_query_window_window.move(cols - 1, 0)
68
+ search_query_window_window.resize(1, cols)
69
+ search_query_window_window.refresh
70
+
71
+ refresh
24
72
  end
25
73
 
26
74
  def respond_to_key(key)
@@ -92,17 +140,7 @@ module Twterm
92
140
  def refresh
93
141
  app.tab_manager.refresh_window
94
142
  app.tab_manager.current_tab.render
95
- MessageWindow.instance.show
96
- end
97
-
98
- def resize(event)
99
- return if Curses.closed?
100
-
101
- lines, cols = event.lines, event.cols
102
- Curses.resizeterm(lines, cols)
103
- @screen.resize(lines, cols)
104
-
105
- refresh
143
+ app.message_window.show
106
144
  end
107
145
 
108
146
  def scan
@@ -1,22 +1,19 @@
1
- require 'twterm/event/screen/resize'
2
1
  require 'twterm/subscriber'
3
2
 
4
3
  module Twterm
5
4
  class SearchQueryWindow
6
- include Singleton
7
5
  include Subscriber
8
6
 
9
7
  class CancelInput < StandardError; end
10
8
 
11
9
  attr_reader :last_query
12
10
 
13
- def initialize
14
- @window = Curses.stdscr.subwin(1, Curses.stdscr.maxx, Curses.stdscr.maxy - 1, 0)
11
+ # @param window [Curses::Window]
12
+ def initialize(window)
13
+ @window = window
15
14
  @searching_down = true
16
15
  @str = ''
17
16
  @last_query = ''
18
-
19
- subscribe(Event::Screen::Resize, :resize)
20
17
  end
21
18
 
22
19
  def input
@@ -113,13 +110,9 @@ module Twterm
113
110
 
114
111
  private
115
112
 
113
+ # @return [Curses::Window]
116
114
  attr_reader :window
117
115
 
118
- def resize(_event)
119
- window.resize(1, Curses.stdscr.maxx)
120
- window.move(Curses.stdscr.maxy - 1, 0)
121
- end
122
-
123
116
  def render(str)
124
117
  window.clear
125
118
  window.setpos(0, 0)
@@ -1,6 +1,5 @@
1
1
  require 'concurrent'
2
2
 
3
- require 'twterm/event/screen/resize'
4
3
  require 'twterm/image'
5
4
  require 'twterm/subscriber'
6
5
 
@@ -12,10 +11,6 @@ module Twterm
12
11
  # @return [String]
13
12
  attr_reader :title
14
13
 
15
- # @return [Curses::Window]
16
- # @todo This can be (and should be) private
17
- attr_reader :window
18
-
19
14
  # @param other [Twterm::Tab::AbstractTab]
20
15
  #
21
16
  # @return [Boolean]
@@ -26,7 +21,6 @@ module Twterm
26
21
  # @return [void]
27
22
  def close
28
23
  unsubscribe
29
- window.close
30
24
  end
31
25
 
32
26
  # A utility method to find a status by its ID
@@ -70,10 +64,6 @@ module Twterm
70
64
 
71
65
  def initialize(app, client)
72
66
  @app, @client = app, client
73
-
74
- @window = Curses.stdscr.subwin(Curses.stdscr.maxy - 3, Curses.stdscr.maxx, 2, 0)
75
-
76
- subscribe(Event::Screen::Resize, :resize)
77
67
  end
78
68
 
79
69
  def render
@@ -129,16 +119,15 @@ module Twterm
129
119
  )
130
120
  end
131
121
 
132
- # @return [void]
133
- def resize(_event)
134
- window.resize(Curses.stdscr.maxy - 3, Curses.stdscr.maxx)
135
- window.move(2, 0)
136
- end
137
-
138
122
  # @return [Twterm::View]
139
123
  def view
140
124
  View.new(window, image)
141
125
  end
126
+
127
+ # @todo This method is for transition. `window` should explicitly be obtained on initialization.
128
+ def window
129
+ app.screen.tab_window
130
+ end
142
131
  end
143
132
  end
144
133
  end
@@ -27,7 +27,7 @@ module Twterm
27
27
  attr_reader :index, :offset
28
28
 
29
29
  attr_accessor :delegate
30
- def_delegators :delegate, :items, :total_item_count, :drawable_item_count
30
+ def_delegators :delegate, :items, :total_item_count, :drawable_item_count, :search_query_window
31
31
 
32
32
  def after_move(&block)
33
33
  add_hook(:after_move, &block)
@@ -14,6 +14,12 @@ module Twterm
14
14
  raise NotImplementedError, '`matches?` method must be implemented'
15
15
  end
16
16
 
17
+ # @abstract
18
+ # @return [Twterm::SearchQueryWindow]
19
+ def search_query_window
20
+ raise NotImplementedError, '`search_query_window` method must be implemented'
21
+ end
22
+
17
23
  class Scroller < Scrollable::Scroller
18
24
  extend Forwardable
19
25
  include Publisher
@@ -122,10 +128,6 @@ module Twterm
122
128
  end
123
129
  end
124
130
 
125
- def search_query_window
126
- SearchQueryWindow.instance
127
- end
128
-
129
131
  alias_method :count, :total_item_count
130
132
  end
131
133
  end
@@ -226,10 +226,10 @@ module Twterm
226
226
 
227
227
  header = [
228
228
  ImageBuilder::UserNameImageBuilder.new(user).build,
229
- Image.string(original.date.to_s).brackets,
229
+ Image.string(original.date.to_s).brackets.dim,
230
230
  (Image.whitespace.color(:black, :red) if original.favorited?),
231
231
  (Image.whitespace.color(:black, :green) if original.retweeted?),
232
- ((Image.string('retweeted by ') - !Image.string("@#{retweeted_by.screen_name}")).parens if status.retweet?),
232
+ ((Image.string('retweeted by ') - !Image.string("@#{retweeted_by.screen_name}")).parens.dim if status.retweet?),
233
233
  ((Image.number(original.favorite_count) - Image.plural(original.favorite_count, 'like')).color(:red) if original.favorite_count.positive?),
234
234
  ((Image.number(original.retweet_count) - Image.plural(original.retweet_count, 'RT')).color(:green) if original.retweet_count.positive?),
235
235
  ].compact.intersperse(Image.whitespace).reduce(Image.empty, :-)
@@ -263,6 +263,11 @@ module Twterm
263
263
  end
264
264
  end
265
265
 
266
+ # for the sake of Twterm::Tab::Searchable
267
+ def search_query_window
268
+ app.search_query_window
269
+ end
270
+
266
271
  def sort
267
272
  return if items.empty? || scroller.current_item.nil?
268
273
 
@@ -1,4 +1,3 @@
1
- require 'twterm/event/screen/resize'
2
1
  require 'twterm/publisher'
3
2
  require 'twterm/subscriber'
4
3
  require 'twterm/utils'
@@ -82,16 +81,17 @@ module Twterm
82
81
  left <= x && x < right && top <= y && y < bottom
83
82
  end
84
83
 
85
- def initialize(app, client)
84
+ # @param app [Twterm::App]
85
+ # @param client [Twterm::Client]
86
+ # @param window [Curses::Window]
87
+ def initialize(app, client, window)
86
88
  @app, @client = app, client
87
89
 
88
90
  @tabs = []
89
91
  @index = 0
90
92
  @history = []
91
93
 
92
- @window = Curses.stdscr.subwin(1, Curses.stdscr.maxx, 0, 0)
93
-
94
- subscribe(Event::Screen::Resize, :resize)
94
+ @window = window
95
95
  end
96
96
 
97
97
  # Open the clicked tab
@@ -266,10 +266,5 @@ module Twterm
266
266
 
267
267
  nil
268
268
  end
269
-
270
- def resize(_event)
271
- @window.resize(1, Curses.stdscr.maxx)
272
- @window.move(0, 0)
273
- end
274
269
  end
275
270
  end
@@ -1,3 +1,3 @@
1
1
  module Twterm
2
- VERSION = '2.9.0'
2
+ VERSION = '2.10.0'
3
3
  end
data/nix/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'twterm'
3
+ gem 'twterm', '2.9.0'
data/nix/Gemfile.lock CHANGED
@@ -5,57 +5,64 @@ GEM
5
5
  public_suffix (>= 2.0.2, < 5.0)
6
6
  buftok (0.2.0)
7
7
  citrus (3.0.2)
8
- concurrent-ruby (1.0.5)
9
- curses (1.3.2)
8
+ concurrent-ruby (1.1.8)
9
+ curses (1.4.0)
10
10
  domain_name (0.5.20190701)
11
11
  unf (>= 0.0.5, < 1.0.0)
12
12
  equalizer (0.0.11)
13
- http (3.3.0)
13
+ ffi (1.14.2)
14
+ ffi-compiler (1.0.1)
15
+ ffi (>= 1.0.0)
16
+ rake
17
+ http (4.4.1)
14
18
  addressable (~> 2.3)
15
19
  http-cookie (~> 1.0)
16
- http-form_data (~> 2.0)
17
- http_parser.rb (~> 0.6.0)
20
+ http-form_data (~> 2.2)
21
+ http-parser (~> 1.2.0)
18
22
  http-cookie (1.0.3)
19
23
  domain_name (~> 0.5)
20
24
  http-form_data (2.3.0)
25
+ http-parser (1.2.3)
26
+ ffi-compiler (>= 1.0, < 2.0)
21
27
  http_parser.rb (0.6.0)
22
28
  idn-ruby (0.1.0)
23
- launchy (2.4.3)
24
- addressable (~> 2.3)
29
+ launchy (2.5.0)
30
+ addressable (~> 2.7)
25
31
  memoizable (0.4.2)
26
32
  thread_safe (~> 0.3, >= 0.3.1)
27
33
  multipart-post (2.1.1)
28
34
  naught (1.1.0)
29
- oauth (0.5.4)
30
- public_suffix (4.0.5)
35
+ oauth (0.5.5)
36
+ public_suffix (4.0.6)
37
+ rake (13.0.3)
31
38
  simple_oauth (0.3.1)
32
39
  terminal-notifier (2.0.0)
33
40
  thread_safe (0.3.6)
34
- toml-rb (0.3.15)
41
+ toml-rb (2.0.1)
35
42
  citrus (~> 3.0, > 3.0)
36
- twitter (6.2.0)
43
+ twitter (7.0.0)
37
44
  addressable (~> 2.3)
38
45
  buftok (~> 0.2.0)
39
46
  equalizer (~> 0.0.11)
40
- http (~> 3.0)
47
+ http (~> 4.0)
41
48
  http-form_data (~> 2.0)
42
49
  http_parser.rb (~> 0.6.0)
43
50
  memoizable (~> 0.4.0)
44
51
  multipart-post (~> 2.0)
45
52
  naught (~> 1.0)
46
53
  simple_oauth (~> 0.3.0)
47
- twitter-text (2.1.0)
54
+ twitter-text (3.1.0)
48
55
  idn-ruby
49
56
  unf (~> 0.1.0)
50
- twterm (2.8.0)
51
- concurrent-ruby (~> 1.0.5)
52
- curses (~> 1.3.2)
53
- launchy (~> 2.4.3)
57
+ twterm (2.9.0)
58
+ concurrent-ruby (~> 1.1.7)
59
+ curses (~> 1.4.0)
60
+ launchy (~> 2.5.0)
54
61
  oauth (~> 0.5.1)
55
62
  terminal-notifier (~> 2.0.0)
56
- toml-rb (~> 0.3.14)
57
- twitter (~> 6.2.0)
58
- twitter-text (~> 2.1.0)
63
+ toml-rb (~> 2.0.1)
64
+ twitter (~> 7.0.0)
65
+ twitter-text (~> 3.1.0)
59
66
  unf (0.1.4)
60
67
  unf_ext
61
68
  unf_ext (0.0.7.7)
@@ -64,7 +71,7 @@ PLATFORMS
64
71
  ruby
65
72
 
66
73
  DEPENDENCIES
67
- twterm
74
+ twterm (= 2.9.0)
68
75
 
69
76
  BUNDLED WITH
70
77
  2.1.4
data/nix/gemset.nix CHANGED
@@ -35,20 +35,20 @@
35
35
  platforms = [];
36
36
  source = {
37
37
  remotes = ["https://rubygems.org"];
38
- sha256 = "183lszf5gx84kcpb779v6a2y0mx9sssy8dgppng1z9a505nj1qcf";
38
+ sha256 = "0mr23wq0szj52xnj0zcn1k0c7j4v79wlwbijkpfcscqww3l6jlg3";
39
39
  type = "gem";
40
40
  };
41
- version = "1.0.5";
41
+ version = "1.1.8";
42
42
  };
43
43
  curses = {
44
44
  groups = ["default"];
45
45
  platforms = [];
46
46
  source = {
47
47
  remotes = ["https://rubygems.org"];
48
- sha256 = "0hic9kq09dhh8jqjx3k1991rnqhlj3glz82w0g7ndcri52m1hgqg";
48
+ sha256 = "0i4j6j18ih6lx7gk9jg2p7q8iswc897mgzn5m62jbf0zv0f7mkji";
49
49
  type = "gem";
50
50
  };
51
- version = "1.3.2";
51
+ version = "1.4.0";
52
52
  };
53
53
  domain_name = {
54
54
  dependencies = ["unf"];
@@ -71,16 +71,37 @@
71
71
  };
72
72
  version = "0.0.11";
73
73
  };
74
+ ffi = {
75
+ groups = ["default"];
76
+ platforms = [];
77
+ source = {
78
+ remotes = ["https://rubygems.org"];
79
+ sha256 = "15hgiy09i8ywjihyzyvjvk42ivi3kmy6dm21s5sgg9j7y3h3zkkx";
80
+ type = "gem";
81
+ };
82
+ version = "1.14.2";
83
+ };
84
+ ffi-compiler = {
85
+ dependencies = ["ffi" "rake"];
86
+ groups = ["default"];
87
+ platforms = [];
88
+ source = {
89
+ remotes = ["https://rubygems.org"];
90
+ sha256 = "0c2caqm9wqnbidcb8dj4wd3s902z15qmgxplwyfyqbwa0ydki7q1";
91
+ type = "gem";
92
+ };
93
+ version = "1.0.1";
94
+ };
74
95
  http = {
75
- dependencies = ["addressable" "http-cookie" "http-form_data" "http_parser.rb"];
96
+ dependencies = ["addressable" "http-cookie" "http-form_data" "http-parser"];
76
97
  groups = ["default"];
77
98
  platforms = [];
78
99
  source = {
79
100
  remotes = ["https://rubygems.org"];
80
- sha256 = "1jlm5prw437wqpfxcigh88lfap3m7g8mnmj5as7qw6dzqnvrxwmc";
101
+ sha256 = "0z8vmvnkrllkpzsxi94284di9r63g9v561a16an35izwak8g245y";
81
102
  type = "gem";
82
103
  };
83
- version = "3.3.0";
104
+ version = "4.4.1";
84
105
  };
85
106
  http-cookie = {
86
107
  dependencies = ["domain_name"];
@@ -103,6 +124,17 @@
103
124
  };
104
125
  version = "2.3.0";
105
126
  };
127
+ http-parser = {
128
+ dependencies = ["ffi-compiler"];
129
+ groups = ["default"];
130
+ platforms = [];
131
+ source = {
132
+ remotes = ["https://rubygems.org"];
133
+ sha256 = "18qqvckvqjffh88hfib6c8pl9qwk9gp89w89hl3f2s1x8hgyqka1";
134
+ type = "gem";
135
+ };
136
+ version = "1.2.3";
137
+ };
106
138
  "http_parser.rb" = {
107
139
  groups = ["default"];
108
140
  platforms = [];
@@ -129,10 +161,10 @@
129
161
  platforms = [];
130
162
  source = {
131
163
  remotes = ["https://rubygems.org"];
132
- sha256 = "190lfbiy1vwxhbgn4nl4dcbzxvm049jwc158r2x7kq3g5khjrxa2";
164
+ sha256 = "1xdyvr5j0gjj7b10kgvh8ylxnwk3wx19my42wqn9h82r4p246hlm";
133
165
  type = "gem";
134
166
  };
135
- version = "2.4.3";
167
+ version = "2.5.0";
136
168
  };
137
169
  memoizable = {
138
170
  dependencies = ["thread_safe"];
@@ -170,20 +202,30 @@
170
202
  platforms = [];
171
203
  source = {
172
204
  remotes = ["https://rubygems.org"];
173
- sha256 = "1zszdg8q1b135z7l7crjj234k4j0m347hywp5kj6zsq7q78pw09y";
205
+ sha256 = "1m08365nyp0fgw2iyzj8q8qy8zml0c1hw2dd8cp82pp6656ahbh3";
174
206
  type = "gem";
175
207
  };
176
- version = "0.5.4";
208
+ version = "0.5.5";
177
209
  };
178
210
  public_suffix = {
179
211
  groups = ["default"];
180
212
  platforms = [];
181
213
  source = {
182
214
  remotes = ["https://rubygems.org"];
183
- sha256 = "0vywld400fzi17cszwrchrzcqys4qm6sshbv73wy5mwcixmrgg7g";
215
+ sha256 = "1xqcgkl7bwws1qrlnmxgh8g4g9m10vg60bhlw40fplninb3ng6d9";
216
+ type = "gem";
217
+ };
218
+ version = "4.0.6";
219
+ };
220
+ rake = {
221
+ groups = ["default"];
222
+ platforms = [];
223
+ source = {
224
+ remotes = ["https://rubygems.org"];
225
+ sha256 = "1iik52mf9ky4cgs38fp2m8r6skdkq1yz23vh18lk95fhbcxb6a67";
184
226
  type = "gem";
185
227
  };
186
- version = "4.0.5";
228
+ version = "13.0.3";
187
229
  };
188
230
  simple_oauth = {
189
231
  groups = ["default"];
@@ -221,10 +263,10 @@
221
263
  platforms = [];
222
264
  source = {
223
265
  remotes = ["https://rubygems.org"];
224
- sha256 = "03sr3k193i1r5bh9g4zc7iq9jklapmwj0rndcvhr9q7v5xm7x4rf";
266
+ sha256 = "0x5j95w28vj85bzw98g1dyd4gm7xpli2fdvwwrgwlay7gb3wc5jh";
225
267
  type = "gem";
226
268
  };
227
- version = "0.3.15";
269
+ version = "2.0.1";
228
270
  };
229
271
  twitter = {
230
272
  dependencies = ["addressable" "buftok" "equalizer" "http" "http-form_data" "http_parser.rb" "memoizable" "multipart-post" "naught" "simple_oauth"];
@@ -232,10 +274,10 @@
232
274
  platforms = [];
233
275
  source = {
234
276
  remotes = ["https://rubygems.org"];
235
- sha256 = "0fjyz3viabz3xs5d9aad18zgdbhfwm51jsnzigc8kxk77p1x58n5";
277
+ sha256 = "13dmkjgsnym1avym9f7y2i2h3mlk8crqvc87drrzr4f0sf9l8g2y";
236
278
  type = "gem";
237
279
  };
238
- version = "6.2.0";
280
+ version = "7.0.0";
239
281
  };
240
282
  twitter-text = {
241
283
  dependencies = ["idn-ruby" "unf"];
@@ -243,10 +285,10 @@
243
285
  platforms = [];
244
286
  source = {
245
287
  remotes = ["https://rubygems.org"];
246
- sha256 = "1igv713wn6wqhq4nlr81r93v7wmgjqny24jwp3ai5i4ipk2f2k6a";
288
+ sha256 = "1dnmp0bj3l01nbb52zby2c7hrazcdwfg846knkrjdfl0yfmv793z";
247
289
  type = "gem";
248
290
  };
249
- version = "2.1.0";
291
+ version = "3.1.0";
250
292
  };
251
293
  twterm = {
252
294
  dependencies = ["concurrent-ruby" "curses" "launchy" "oauth" "terminal-notifier" "toml-rb" "twitter" "twitter-text"];
@@ -254,10 +296,10 @@
254
296
  platforms = [];
255
297
  source = {
256
298
  remotes = ["https://rubygems.org"];
257
- sha256 = "075rq11axsz41hcrmm6ixjyy0kz3axf0mhkvq3cgryqib2isjbk9";
299
+ sha256 = "16jbad4d5g8xf5gphlzf1ip7yih1xdvj2aqn9sb3xhy2vssb5y0c";
258
300
  type = "gem";
259
301
  };
260
- version = "2.8.0";
302
+ version = "2.9.0";
261
303
  };
262
304
  unf = {
263
305
  dependencies = ["unf_ext"];
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Twterm::Image::Bold do
4
+ let(:string_image) { Twterm::Image::StringImage.new(str) }
5
+ let(:str) { 'Hello' }
6
+
7
+ describe '#height' do
8
+ subject { image.height }
9
+
10
+ let(:image) { described_class.new(string_image) }
11
+
12
+ it { is_expected.to eq string_image.height }
13
+ end
14
+
15
+ describe '#to_s' do
16
+ subject { image.to_s }
17
+
18
+ let(:image) { described_class.new(string_image) }
19
+
20
+ it { is_expected.to eq "\e[1mHello\e[0m" }
21
+ end
22
+
23
+ describe '#width' do
24
+ subject { image.width }
25
+
26
+ let(:image) { described_class.new(string_image) }
27
+
28
+ it { is_expected.to eq string_image.width }
29
+ end
30
+ end
@@ -4,6 +4,14 @@ RSpec.describe Twterm::Image::Color do
4
4
  let(:string_image) { Twterm::Image::StringImage.new(str) }
5
5
  let(:str) { 'Hello' }
6
6
 
7
+ describe '#height' do
8
+ subject { image.height }
9
+
10
+ let(:image) { described_class.new(string_image, :red) }
11
+
12
+ it { is_expected.to eq string_image.height }
13
+ end
14
+
7
15
  describe '#to_s' do
8
16
  subject { image.to_s }
9
17
 
@@ -19,4 +27,12 @@ RSpec.describe Twterm::Image::Color do
19
27
  it { is_expected.to eq "\e[47m\e[31mHello\e[0m" }
20
28
  end
21
29
  end
30
+
31
+ describe '#width' do
32
+ subject { image.width }
33
+
34
+ let(:image) { described_class.new(string_image, :red) }
35
+
36
+ it { is_expected.to eq string_image.width }
37
+ end
22
38
  end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Twterm::Image::Dim do
4
+ let(:string_image) { Twterm::Image::StringImage.new(str) }
5
+ let(:str) { 'Hello' }
6
+
7
+ describe '#height' do
8
+ subject { image.height }
9
+
10
+ let(:image) { described_class.new(string_image) }
11
+
12
+ it { is_expected.to eq string_image.height }
13
+ end
14
+
15
+ describe '#to_s' do
16
+ subject { image.to_s }
17
+
18
+ let(:image) { described_class.new(string_image) }
19
+
20
+ it { is_expected.to eq "\e[2mHello\e[0m" }
21
+ end
22
+
23
+ describe '#width' do
24
+ subject { image.width }
25
+
26
+ let(:image) { described_class.new(string_image) }
27
+
28
+ it { is_expected.to eq string_image.width }
29
+ end
30
+ end
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: 2.9.0
4
+ version: 2.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryota Kameoka
@@ -254,7 +254,6 @@ files:
254
254
  - lib/twterm/event/open_photo.rb
255
255
  - lib/twterm/event/open_uri.rb
256
256
  - lib/twterm/event/screen/refresh.rb
257
- - lib/twterm/event/screen/resize.rb
258
257
  - lib/twterm/event/status/abstract_status_event.rb
259
258
  - lib/twterm/event/status/mention.rb
260
259
  - lib/twterm/event/status_deleted.rb
@@ -268,11 +267,13 @@ files:
268
267
  - lib/twterm/friendship.rb
269
268
  - lib/twterm/hashtag.rb
270
269
  - lib/twterm/image.rb
270
+ - lib/twterm/image/attr.rb
271
271
  - lib/twterm/image/between.rb
272
272
  - lib/twterm/image/blank_line.rb
273
273
  - lib/twterm/image/bold.rb
274
274
  - lib/twterm/image/brackets.rb
275
275
  - lib/twterm/image/color.rb
276
+ - lib/twterm/image/dim.rb
276
277
  - lib/twterm/image/empty.rb
277
278
  - lib/twterm/image/horizontal_sequential_image.rb
278
279
  - lib/twterm/image/parens.rb
@@ -368,13 +369,14 @@ files:
368
369
  - spec/supports/shared_examples/abstract_key_mapper.rb
369
370
  - spec/twterm/completer/search_query_completer_spec.rb
370
371
  - spec/twterm/config_spec.rb
371
- - spec/twterm/event/screen/resize_spec.rb
372
372
  - spec/twterm/event_dispatcher_spec.rb
373
373
  - spec/twterm/extension/enumerator/lazy_spec.rb
374
374
  - spec/twterm/friendship_spec.rb
375
375
  - spec/twterm/image/blank_line_spec.rb
376
+ - spec/twterm/image/bold_spec.rb
376
377
  - spec/twterm/image/brackets_spec.rb
377
378
  - spec/twterm/image/color_spec.rb
379
+ - spec/twterm/image/dim_spec.rb
378
380
  - spec/twterm/image/empry_spec.rb
379
381
  - spec/twterm/image/horizontal_sequential_image_spec.rb
380
382
  - spec/twterm/image/parens_spec.rb
@@ -1,13 +0,0 @@
1
- require 'twterm/event/abstract_event'
2
-
3
- module Twterm
4
- module Event
5
- module Screen
6
- class Resize < AbstractEvent
7
- def fields
8
- { lines: Integer, cols: Integer }
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,11 +0,0 @@
1
- require 'spec_helper'
2
- require 'twterm/event/screen/resize'
3
-
4
- RSpec.describe Twterm::Event::Screen::Resize do
5
- describe '#fields' do
6
- it 'has fields of Integer * Integer' do
7
- expect { described_class.new(5, 10) }.not_to raise_error
8
- expect { described_class.new('hello', 'world') }.to raise_error
9
- end
10
- end
11
- end