twterm 2.9.0 → 2.10.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: 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