twterm 2.5.1 → 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 +4 -4
- data/.circleci/config.yml +62 -0
- data/.gitignore +1 -0
- data/Makefile +21 -0
- data/README.md +52 -6
- data/bin/twterm +1 -3
- data/default.nix +21 -0
- data/gemset.nix +4981 -0
- data/lib/twterm/app.rb +13 -26
- data/lib/twterm/client.rb +1 -6
- data/lib/twterm/color_manager.rb +8 -9
- data/lib/twterm/image.rb +31 -0
- data/lib/twterm/image/attr.rb +42 -0
- data/lib/twterm/image/bold.rb +7 -21
- data/lib/twterm/image/color.rb +9 -15
- data/lib/twterm/image/dim.rb +13 -0
- data/lib/twterm/image/underlined.rb +17 -0
- data/lib/twterm/image_builder/user_name_image_builder.rb +1 -0
- data/lib/twterm/key_mapper.rb +6 -8
- data/lib/twterm/key_mapper/abstract_key_mapper.rb +2 -2
- data/lib/twterm/list.rb +36 -1
- data/lib/twterm/message_window.rb +4 -13
- data/lib/twterm/persistable_configuration_proxy.rb +6 -6
- data/lib/twterm/preferences.rb +8 -1
- data/lib/twterm/rest_client.rb +0 -33
- data/lib/twterm/screen.rb +103 -25
- data/lib/twterm/search_query_window.rb +5 -13
- data/lib/twterm/status.rb +10 -0
- data/lib/twterm/tab/abstract_tab.rb +30 -16
- data/lib/twterm/tab/new/index.rb +0 -10
- data/lib/twterm/tab/new/search.rb +2 -2
- data/lib/twterm/tab/new/user.rb +2 -2
- data/lib/twterm/tab/preferences/control.rb +77 -0
- data/lib/twterm/tab/preferences/index.rb +6 -0
- data/lib/twterm/tab/scrollable.rb +1 -1
- data/lib/twterm/tab/searchable.rb +6 -4
- data/lib/twterm/tab/status_tab.rb +10 -0
- data/lib/twterm/tab/statuses/abstract_statuses_tab.rb +11 -6
- data/lib/twterm/tab/statuses/home.rb +0 -3
- data/lib/twterm/tab/statuses/mentions.rb +1 -0
- data/lib/twterm/tab/user_tab.rb +0 -9
- data/lib/twterm/tab_manager.rb +77 -10
- data/lib/twterm/tweetbox.rb +2 -3
- data/lib/twterm/user.rb +1 -0
- data/lib/twterm/version.rb +1 -1
- data/nix/Gemfile +3 -0
- data/nix/Gemfile.lock +77 -0
- data/nix/gemset.nix +325 -0
- data/shell.nix +40 -0
- data/spec/twterm/image/bold_spec.rb +30 -0
- data/spec/twterm/image/color_spec.rb +16 -0
- data/spec/twterm/image/dim_spec.rb +30 -0
- data/twterm.gemspec +13 -13
- metadata +46 -46
- data/.travis.yml +0 -12
- data/lib/twterm/direct_message.rb +0 -60
- data/lib/twterm/direct_message_composer.rb +0 -80
- data/lib/twterm/direct_message_manager.rb +0 -51
- data/lib/twterm/event/direct_message/fetched.rb +0 -10
- data/lib/twterm/event/notification/direct_message.rb +0 -30
- data/lib/twterm/event/screen/resize.rb +0 -13
- data/lib/twterm/event/status/timeline.rb +0 -10
- data/lib/twterm/repository/direct_message_repository.rb +0 -14
- data/lib/twterm/streaming_client.rb +0 -146
- data/lib/twterm/tab/direct_message/conversation.rb +0 -104
- data/lib/twterm/tab/direct_message/conversation_list.rb +0 -100
- data/spec/twterm/event/screen/resize_spec.rb +0 -11
data/lib/twterm/app.rb
CHANGED
@@ -1,16 +1,13 @@
|
|
1
1
|
require 'curses'
|
2
2
|
|
3
3
|
require 'twterm/completion_manager'
|
4
|
-
require 'twterm/direct_message_composer'
|
5
4
|
require 'twterm/environment'
|
6
5
|
require 'twterm/event/screen/refresh'
|
7
|
-
require 'twterm/event/screen/resize'
|
8
6
|
require 'twterm/message_window'
|
9
7
|
require 'twterm/notification_dispatcher'
|
10
8
|
require 'twterm/persistable_configuration_proxy'
|
11
9
|
require 'twterm/preferences'
|
12
10
|
require 'twterm/photo_viewer'
|
13
|
-
require 'twterm/repository/direct_message_repository'
|
14
11
|
require 'twterm/repository/friendship_repository'
|
15
12
|
require 'twterm/repository/hashtag_repository'
|
16
13
|
require 'twterm/repository/list_repository'
|
@@ -26,6 +23,12 @@ module Twterm
|
|
26
23
|
|
27
24
|
attr_reader :environment, :preferences, :screen
|
28
25
|
|
26
|
+
# return [Twterm::MessageWindow]
|
27
|
+
attr_reader :message_window
|
28
|
+
|
29
|
+
# return [Twterm::SearchQueryWindow]
|
30
|
+
attr_reader :search_query_window
|
31
|
+
|
29
32
|
DATA_DIR = "#{ENV['HOME']}/.twterm".freeze
|
30
33
|
|
31
34
|
def initialize
|
@@ -42,14 +45,6 @@ module Twterm
|
|
42
45
|
@completion_manager ||= CompletionManager.new(self)
|
43
46
|
end
|
44
47
|
|
45
|
-
def direct_message_composer
|
46
|
-
@direct_message_composer ||= DirectMessageComposer.new(self, client)
|
47
|
-
end
|
48
|
-
|
49
|
-
def direct_message_repository
|
50
|
-
@direct_messages_repository ||= Repository::DirectMessageRepository.new
|
51
|
-
end
|
52
|
-
|
53
48
|
def friendship_repository
|
54
49
|
@friendship_repository ||= Repository::FriendshipRepository.new
|
55
50
|
end
|
@@ -73,8 +68,8 @@ module Twterm
|
|
73
68
|
|
74
69
|
@screen = Screen.new(self, client)
|
75
70
|
|
76
|
-
SearchQueryWindow.
|
77
|
-
MessageWindow.
|
71
|
+
@search_query_window = SearchQueryWindow.new(screen.search_query_window_window)
|
72
|
+
@message_window = MessageWindow.new(screen.message_window_window)
|
78
73
|
|
79
74
|
@notification_dispatcher = NotificationDispatcher.new(preferences)
|
80
75
|
@photo_viewer = PhotoViewer.new(preferences)
|
@@ -89,8 +84,6 @@ module Twterm
|
|
89
84
|
|
90
85
|
publish(Event::Screen::Refresh.new)
|
91
86
|
|
92
|
-
client.connect_user_stream
|
93
|
-
|
94
87
|
reset_interruption_handler
|
95
88
|
|
96
89
|
Signal.trap(:WINCH) { on_resize }
|
@@ -105,11 +98,6 @@ module Twterm
|
|
105
98
|
user_repository.expire(3600)
|
106
99
|
end
|
107
100
|
|
108
|
-
direct_message_repository.before_create do |dm|
|
109
|
-
user_repository.create(dm.recipient)
|
110
|
-
user_repository.create(dm.sender)
|
111
|
-
end
|
112
|
-
|
113
101
|
user_repository.before_create do |user|
|
114
102
|
client_id = client.user_id
|
115
103
|
|
@@ -160,7 +148,7 @@ module Twterm
|
|
160
148
|
end
|
161
149
|
|
162
150
|
def tab_manager
|
163
|
-
@tab_manager ||= TabManager.new(self, client)
|
151
|
+
@tab_manager ||= TabManager.new(self, client, screen.tab_manager_window)
|
164
152
|
end
|
165
153
|
|
166
154
|
def tweetbox
|
@@ -181,7 +169,6 @@ module Twterm
|
|
181
169
|
config[:access_token_secret],
|
182
170
|
{
|
183
171
|
friendship: friendship_repository,
|
184
|
-
direct_message: direct_message_repository,
|
185
172
|
hashtag: hashtag_repository,
|
186
173
|
list: list_repository,
|
187
174
|
status: status_repository,
|
@@ -195,11 +182,11 @@ module Twterm
|
|
195
182
|
end
|
196
183
|
|
197
184
|
def on_resize
|
198
|
-
|
185
|
+
lines, cols = `stty size`.split(' ').map(&:to_i)
|
186
|
+
|
187
|
+
Readline.set_screen_size(lines, cols)
|
199
188
|
|
200
|
-
lines
|
201
|
-
cols = `tput cols`.to_i
|
202
|
-
publish(Event::Screen::Resize.new(lines, cols))
|
189
|
+
screen.resize(lines, cols) unless Curses.closed?
|
203
190
|
end
|
204
191
|
end
|
205
192
|
end
|
data/lib/twterm/client.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
require 'twterm/rest_client'
|
2
|
-
require 'twterm/streaming_client'
|
3
2
|
|
4
3
|
module Twterm
|
5
4
|
class Client
|
6
5
|
include RESTClient
|
7
|
-
include StreamingClient
|
8
6
|
|
9
7
|
attr_reader :user_id, :screen_name
|
10
8
|
|
@@ -13,7 +11,6 @@ module Twterm
|
|
13
11
|
@access_token, @access_token_secret = access_token, access_token_secret
|
14
12
|
|
15
13
|
@friendship_repository = repositories[:friendship]
|
16
|
-
@direct_message_repository = repositories[:direct_message]
|
17
14
|
@hashtag_repository = repositories[:hashtag]
|
18
15
|
@list_repository = repositories[:list]
|
19
16
|
@status_repository = repositories[:status]
|
@@ -29,12 +26,10 @@ module Twterm
|
|
29
26
|
muted_user_ids.include?(status.retweeted_status.user.id))
|
30
27
|
end
|
31
28
|
end
|
32
|
-
|
33
|
-
direct_message_manager
|
34
29
|
end
|
35
30
|
|
36
31
|
private
|
37
32
|
|
38
|
-
attr_reader :friendship_repository, :
|
33
|
+
attr_reader :friendship_repository, :hashtag_repository, :list_repository, :status_repository, :user_repository
|
39
34
|
end
|
40
35
|
end
|
data/lib/twterm/color_manager.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
module Twterm
|
2
2
|
class ColorManager
|
3
3
|
include Singleton
|
4
|
-
include Curses
|
5
4
|
|
6
5
|
COLORS = [:black, :white, :red, :green, :blue, :yellow, :cyan, :magenta, :transparent]
|
7
6
|
CURSES_COLORS = {
|
8
|
-
black: COLOR_BLACK,
|
9
|
-
white: COLOR_WHITE,
|
10
|
-
red: COLOR_RED,
|
11
|
-
green: COLOR_GREEN,
|
12
|
-
blue: COLOR_BLUE,
|
13
|
-
yellow: COLOR_YELLOW,
|
14
|
-
cyan: COLOR_CYAN,
|
15
|
-
magenta: COLOR_MAGENTA,
|
7
|
+
black: Curses::COLOR_BLACK,
|
8
|
+
white: Curses::COLOR_WHITE,
|
9
|
+
red: Curses::COLOR_RED,
|
10
|
+
green: Curses::COLOR_GREEN,
|
11
|
+
blue: Curses::COLOR_BLUE,
|
12
|
+
yellow: Curses::COLOR_YELLOW,
|
13
|
+
cyan: Curses::COLOR_CYAN,
|
14
|
+
magenta: Curses::COLOR_MAGENTA,
|
16
15
|
transparent: -1
|
17
16
|
}
|
18
17
|
|
data/lib/twterm/image.rb
CHANGED
@@ -3,10 +3,12 @@ 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'
|
9
10
|
require 'twterm/image/string_image'
|
11
|
+
require 'twterm/image/underlined'
|
10
12
|
require 'twterm/image/vertical_sequential_image'
|
11
13
|
|
12
14
|
class Twterm::Image
|
@@ -14,6 +16,10 @@ class Twterm::Image
|
|
14
16
|
@column, @line = column, line
|
15
17
|
end
|
16
18
|
|
19
|
+
def _
|
20
|
+
underlined
|
21
|
+
end
|
22
|
+
|
17
23
|
def !
|
18
24
|
bold
|
19
25
|
end
|
@@ -44,6 +50,10 @@ class Twterm::Image
|
|
44
50
|
Brackets.new(self)
|
45
51
|
end
|
46
52
|
|
53
|
+
def dim(on = true)
|
54
|
+
on ? Dim.new(self) : self
|
55
|
+
end
|
56
|
+
|
47
57
|
def self.checkbox(checked)
|
48
58
|
string(checked ? '*' : ' ').brackets
|
49
59
|
end
|
@@ -101,6 +111,27 @@ class Twterm::Image
|
|
101
111
|
StringImage.new(str)
|
102
112
|
end
|
103
113
|
|
114
|
+
# @param items [Array<Symbol>]
|
115
|
+
# @param selected [Symbol]
|
116
|
+
#
|
117
|
+
# @return [Image]
|
118
|
+
def self.toggle_switch(items, selected)
|
119
|
+
items
|
120
|
+
.map do |item|
|
121
|
+
on = item == selected
|
122
|
+
string(item.to_s)
|
123
|
+
.bold(on)
|
124
|
+
.underlined(on)
|
125
|
+
end
|
126
|
+
.intersperse(string(' | '))
|
127
|
+
.reduce(empty) { |acc, x| acc - x }
|
128
|
+
.brackets
|
129
|
+
end
|
130
|
+
|
131
|
+
def underlined(on = true)
|
132
|
+
on ? Underlined.new(self) : self
|
133
|
+
end
|
134
|
+
|
104
135
|
def self.whitespace
|
105
136
|
string(' ')
|
106
137
|
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
|
data/lib/twterm/image/bold.rb
CHANGED
@@ -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
|
-
|
23
|
-
image.width
|
24
|
-
end
|
10
|
+
protected
|
25
11
|
|
26
|
-
|
27
|
-
|
28
|
-
|
12
|
+
def attr
|
13
|
+
Curses::A_BOLD
|
14
|
+
end
|
29
15
|
end
|
30
16
|
end
|
31
17
|
end
|
data/lib/twterm/image/color.rb
CHANGED
@@ -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
|
-
|
6
|
-
end
|
7
|
-
|
8
|
-
def height
|
9
|
-
image.height
|
10
|
-
end
|
7
|
+
super(image)
|
11
8
|
|
12
|
-
|
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
|
-
|
33
|
-
|
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
|
data/lib/twterm/key_mapper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'toml'
|
1
|
+
require 'toml-rb'
|
2
2
|
require 'singleton'
|
3
3
|
|
4
4
|
require 'twterm/app'
|
@@ -105,14 +105,12 @@ module Twterm
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def load_dict_file!
|
108
|
-
dict =
|
109
|
-
rescue
|
108
|
+
dict = TomlRB.load_file(dict_file_path, symbolize_keys: true)
|
109
|
+
rescue TomlRB::ParseError => e
|
110
110
|
first_line =
|
111
111
|
case e
|
112
|
-
when
|
113
|
-
"Your key assignments dictionary file (#{dict_file_path}) could not be parsed"
|
114
|
-
when TOML::ValueOverwriteError
|
115
|
-
"Command `#{e.key}` is declared more than once"
|
112
|
+
when TomlRB::ParseError
|
113
|
+
"Your key assignments dictionary file (#{dict_file_path}) could not be parsed:\n#{e.message}"
|
116
114
|
end
|
117
115
|
|
118
116
|
warn <<-EOS
|
@@ -132,7 +130,7 @@ Press any key to continue
|
|
132
130
|
end
|
133
131
|
|
134
132
|
def save!(mappings)
|
135
|
-
dict =
|
133
|
+
dict = TomlRB.dump(mappings).gsub("\n[", "\n\n[")
|
136
134
|
File.open(dict_file_path, 'w', 0644) { |f| f.write(dict) }
|
137
135
|
end
|
138
136
|
end
|
@@ -35,8 +35,6 @@ module Twterm
|
|
35
35
|
|
36
36
|
def translate(key)
|
37
37
|
case key
|
38
|
-
when '!'..'}' then key
|
39
|
-
when /\A\^([A-Z]?)\Z/ then $1.ord - 'A'.ord + 1
|
40
38
|
when 'F1' then Curses::Key::F1
|
41
39
|
when 'F2' then Curses::Key::F2
|
42
40
|
when 'F3' then Curses::Key::F3
|
@@ -49,6 +47,8 @@ module Twterm
|
|
49
47
|
when 'F10' then Curses::Key::F10
|
50
48
|
when 'F11' then Curses::Key::F11
|
51
49
|
when 'F12' then Curses::Key::F12
|
50
|
+
when /\A\^([A-Z]?)\Z/ then $1.ord - 'A'.ord + 1
|
51
|
+
when '!'..'}' then key
|
52
52
|
else
|
53
53
|
raise NoSuchKey.new(key)
|
54
54
|
end
|