twterm 1.0.9 → 1.0.10

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.
@@ -1,14 +1,16 @@
1
1
  module Twterm
2
2
  class Tweetbox
3
+ class EmptyTextError < StandardError; end
4
+ class InvalidCharactersError < StandardError; end
5
+ class TextTooLongError < StandardError; end
6
+
3
7
  include Singleton
4
8
  include Readline
5
9
  include Curses
6
10
 
7
- def initialize
8
- @status = ''
9
- end
10
-
11
11
  def compose(in_reply_to = nil)
12
+ @text = ''
13
+
12
14
  if in_reply_to.is_a? Status
13
15
  @in_reply_to = in_reply_to
14
16
  else
@@ -24,37 +26,39 @@ module Twterm
24
26
  thread = Thread.new do
25
27
  close_screen
26
28
 
27
- if @in_reply_to.nil?
29
+ if in_reply_to.nil?
28
30
  puts "\nCompose new tweet:"
29
31
  else
30
- puts "\nReply to @#{@in_reply_to.user.screen_name}'s tweet: \"#{@in_reply_to.text}\""
32
+ puts "\nReply to @#{in_reply_to.user.screen_name}'s tweet: \"#{in_reply_to.text}\""
31
33
  end
32
34
 
33
35
  CompletionManager.instance.set_default_mode!
34
36
 
35
37
  loop do
36
38
  loop do
37
- msg = @in_reply_to.nil? || !@status.empty? ? '> ' : "> @#{in_reply_to.user.screen_name} "
39
+ msg = in_reply_to.nil? || !text.empty? ? '> ' : "> @#{in_reply_to.user.screen_name} "
38
40
  line = (readline(msg, true) || '').strip
39
41
  break if line.empty?
40
42
 
41
43
  if line.end_with?('\\')
42
- @status << line.chop.lstrip + "\n"
44
+ @text << line.chop.rstrip + "\n"
43
45
  else
44
- @status << line
46
+ @text << line
45
47
  break
46
48
  end
47
49
  end
48
50
 
49
51
  puts "\n"
50
52
 
51
- case validate
52
- when :too_long
53
- puts "Status is too long (#{length} / 140 characters)"
54
- when :invalid_characters
55
- puts 'Status contains invalid characters'
56
- else
53
+ begin
54
+ validate_text!
57
55
  break
56
+ rescue EmptyTextError
57
+ break
58
+ rescue InvalidCharactersError
59
+ puts 'Text contains invalid characters'
60
+ rescue TextTooLongError
61
+ puts "Text is too long (#{text_length} / 140 characters)"
58
62
  end
59
63
 
60
64
  puts "\n"
@@ -68,30 +72,52 @@ module Twterm
68
72
  App.instance.register_interruption_handler do
69
73
  thread.kill
70
74
  clear
71
- puts "\ncanceled"
75
+ puts "\nCanceled"
72
76
  resetter.call
73
77
  end
74
78
 
75
79
  thread.join
76
80
  end
77
81
 
78
- def post
79
- return if validate
82
+ private
83
+
84
+ attr_reader :in_reply_to
80
85
 
81
- Client.current.post(@status, @in_reply_to)
86
+ def clear
87
+ @text = ''
88
+ @in_reply_to = nil
89
+ end
90
+
91
+ def post
92
+ validate_text!
93
+ Client.current.post(text, in_reply_to)
94
+ rescue EmptyTextError
95
+ # do nothing
96
+ rescue InvalidCharactersError
97
+ Notifier.instance.show_error 'Text contains invalid characters'
98
+ rescue TextTooLongError
99
+ Notifier.instance.show_error "Text is too long (#{text_length} / 140 characters)"
100
+ ensure
82
101
  clear
83
102
  end
84
103
 
85
- def validate
86
- Twitter::Validation.tweet_invalid?(@status)
104
+ def text
105
+ @text || ''
87
106
  end
88
107
 
89
- def length
90
- Twitter::Validation.tweet_length(@status)
108
+ def text_length
109
+ Twitter::Validation.tweet_length(text)
91
110
  end
92
111
 
93
- def clear
94
- @status = ''
112
+ def validate_text!
113
+ case Twitter::Validation.tweet_invalid?(text)
114
+ when :empty
115
+ fail EmptyTextError
116
+ when :invalid_characters
117
+ fail InvalidCharactersError
118
+ when :too_long
119
+ fail TextTooLongError
120
+ end
95
121
  end
96
122
  end
97
123
  end
data/lib/twterm/user.rb CHANGED
@@ -5,20 +5,12 @@ module Twterm
5
5
  :followers_count, :touched_at, :color
6
6
  alias_method :following?, :following
7
7
  alias_method :protected?, :protected
8
- class << self
9
- alias_method :create, :new
10
- end
11
8
 
12
9
  MAX_CACHED_TIME = 3600
13
10
  COLORS = [:red, :blue, :green, :cyan, :yellow, :magenta]
14
11
 
15
12
  @@instances = {}
16
13
 
17
- def self.new(user)
18
- instance = find(user.id)
19
- instance.nil? ? super : instance.update!(user)
20
- end
21
-
22
14
  def initialize(user)
