twterm 2.5.0 → 2.9.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 +18 -0
- data/README.md +30 -4
- data/bin/twterm +1 -3
- data/default.nix +21 -0
- data/gemset.nix +5130 -0
- data/lib/twterm/app.rb +0 -18
- data/lib/twterm/client.rb +1 -6
- data/lib/twterm/color_manager.rb +8 -9
- data/lib/twterm/image.rb +26 -0
- data/lib/twterm/image/underlined.rb +31 -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 -5
- 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 +54 -14
- data/lib/twterm/search_query_window.rb +4 -5
- data/lib/twterm/status.rb +10 -0
- data/lib/twterm/tab/abstract_tab.rb +33 -8
- data/lib/twterm/tab/new/index.rb +0 -10
- data/lib/twterm/tab/new/list.rb +3 -3
- 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/status_tab.rb +10 -0
- data/lib/twterm/tab/statuses/abstract_statuses_tab.rb +4 -4
- 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 -5
- 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 +70 -0
- data/nix/gemset.nix +283 -0
- data/shell.nix +40 -0
- data/twterm.gemspec +13 -13
- metadata +42 -44
- 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/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/lib/twterm/app.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
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
6
|
require 'twterm/event/screen/resize'
|
@@ -10,7 +9,6 @@ require 'twterm/notification_dispatcher'
|
|
10
9
|
require 'twterm/persistable_configuration_proxy'
|
11
10
|
require 'twterm/preferences'
|
12
11
|
require 'twterm/photo_viewer'
|
13
|
-
require 'twterm/repository/direct_message_repository'
|
14
12
|
require 'twterm/repository/friendship_repository'
|
15
13
|
require 'twterm/repository/hashtag_repository'
|
16
14
|
require 'twterm/repository/list_repository'
|
@@ -42,14 +40,6 @@ module Twterm
|
|
42
40
|
@completion_manager ||= CompletionManager.new(self)
|
43
41
|
end
|
44
42
|
|
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
43
|
def friendship_repository
|
54
44
|
@friendship_repository ||= Repository::FriendshipRepository.new
|
55
45
|
end
|
@@ -89,8 +79,6 @@ module Twterm
|
|
89
79
|
|
90
80
|
publish(Event::Screen::Refresh.new)
|
91
81
|
|
92
|
-
client.connect_user_stream
|
93
|
-
|
94
82
|
reset_interruption_handler
|
95
83
|
|
96
84
|
Signal.trap(:WINCH) { on_resize }
|
@@ -105,11 +93,6 @@ module Twterm
|
|
105
93
|
user_repository.expire(3600)
|
106
94
|
end
|
107
95
|
|
108
|
-
direct_message_repository.before_create do |dm|
|
109
|
-
user_repository.create(dm.recipient)
|
110
|
-
user_repository.create(dm.sender)
|
111
|
-
end
|
112
|
-
|
113
96
|
user_repository.before_create do |user|
|
114
97
|
client_id = client.user_id
|
115
98
|
|
@@ -181,7 +164,6 @@ module Twterm
|
|
181
164
|
config[:access_token_secret],
|
182
165
|
{
|
183
166
|
friendship: friendship_repository,
|
184
|
-
direct_message: direct_message_repository,
|
185
167
|
hashtag: hashtag_repository,
|
186
168
|
list: list_repository,
|
187
169
|
status: status_repository,
|
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
@@ -7,6 +7,7 @@ require 'twterm/image/empty'
|
|
7
7
|
require 'twterm/image/horizontal_sequential_image'
|
8
8
|
require 'twterm/image/parens'
|
9
9
|
require 'twterm/image/string_image'
|
10
|
+
require 'twterm/image/underlined'
|
10
11
|
require 'twterm/image/vertical_sequential_image'
|
11
12
|
|
12
13
|
class Twterm::Image
|
@@ -14,6 +15,10 @@ class Twterm::Image
|
|
14
15
|
@column, @line = column, line
|
15
16
|
end
|
16
17
|
|
18
|
+
def _
|
19
|
+
underlined
|
20
|
+
end
|
21
|
+
|
17
22
|
def !
|
18
23
|
bold
|
19
24
|
end
|
@@ -101,6 +106,27 @@ class Twterm::Image
|
|
101
106
|
StringImage.new(str)
|
102
107
|
end
|
103
108
|
|
109
|
+
# @param items [Array<Symbol>]
|
110
|
+
# @param selected [Symbol]
|
111
|
+
#
|
112
|
+
# @return [Image]
|
113
|
+
def self.toggle_switch(items, selected)
|
114
|
+
items
|
115
|
+
.map do |item|
|
116
|
+
on = item == selected
|
117
|
+
string(item.to_s)
|
118
|
+
.bold(on)
|
119
|
+
.underlined(on)
|
120
|
+
end
|
121
|
+
.intersperse(string(' | '))
|
122
|
+
.reduce(empty) { |acc, x| acc - x }
|
123
|
+
.brackets
|
124
|
+
end
|
125
|
+
|
126
|
+
def underlined(on = true)
|
127
|
+
on ? Underlined.new(self) : self
|
128
|
+
end
|
129
|
+
|
104
130
|
def self.whitespace
|
105
131
|
string(' ')
|
106
132
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Twterm
|
2
|
+
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
|
+
|
18
|
+
def to_s
|
19
|
+
"\e[4m#{image}\e[0m"
|
20
|
+
end
|
21
|
+
|
22
|
+
def width
|
23
|
+
image.width
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :image
|
29
|
+
end
|
30
|
+
end
|
31
|
+
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
|
data/lib/twterm/list.rb
CHANGED
@@ -1,7 +1,41 @@
|
|
1
1
|
module Twterm
|
2
|
+
# A Twitter list
|
2
3
|
class List
|
3
|
-
|
4
|
+
# Unique ID of the list
|
5
|
+
#
|
6
|
+
# @return [Integer]
|
7
|
+
attr_reader :id
|
4
8
|
|
9
|
+
# @return [String]
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
attr_reader :slug
|
14
|
+
|
15
|
+
# @return [String]
|
16
|
+
attr_reader :full_name
|
17
|
+
|
18
|
+
attr_reader :mode
|
19
|
+
|
20
|
+
# @return [String]
|
21
|
+
attr_reader :description
|
22
|
+
|
23
|
+
# The number of users that are in this list
|
24
|
+
#
|
25
|
+
# @return [Integer]
|
26
|
+
attr_reader :member_count
|
27
|
+
|
28
|
+
# The number of users that subscribe this list
|
29
|
+
#
|
30
|
+
# @return [Integer]
|
31
|
+
attr_reader :subscriber_count
|
32
|
+
|
33
|
+
# @return [String]
|
34
|
+
attr_reader :url
|
35
|
+
|
36
|
+
# @param other [List]
|
37
|
+
#
|
38
|
+
# @return [Boolean]
|
5
39
|
def ==(other)
|
6
40
|
other.is_a?(self.class) && id == other.id
|
7
41
|
end
|
@@ -11,6 +45,7 @@ module Twterm
|
|
11
45
|
update!(list)
|
12
46
|
end
|
13
47
|
|
48
|
+
# @return [self]
|
14
49
|
def update!(list)
|
15
50
|
@name = list.name
|
16
51
|
@slug = list.slug
|
@@ -5,11 +5,10 @@ require 'twterm/event/screen/resize'
|
|
5
5
|
module Twterm
|
6
6
|
class MessageWindow
|
7
7
|
include Singleton
|
8
|
-
include Curses
|
9
8
|
include Subscriber
|
10
9
|
|
11
10
|
def initialize
|
12
|
-
@window = stdscr.subwin(1, stdscr.maxx, stdscr.maxy -
|
11
|
+
@window = Curses.stdscr.subwin(1, Curses.stdscr.maxx, Curses.stdscr.maxy - 1, 0)
|
13
12
|
@queue = Queue.new
|
14
13
|
|
15
14
|
subscribe(Event::Message::AbstractMessage) do |e|
|
@@ -34,7 +33,7 @@ module Twterm
|
|
34
33
|
|
35
34
|
def show(message = nil)
|
36
35
|
loop do
|
37
|
-
break unless closed?
|
36
|
+
break unless Curses.closed?
|
38
37
|
sleep 0.5
|
39
38
|
end
|
40
39
|
|
@@ -74,8 +73,8 @@ module Twterm
|
|
74
73
|
end
|
75
74
|
|
76
75
|
def resize(_event)
|
77
|
-
@window.resize(1, stdscr.maxx)
|
78
|
-
@window.move(stdscr.maxy -
|
76
|
+
@window.resize(1, Curses.stdscr.maxx)
|
77
|
+
@window.move(Curses.stdscr.maxy - 1, 0)
|
79
78
|
end
|
80
79
|
end
|
81
80
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'toml'
|
1
|
+
require 'toml-rb'
|
2
2
|
|
3
3
|
module Twterm
|
4
4
|
class PersistableConfigurationProxy
|
@@ -32,16 +32,16 @@ module Twterm
|
|
32
32
|
# @param [String] filepath File path to load configuration from
|
33
33
|
# @return [Twterm::PersistableConfigurationProxy] a configuration proxy
|
34
34
|
def self.load_from_file!(klass, filepath)
|
35
|
-
config =
|
35
|
+
config = TomlRB.load_file(filepath, symbolize_keys: true)
|
36
36
|
new(klass.new(config), filepath).migrate!
|
37
37
|
rescue Errno::ENOENT
|
38
38
|
new(klass.default, filepath)
|
39
|
-
rescue
|
39
|
+
rescue TomlRB::ParseError, TomlRB::ValueOverwriteError => e
|
40
40
|
msg =
|
41
41
|
case e
|
42
|
-
when
|
42
|
+
when TomlRB::ParseError
|
43
43
|
"Your configuration file could not be parsed"
|
44
|
-
when
|
44
|
+
when TomlRB::ValueOverwriteError
|
45
45
|
"`#{e.key}` is declared more than once"
|
46
46
|
end
|
47
47
|
|
@@ -75,7 +75,7 @@ Press any key to continue
|
|
75
75
|
attr_reader :filepath, :instance
|
76
76
|
|
77
77
|
def persist!
|
78
|
-
hash =
|
78
|
+
hash = TomlRB.dump(instance.to_h).gsub("\n[", "\n\n[")
|
79
79
|
File.open(filepath, 'w', 0644) { |f| f.write(hash) }
|
80
80
|
end
|
81
81
|
end
|
data/lib/twterm/preferences.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'toml'
|
1
|
+
require 'toml-rb'
|
2
2
|
|
3
3
|
require 'twterm/abstract_persistable_configuration'
|
4
4
|
|
@@ -27,6 +27,9 @@ module Twterm
|
|
27
27
|
# @return [Twterm::Preferences] an instance having the default value
|
28
28
|
def self.default
|
29
29
|
new({
|
30
|
+
control: {
|
31
|
+
scroll_direction: 'traditional',
|
32
|
+
},
|
30
33
|
photo_viewer_backend: {
|
31
34
|
browser: true,
|
32
35
|
imgcat: false,
|
@@ -48,8 +51,12 @@ module Twterm
|
|
48
51
|
# @return [Hash]
|
49
52
|
def self.structure
|
50
53
|
bool = -> x { x == true || x == false }
|
54
|
+
scroll_direction = -> x { x == 'natural' || x == 'traditional' }
|
51
55
|
|
52
56
|
{
|
57
|
+
control: {
|
58
|
+
scroll_direction: scroll_direction
|
59
|
+
},
|
53
60
|
photo_viewer_backend: {
|
54
61
|
browser: bool,
|
55
62
|
imgcat: bool,
|
data/lib/twterm/rest_client.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
require 'concurrent'
|
2
|
-
require 'twterm/direct_message'
|
3
|
-
require 'twterm/direct_message_manager'
|
4
2
|
require 'twterm/publisher'
|
5
3
|
require 'twterm/event/message/success'
|
6
4
|
|
@@ -25,33 +23,6 @@ module Twterm
|
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
|
-
def create_direct_message(recipient, text)
|
29
|
-
send_request do
|
30
|
-
rest_client.create_direct_message(recipient.id, text)
|
31
|
-
end.then do |message|
|
32
|
-
msg = direct_message_repository.create(message)
|
33
|
-
direct_message_manager.add(recipient.id, msg)
|
34
|
-
publish(Event::DirectMessage::Fetched.new)
|
35
|
-
publish(Event::Message::Success.new('Your message to @%s has been sent' % recipient.screen_name))
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def direct_message_conversations
|
40
|
-
direct_message_manager.conversations
|
41
|
-
end
|
42
|
-
|
43
|
-
def direct_messages_received
|
44
|
-
send_request do
|
45
|
-
rest_client.direct_messages(count: 200).map { |dm| direct_message_repository.create(dm) }
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def direct_messages_sent
|
50
|
-
send_request do
|
51
|
-
rest_client.direct_messages_sent(count: 200).map { |dm| direct_message_repository.create(dm) }
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
26
|
def destroy_status(status)
|
56
27
|
send_request_without_catch do
|
57
28
|
rest_client.destroy_status(status.id)
|
@@ -424,10 +395,6 @@ module Twterm
|
|
424
395
|
|
425
396
|
private
|
426
397
|
|
427
|
-
def direct_message_manager
|
428
|
-
@direct_message_manager ||= DirectMessageManager.new(self)
|
429
|
-
end
|
430
|
-
|
431
398
|
def show_error
|
432
399
|
proc do |e|
|
433
400
|
case e
|