23
15
  @id = user.id
24
16
  update!(user)
@@ -73,5 +65,10 @@ module Twterm
73
65
  user_ids = users.map(&:id)
74
66
  @@instances = user_ids.zip(users).to_h
75
67
  end
68
+
69
+ def self.new(user)
70
+ instance = find(user.id)
71
+ instance.nil? ? super : instance.update!(user)
72
+ end
76
73
  end
77
74
  end
@@ -1,3 +1,3 @@
1
1
  module Twterm
2
- VERSION = '1.0.9'
2
+ VERSION = '1.0.10'
3
3
  end
data/lib/twterm.rb CHANGED
@@ -3,6 +3,7 @@ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname
3
3
 
4
4
  require 'cgi'
5
5
  require 'curses'
6
+ require 'forwardable'
6
7
  require 'launchy'
7
8
  require 'oauth'
8
9
  require 'readline'
@@ -36,9 +37,10 @@ require 'twterm/tab_manager'
36
37
  require 'twterm/tab/base'
37
38
  require 'twterm/tab/dumpable'
38
39
  require 'twterm/tab/exceptions'
39
- require 'twterm/tab/scrollable'
40
+ require 'twterm/tab/scroll_manager'
40
41
  require 'twterm/tab/statuses_tab'
41
42
  require 'twterm/tab/conversation_tab'
43
+ require 'twterm/tab/key_assignments_cheatsheet'
42
44
  require 'twterm/tab/list_tab'
43
45
  require 'twterm/tab/mentions_tab'
44
46
  require 'twterm/tab/new/start'
@@ -55,6 +57,6 @@ require 'twterm/version'
55
57
 
56
58
  module Twterm
57
59
  class Conf
58
- REQUIRE_VERSION = '1.0.9'
60
+ REQUIRE_VERSION = '1.0.10'
59
61
  end
60
62
  end
@@ -0,0 +1,4 @@
1
+ ---
2
+ :access_token: token
3
+ :access_token_secret: secret
4
+ :screen_name: name
@@ -0,0 +1,7 @@
1
+ RSpec.configure do |config|
2
+ config.run_all_when_everything_filtered = true
3
+ config.filter_run :focus
4
+ config.order = :random
5
+ end
6
+
7
+ require 'twterm'
@@ -0,0 +1,34 @@
1
+ describe Twterm::Config do
2
+ MOCK_CONFIG_PATH = 'spec/resources/config'.freeze
3
+
4
+ let(:config) { described_class.new }
5
+
6
+ describe '#[]' do
7
+ it 'returns config value from config_file_path' do
8
+ allow(config).to receive(:config_file_path).and_return(MOCK_CONFIG_PATH)
9
+
10
+ expect(config[:access_token]).to eq 'token'
11
+ end
12
+ end
13
+
14
+ describe '#[]=' do
15
+ context 'when fail to load config file' do
16
+ it 'set new value to config file' do
17
+ allow(config).to receive(:config_file_path).and_return('invalid path')
18
+ allow(config).to receive(:save_config_to_file).and_return(nil)
19
+
20
+ expect(config[:access_token]).to be_nil
21
+ config[:access_token] = 'new_token'
22
+ expect(config[:access_token]).to eq 'new_token'
23
+ end
24
+ end
25
+
26
+ it 'can set some value' do
27
+ allow(config).to receive(:config_file_path).and_return(MOCK_CONFIG_PATH)
28
+ allow(config).to receive(:save_config_to_file).and_return(nil)
29
+
30
+ config[:access_token] = 'new_token'
31
+ expect(config[:access_token]).to eq 'new_token'
32
+ end
33
+ end
34
+ end
data/twterm.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |i| i == 'Gemfile.lock' }
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.require_paths = ['lib']
19
+ spec.required_ruby_version = '>= 2.1.0'
19
20
 
20
21
  spec.add_dependency 'curses', '>= 1.0.1'
21
22
  spec.add_dependency 'launchy', '>= 2.4.3'
@@ -26,4 +27,5 @@ Gem::Specification.new do |spec|
26
27
 
27
28
  spec.add_development_dependency 'bundler', '~> 1.8'
28
29
  spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'rspec', '~> 3.2.0'
29
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twterm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryota Kameoka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-20 00:00:00.000000000 Z
11
+ date: 2015-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '10.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 3.2.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 3.2.0
125
139
  description: A full-featured CLI Twitter client
126
140
  email:
127
141
  - kameoka.ryota@gmail.com
@@ -131,8 +145,9 @@ extensions: []
131
145
  extra_rdoc_files: []
132
146
  files:
133
147
  - ".gitignore"
148
+ - ".rspec"
134
149
  - Gemfile
135
- - LICENSE.txt
150
+ - LICENSE
136
151
  - README.md
137
152
  - Rakefile
138
153
  - bin/twterm
@@ -162,13 +177,14 @@ files:
162
177
  - lib/twterm/tab/dumpable.rb
163
178
  - lib/twterm/tab/exceptions.rb
164
179
  - lib/twterm/tab/favorites.rb
180
+ - lib/twterm/tab/key_assignments_cheatsheet.rb
165
181
  - lib/twterm/tab/list_tab.rb
166
182
  - lib/twterm/tab/mentions_tab.rb
167
183
  - lib/twterm/tab/new/list.rb
168
184
  - lib/twterm/tab/new/search.rb
169
185
  - lib/twterm/tab/new/start.rb
170
186
  - lib/twterm/tab/new/user.rb
171
- - lib/twterm/tab/scrollable.rb
187
+ - lib/twterm/tab/scroll_manager.rb
172
188
  - lib/twterm/tab/search_tab.rb
173
189
  - lib/twterm/tab/statuses_tab.rb
174
190
  - lib/twterm/tab/timeline_tab.rb
@@ -178,6 +194,9 @@ files:
178
194
  - lib/twterm/user.rb
179
195
  - lib/twterm/user_window.rb
180
196
  - lib/twterm/version.rb
197
+ - spec/resources/config
198
+ - spec/spec_helper.rb
199
+ - spec/twterm/config_spec.rb
181
200
  - twterm.gemspec
182
201
  homepage: http://twterm.ryota-ka.me/
183
202
  licenses:
@@ -191,7 +210,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
210
  requirements:
192
211
  - - ">="
193
212
  - !ruby/object:Gem::Version
194
- version: '0'
213
+ version: 2.1.0
195
214
  required_rubygems_version: !ruby/object:Gem::Requirement
196
215
  requirements:
197
216
  - - ">="
@@ -199,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
218
  version: '0'
200
219
  requirements: []
201
220
  rubyforge_project:
202
- rubygems_version: 2.4.5
221
+ rubygems_version: 2.4.7
203
222
  signing_key:
204
223
  specification_version: 4
205
224
  summary: A full-featured CLI Twitter client
@@ -1,130 +0,0 @@
1
- module Twterm
2
- module Tab
3
- module Scrollable
4
- include Base
5
-
6
- def initialize
7
- super
8
-
9
- @scrollable_index = 0
10
- @scrollable_count = 0
11
- @scrollable_offset = 0
12
- @scrollable_last = 0
13
- @scrollable_scrollbar_length = 0
14
- end
15
-
16
- def respond_to_key(key)
17
- case key
18
- when 'g'
19
- move_to_top
20
- when 'G'
21
- move_to_bottom
22
- when 'j', 14, Key::DOWN
23
- move_down
24
- when 'k', 16, Key::UP
25
- move_up
26
- when 'd', 4
27
- 10.times { move_down }
28
- when 'u', 21
29
- 10.times { move_up }
30
- else
31
- return false
32
- end
33
- true
34
- end
35
-
36
- def index
37
- @scrollable_index
38
- end
39
-
40
- def count
41
- @scrollable_count
42
- end
43
-
44
- def offset
45
- @scrollable_offset
46
- end
47
-
48
- def last
49
- @scrollable_last
50
- end
51
-
52
- def item_prepended
53
- @scrollable_index += 1
54
- @scrollable_offset += 1
55
- update_scrollbar_length
56
- end
57
-
58
- def item_appended
59
- @scrollable_index -= 1
60
- @scrollable_offset -= 1 if @scrollable_offset > 0
61
- update_scrollbar_length
62
- end
63
-
64
- def move_up
65
- return if count == 0 || index == 0
66
-
67
- @scrollable_index = [index - 1, 0].max
68
- @scrollable_offset = [offset - 1, 0].max if index - 4 < offset
69
- refresh
70
- end
71
-
72
- def move_down
73
- return if count == 0 || index == count - 1
74
-
75
- @scrollable_index = [index + 1, count - 1].min
76
- @scrollable_offset = [
77
- offset + 1,
78
- count - 1,
79
- count - offset_from_bottom
80
- ].min if index > last - 4
81
-
82
- refresh
83
- end
84
-
85
- def move_to_top
86
- return if count == 0 || index == 0
87
-
88
- @scrollable_index = 0
89
- @scrollable_offset = 0
90
- refresh
91
- end
92
-
93
- def move_to_bottom
94
- return if count == 0 || index == count - 1
95
-
96
- @scrollable_index = count - 1
97
- @scrollable_offset = count - 1 - offset_from_bottom
98
- refresh
99
- end
100
-
101
- def offset_from_bottom
102
- 0
103
- end
104
-
105
- def update_scrollbar_length
106
- @scrollable_scrollbar_length =
107
- if count == 0
108
- 0
109
- else
110
- height = @window.maxy
111
- [height * (last - offset + 1) / count, 1].max
112
- end
113
- end
114
-
115
- def draw_scroll_bar
116
- return if count == 0
117
-
118
- height = @window.maxy
119
- top = height * index / count
120
-
121
- @window.with_color(:black, :white) do
122
- @scrollable_scrollbar_length.times do |i|
123
- @window.setpos(top + i, @window.maxx - 1)
124
- @window.addch(' ')
125
- end
126
- end
127
- end
128
- end
129
- end
130
- end